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

(图片来源网络,侵删)
核心思想
- 密钥:一个整数
k,表示字母需要“移动”的位数。 - 加密:对于明文中的每一个字母,将其在字母表中的位置向后移动
k位,如果移动后超出了 'Z' 或 'z',则从字母表的开头('A' 或 'a')继续。- 密钥
k=3,'A' -> 'D','B' -> 'E','X' -> 'A','y' -> 'b'。
- 密钥
- 解密:加密的逆过程,将密文中的每一个字母向前移动
k位。- 密钥
k=3,'D' -> 'A','E' -> 'B','A' -> 'X','b' -> 'y'。
- 密钥
C 语言实现步骤
我们将编写一个 C 程序,它包含以下功能:
- 一个加密函数
caesar_encrypt。 - 一个解密函数
caesar_decrypt。 - 一个主函数
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变量在解密时仍然可用。- 我们分别调用加密和解密函数,并打印结果,清晰地展示了整个过程。
如何编译和运行
- 将上面的代码保存为文件,
caesar.c。 - 打开终端或命令提示符。
- 使用 GCC 编译器进行编译:
gcc caesar.c -o caesar
- 运行生成的可执行文件:
./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!
总结与改进
这个实现是凯撒密码的一个标准版本,你可以根据需要进行扩展:

(图片来源网络,侵删)
- 文件加密/解密:修改
main函数,让它从文件读取内容,加密/解密后再写回另一个文件。 - 更友好的交互:创建一个循环菜单,让用户可以选择加密、解密或退出程序。
- 处理非 ASCII 字符:当前的实现只处理英文字母,如果需要处理其他语言的字母(如带重音符号的法语字母),需要更复杂的逻辑。
- 密钥安全性:凯撒密码非常容易被破解(暴力破解即可,因为只有 25 种可能的密钥),在实际应用中,绝不会使用如此简单的加密算法,它通常用于教学目的。

(图片来源网络,侵删)
