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

CS50替换程序printf输出异常:密文末尾出现多余字符

问题:替换程序密文末尾出现未知字符的原因

我正在完成哈佛大学CS50 2022年第2次作业的替换程序,以下是我的实现代码:

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

int main(int argc, string argv[1])
{
    if (argc > 2 || argc < 2){
        printf("Plz 1 word in command\n");
        return 1;
    }
    int sum = 0;
    string arg1 = argv[1];


    //test
    for (int i = 0; i < strlen(arg1); i++){
        if (isalpha(arg1[i]) == 0){
            printf("plz only alphabet character\n");
            return 1;
        }}
    // convert all key to upper
    for (int i = 0; i < strlen(arg1); i++){
        arg1[i] = toupper(arg1[i]);
     }
    for (int i = 0; i < strlen(arg1); i++){
          sum = sum + (int)(arg1[i]);
    }
    if (strlen(arg1) != 26){
        printf("Plz input 26 char\n");
        return 1;
    } else if (sum != 2015){printf("no oveerlapping letter plz\n");
    return 1; }
    //test finish
    string al = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    string pt = get_string("plaintext: ");
    char pt1[strlen(pt)]; 
    char cp[strlen(pt)]; 
    // all plain text to upper
    for (int i = 0; i < strlen(pt); i++){
        pt1[i]=toupper(pt[i]);
    }
    //scan
    for (int a = 0; a < strlen(pt); a++){
        char b = pt1[a];
        for (int i = 0; i < strlen(al); i++){
             if ( al[i] == b){
                   cp[a] = arg1[i];
                   break;
             } else {
                cp[a] = b;
             }
        }
    //case preserve
      if (islower(pt[a])){
         cp[a] = tolower(cp[a]);
    }} 

       printf("ciphertext: %s\n", cp);
       return 0;
}

当我输入密钥YTNSHKVEFXRBAUQZCLWDMIPGJO,并输入明文hello!1 lmao时,得到如下输出:

substitution/ $ ./substitution YTNSHKVEFXRBAUQZCLWDMIPGJO
plaintext: hello!1 lmao
ciphertext: ehbbq!1 bayq� 

预期输出应为ehbbq!1 bayq,但实际输出的密文末尾出现了多余的未知字符,请问该问题的原因是什么?


原因及解决方法

问题出在字符串结束符\0的缺失:

  • C语言中,所有字符串都必须以空字符\0作为结束标记,printf("%s")会持续读取内存直到遇到这个标记。
  • 你定义cp数组时,长度设为strlen(pt),刚好等于明文的字符数量,但没有预留存储\0的空间。填充完密文字符后,数组末尾没有结束符,导致printf读取到内存中的随机垃圾字符。

修复步骤:

  1. 修改cp数组的定义,预留一个字节给结束符:
    char cp[strlen(pt) + 1]; 
    
  2. 在填充完所有密文字符后,手动添加结束符:
    // 在printf之前添加
    cp[strlen(pt)] = '\0';
    

另外,你的pt1数组也存在同样的问题(没有结束符),虽然当前逻辑中没有直接用它作为字符串输出,但为了代码规范,建议同样修改为char pt1[strlen(pt) + 1];,并在填充后添加pt1[strlen(pt)] = '\0';。

额外提示:你用字符ASCII码之和判断密钥是否有重复字符的逻辑不可靠——不同的字符组合可能会得到相同的和(比如A+C与B+B的ASCII和都是132),建议改用数组标记已出现的字符来验证唯一性。


内容的提问来源于stack exchange,提问作者alksdhalksjdb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:15:37