You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

凯撒密码实现求助:如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 14:17:34