Caesar cipher C语言如何实现加密解密?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 C语言 正文

凯撒密码是一种最简单的替换加密技术,它通过将明文中的每个字母替换为字母表中固定位置之后(或之前)的字母来实现加密。

caesar cipher c语言
(图片来源网络,侵删)

核心思想

  1. 密钥:一个整数 k,表示字母需要“移动”的位数。
  2. 加密:对于明文中的每一个字母,将其在字母表中的位置向后移动 k 位,如果移动后超出了 'Z' 或 'z',则从字母表的开头('A' 或 'a')继续。
    • 密钥 k=3,'A' -> 'D','B' -> 'E','X' -> 'A','y' -> 'b'。
  3. 解密:加密的逆过程,将密文中的每一个字母向前移动 k 位。
    • 密钥 k=3,'D' -> 'A','E' -> 'B','A' -> 'X','b' -> 'y'。

C 语言实现步骤

我们将编写一个 C 程序,它包含以下功能:

  1. 一个加密函数 caesar_encrypt
  2. 一个解密函数 caesar_decrypt
  3. 一个主函数 main 来演示如何使用这两个函数。

完整代码示例

下面是一个完整的、可运行的 C 语言程序。

#include <stdio.h>
#include <ctype.h> // 用于 isalpha(), isupper(), islower(), toupper(), tolower()
// 加密函数
void caesar_encrypt(char *text, int key) {
    // 遍历字符串中的每个字符
    for (int i = 0; text[i] != '\0'; i++) {
        // 检查字符是否是字母
        if (isalpha(text[i])) {
            // 确定是大写字母还是小写字母
            if (isupper(text[i])) {
                // 处理大写字母
                // 1. 转换为 0-25 的数字 (A=0, B=1, ..., Z=25)
                char original_pos = text[i] - 'A';
                // 2. 应用密钥并进行模 26 运算,防止溢出
                char new_pos = (original_pos + key) % 26;
                // 3. 将新数字转换回字母
                text[i] = 'A' + new_pos;
            } else {
                // 处理小写字母
                // 1. 转换为 0-25 的数字 (a=0, b=1, ..., z=25)
                char original_pos = text[i] - 'a';
                // 2. 应用密钥并进行模 26 运算
                char new_pos = (original_pos + key) % 26;
                // 3. 将新数字转换回字母
                text[i] = 'a' + new_pos;
            }
        }
        // 如果不是字母(如空格、标点符号),则不做处理,直接保留
    }
}
// 解密函数
void caesar_decrypt(char *text, int key) {
    // 解密就是加密的逆过程,即用 -key 进行加密
    // 为了处理负数,我们加上 26 再取模
    int decrypt_key = (-key) % 26;
    if (decrypt_key < 0) {
        decrypt_key += 26; // 确保密钥是正数
    }
    caesar_encrypt(text, decrypt_key);
}
int main() {
    char text[100];
    int key;
    // --- 加密演示 ---
    printf("凯撒密码加密演示\n");
    printf("请输入要加密的明文: ");
    fgets(text, sizeof(text), stdin); // 使用 fgets 安全地读取一行,包括空格
    printf("请输入密钥 (1-25): ");
    scanf("%d", &key);
    // 确保密钥在有效范围内
    key = key % 26;
    if (key <= 0) {
        key += 26; // 确保密钥是正数
    }
    // 加密前,先清除 fgets 可能留下的换行符
    text[strcspn(text, "\n")] = 0;
    printf("\n--- 加密过程 ---\n");
    printf("原始明文: %s\n", text);
    // 调用加密函数,注意 C 语言是传值,所以这里我们传递了字符串的地址
    // 为了在函数内修改原字符串,我们直接操作指针指向的内存
    // 为了不影响原数据,我们可以先复制一份
    char encrypted_text[100];
    strcpy(encrypted_text, text);
    caesar_encrypt(encrypted_text, key);
    printf("加密后密文: %s\n", encrypted_text);
    // --- 解密演示 ---
    printf("\n--- 解密过程 ---\n");
    printf("原始密文: %s\n", encrypted_text);
    char decrypted_text[100];
    strcpy(decrypted_text, encrypted_text);
    caesar_decrypt(decrypted_text, key);
    printf("解密后明文: %s\n", decrypted_text);
    return 0;
}

代码分步解析

头文件

#include <stdio.h>  // 用于输入输出函数,如 printf, scanf, fgets
#include <ctype.h>  // 用于字符处理函数,如 isalpha, isupper, islower

加密函数 caesar_encrypt(char *text, int key)

  • char *text: 这是一个指向字符数组的指针,也就是我们常说的字符串,在 C 语言中,字符串是以数组形式存储的,我们通过指针直接修改这个数组的内容。
  • int key: 加密密钥。
  • for (int i = 0; text[i] != '\0'; i++): 循环遍历字符串,直到遇到字符串结束符 \0
  • if (isalpha(text[i])): isalpha() 是一个标准库函数,检查当前字符是否是字母(A-Z, a-z),如果不是字母(比如空格、数字、标点),我们就跳过它,保持不变。
  • 大写字母处理:
    • char original_pos = text[i] - 'A';: 将字符 'A' 到 'Z' 映射到数字 0 到 25。'C' - 'A' = 2。
    • char new_pos = (original_pos + key) % 26;: 加上密钥,然后用 % 26(模26)取余,这是关键一步,确保了即使 key 很大(30),30 % 26 = 4,效果等同于移动 4 位,如果结果是 26 或更大,取模后会回到 0,实现了“循环”。
    • text[i] = 'A' + new_pos;: 将新的数字(0-25)转换回大写字母。'A' + 2 = 'C'。
  • 小写字母处理: 逻辑与大写字母完全相同,只是基准从 'A' 换成了 'a'。

解密函数 caesar_decrypt(char *text, int key)

  • 解密就是加密的逆操作,理论上,我们可以写一个几乎和加密一样的函数,只是用减法代替加法。
  • 但为了代码复用,我们直接调用 caesar_encrypt 函数,只是传入的密钥是 -key
  • int decrypt_key = (-key) % 26;: 计算负的密钥。
  • if (decrypt_key < 0) { decrypt_key += 26; }: C 语言的取模运算对于负数的结果可能因编译器而异,为了确保得到一个在 0-25 范围内的正数,如果结果是负数,我们加上 26,如果 key 是 3,-key % 26 可能是 -23,加上 26 后得到 3。key 是 5,-key % 26 是 -5,加上 26 后得到 21。encrypt(..., 21) 的效果和 decrypt(..., 5) 是一样的。

主函数 main()

  • char text[100];: 定义一个足够大的字符数组来存储用户输入。
  • fgets(text, sizeof(text), stdin);: 比 scanf 更安全的读取字符串的方式,因为它可以读取包含空格的整行,并且不会导致缓冲区溢出。
  • text[strcspn(text, "\n")] = 0;: fgets 会读取用户输入的换行符 \n 并存入字符串,这行代码找到换行符的位置并将其替换为字符串结束符 \0,这样字符串看起来更干净。
  • strcpy(encrypted_text, text);: 创建明文的副本进行加密,这样原始的 text 变量在解密时仍然可用。
  • 我们分别调用加密和解密函数,并打印结果,清晰地展示了整个过程。

如何编译和运行

  1. 将上面的代码保存为文件,caesar.c
  2. 打开终端或命令提示符。
  3. 使用 GCC 编译器进行编译:
    gcc caesar.c -o caesar
  4. 运行生成的可执行文件:
    ./caesar

示例运行:

凯撒密码加密演示
请输入要加密的明文: Hello World, this is a test!
请输入密钥 (1-25): 5
--- 加密过程 ---
原始明文: Hello World, this is a test!
加密后密文: Mjqqt Btwqi, ymnx nx f yjxy!
--- 解密过程 ---
原始密文: Mjqqt Btwqi, ymnx nx f yjxy!
解密后明文: Hello World, this is a test!

总结与改进

这个实现是凯撒密码的一个标准版本,你可以根据需要进行扩展:

caesar cipher c语言
(图片来源网络,侵删)
  • 文件加密/解密:修改 main 函数,让它从文件读取内容,加密/解密后再写回另一个文件。
  • 更友好的交互:创建一个循环菜单,让用户可以选择加密、解密或退出程序。
  • 处理非 ASCII 字符:当前的实现只处理英文字母,如果需要处理其他语言的字母(如带重音符号的法语字母),需要更复杂的逻辑。
  • 密钥安全性:凯撒密码非常容易被破解(暴力破解即可,因为只有 25 种可能的密钥),在实际应用中,绝不会使用如此简单的加密算法,它通常用于教学目的。
caesar cipher c语言
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
dede如何调用当前顶级栏目名称?
« 上一篇 昨天
dede v5.7如何调用当前登录会员信息?
下一篇 » 昨天

相关文章

取消
微信二维码
支付宝二维码

目录[+]