凯撒密码实现求助:如何将ASCII字符转换为0-25范围值以应用加密公式
修正凯撒密码代码的关键要点
我来帮你理清问题所在,一步步修正你的代码~
首先,先拆解你当前代码里的几个核心问题:
1. 多余且错误的convertedUppercase/convertedLowercase数组
你试图用这两个数组存储字母对应的0-25数值,但其实完全没必要——直接在处理每个字符时实时计算即可。而且你的赋值逻辑有问题:当i=26时,uppercase[26]是字符串的结束符'\0','\0' - 'A'会得到一个负数,这会污染数组内容,反而帮倒忙。直接删掉这部分代码就行。
2. 加密计算的逻辑错误
你现在的代码((p[i]) + k) % 26犯了一个关键错误:p[i]是字符的ASCII值(比如'A'是65,'a'是97),直接加k再模26得到的是0-25之间的数字,而不是加密后字符的ASCII值。按照CS50 Discord的提示,正确的步骤应该是:
凯撒密码公式
(p + k) % 26的前提是,明文字符p的取值范围为0-25(对应a-z或A-Z)
所以正确的计算流程应该是:
- 把原字符转换成0-25的数值(比如大写字母:
p[i] - 'A',小写字母:p[i] - 'a') - 应用公式计算加密后的数值:
(数值 + k) % 26 - 把数值转换回对应的ASCII字符(大写加'A',小写加'a')
3. 循环边界与字符串结束符问题
你的循环条件i <= n有问题,因为strlen(p)返回的是明文的字符长度,索引范围是0到n-1,i <= n会处理到p[n](也就是字符串结束符'\0'),可能导致异常。另外,加密后的字符串c最后必须手动添加'\0',否则printf会输出乱码。
修正后的完整代码
#include <stdio.h> #include <string.h> #include <ctype.h> int main() { char p[] = "HelloWorld"; // 示例明文 int k = 3; // 示例密钥 int n = strlen(p); char c[n + 1]; // 预留结束符位置 for (int i = 0; i < n; i++) { if (isalpha(p[i])) { if (isupper(p[i])) { // 大写字母处理:转0-25 → 加密 → 转回ASCII int num = p[i] - 'A'; c[i] = (num + k) % 26 + 'A'; } else { // 小写字母处理 int num = p[i] - 'a'; c[i] = (num + k) % 26 + 'a'; } } else { // 非字母字符直接保留(比如空格、标点) c[i] = p[i]; } } c[n] = '\0'; // 添加字符串结束符 printf("ciphertext: %s\n", c); return 0; }
额外提示
如果密钥k可能大于26或者是负数,可以先对k做一次模26处理,避免计算结果超出范围:
k = k % 26; if (k < 0) { k += 26; // 处理负数密钥的情况 }
这样代码就可以正确运行啦~
内容的提问来源于stack exchange,提问作者user17410586
相关产品推荐
相关产品推荐

