注意事項
凱撒密碼透過旋轉字母表來加密文字,保持數字和符號不變。它曾在古代用於加密機密資訊,但在今天的視角看來,它只是一個玩具密碼。
本文的目的不是推廣凱撒密碼,而是演示如何在英語的實現中使用 C++ 的特性。
目標
- 提供一種加密
char[]
、std::string
和檔案的方法。
- 這是透過一個使用迭代器工作的函式模板來實現的。
語言
C++11,C++ 語言標準的 2011 版本。
您的 C++ 編譯器必須支援 lambda 函式、基於範圍的
for()
迴圈和初始化列表,才能成功編譯本文中的原始碼片段以及附帶的完整程式。
引數與設計思路
程式的核心函式名為
caesar_cipher()
,它有四個引數:
姓名 |
描述 |
src_begin |
源的起始迭代器 |
src_end |
源的結束迭代器 |
dest_begin |
目標的起始迭代器 |
移位 |
一個表示字母表位移的整數 |
傳遞迭代器而不是實際容器的方法有兩個優點:
- 函式與容器無關。
- 函式的實現得到簡化。
使用示例
- 好的
1 2 3 4
|
std::string s("Hello, World!");
caesar_cipher(s.begin(), s.end(), s.begin(), 4); // s == "Lipps, Asvph!"
caesar_cipher(s.begin(), s.end(), s.begin(), -4); // s == "Hello, World!"
|
- 壞的
1 2 3 4 5
|
const std::vector<char> vc{'D', 'b', 'f', 't', 'b', 's'};
std::list<char> lc(vc.size());
caesar_cipher(vc.begin(), vc.end(), lc.begin(), -1);
// lc == std::list<char>({'C', 'a', 'e', 's', 'a', 'r'})
|
- 醜陋的
1 2 3 4 5
|
const char ca[]{"Sqjzanxwn!"};
std::unique_ptr<char[]> upca(new char[sizeof ca]);
caesar_cipher(std::begin(ca), std::end(ca), upca.get(), 4);
// std::strcmp(upca.get(), "Wunderbar!") == 0
|
核心函式原始碼
如果您需要處理檔案的完整程式,請跳到下一節。
備註
- 當字母表位移時,它會迴圈。這意味著對於長度為 26 的字母表,位移 27 與位移 1 相同,位移 52 與不位移相同。
- 第 11 行的目的是將
shift
截斷為可以在 std::rotate()
中使用的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
#include <algorithm>
#include <cctype>
#include <string>
template <typename InputIterator, typename OutputIterator>
OutputIterator caesar_cipher(InputIterator src_begin, InputIterator src_end, OutputIterator dest_begin, int shift)
{
const std::string ab("abcdefghijklmnopqrstuvwxyz"); // AlphaBet
std::string rot_ab(ab); // ROTated AlphaBet
shift %= static_cast<int> (ab.length());
if (shift < 0)
std::rotate(rot_ab.rbegin(), rot_ab.rbegin() - shift, rot_ab.rend());
else
std::rotate(rot_ab.begin(), rot_ab.begin() + shift, rot_ab.end());
return std::transform(src_begin, src_end, dest_begin, [ab, rot_ab](unsigned char c) -> char {
if (std::isalpha(c))
{
if (std::isupper(c))
return std::toupper(rot_ab.at(ab.find(std::tolower(c))));
return rot_ab.at(ab.find(c));
}
return c;
});
}
|
完整程式原始碼
請下載文章末尾的 ZIP 存檔附件。
有用連結
感謝
附件:[caesar.zip]