作者:
2012年12月15日(最後更新:2013年1月5日)

凱撒密碼

評分:3.5/5(62票)
*****

注意事項

凱撒密碼透過旋轉字母表來加密文字,保持數字和符號不變。它曾在古代用於加密機密資訊,但在今天的視角看來,它只是一個玩具密碼。

本文的目的不是推廣凱撒密碼,而是演示如何在英語的實現中使用 C++ 的特性。

目標

  • 提供一種加密 char[]std::string 和檔案的方法。
  • 這是透過一個使用迭代器工作的函式模板來實現的。

語言

C++11,C++ 語言標準的 2011 版本。

您的 C++ 編譯器必須支援 lambda 函式、基於範圍的 for() 迴圈和初始化列表,才能成功編譯本文中的原始碼片段以及附帶的完整程式。

引數與設計思路

程式的核心函式名為 caesar_cipher(),它有四個引數:

姓名 描述
src_begin 源的起始迭代器
src_end 源的結束迭代器
dest_begin 目標的起始迭代器
移位 一個表示字母表位移的整數

傳遞迭代器而不是實際容器的方法有兩個優點:
  1. 函式與容器無關。
  2. 函式的實現得到簡化。

使用示例

  • 好的

    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]