if (next_letter > 'z') {
next_letter = (next_letter - 26);
return next_letter;
}
你没有想到如果字符被签名会发生什么。测试它:
assert(rotate('z', 0) == 'z');
assert(rotate('z', 1) == 'a');
assert(rotate('z', 2) == 'b');
assert(rotate('z', 3) == 'c');
assert(rotate('z', 4) == 'd');
assert(rotate('z', 5) == 'e');
到目前为止还好,但现在:
assert(rotate('z', 6) == 'f');
Ascii“z”+5是127,“z”+6是128。但是,z+=6导致它为负,所以检查
> 'z'
失败。
建议简化:
bool isUpper(char ch) { return (ch >= 'A' && ch <= 'Z'); }
bool isLower(char ch) { return (ch >= 'a' && ch <= 'z'); }
char rotate(char ch, int offset) {
if (isLower(ch)) return (ch - 'a' + offset) % 26 + 'a';
if (isUpper(ch)) return (ch - 'A' + offset) % 26 + 'A';
return ch;
}
<cctype>
std::islower
和
std::isupper
.
Live On Coliru
#include <cctype>
#include <fstream>
#include <iostream>
#include <algorithm>
char rotate(char ch, int offset) {
if (std::islower(ch)) return (ch - 'a' + offset) % 26 + 'a';
if (std::isupper(ch)) return (ch - 'A' + offset) % 26 + 'A';
return ch;
}
std::string readFile(std::string const& fname) {
std::ifstream fin;
fin.exceptions(std::ios::failbit);
fin.open(fname);
return { std::istreambuf_iterator<char>(fin), {} };
}
int main() {
auto const original = readFile("main.cpp");
for (int offset = 0; offset < 26; ++offset) {
std::cout
<< "\n"
<< "=======================\n"
<< "Rotated by " << offset << " positions\n"
<< "=======================\n";
std::transform(
original.begin(), original.end(),
std::ostreambuf_iterator<char>(std::cout),
[offset](char ch) { return rotate(ch, offset); });
}
}
实际上,通过执行26次就地旋转,基本上可以避免复杂性:
Live On Coliru
auto text = readFile("main.cpp");
for (int offset = 0; offset < 26; ++offset) {
std::cout
<< "\n"
<< "=======================\n"
<< "Rotated by " << offset << " positions\n"
<< "=======================\n";
std::cout << text;
for (auto& ch : text) ch = rotate(ch, 1);
}