作者:
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]