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

凯撒密码(Caesar cypher)调试:输出末尾出现问号与随机字符

凯撒密码代码乱码问题解决

问题现象

编写的C语言凯撒密码代码运行时,密文末尾会出现问号和随机字符,仅当输入为5个字符时功能正常。调整数组长度(将char cyphertext[x + 1];改为char cyphertext[x];)无法解决问题。

问题代码

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool only_digits(string s);
char rotate(char c, int n);

int main(int argc, string argv[])
{
    if (argc < 2 || only_digits(argv[1]) == false || argc > 2) // 检查输入合法性
    {
        printf("usage: ./caesasr key\n");
    }
    else
    {
        int key = atoi(argv[1]);
        string plaintext = get_string("plaintext: ");
        int x = strlen(plaintext);
        char cyphertext[x + 1];
        for (int i = 0; i < x; i++)
        {
            cyphertext[i] = rotate(plaintext[i], key);
        }
        printf("cyphertext: %s\n", cyphertext);
    }
}

// 检查输入是否为0-9的单个数字
bool only_digits(string s)
{
    if (s[0] > 47 && s[0] < 58 && strlen(s) == 1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

// 将字符c按凯撒密码规则偏移n位
// 大写字母公式:(cin -65 + n)%26 +65
// 小写字母公式:(cin -97 + n)%26 +97
// 非字母字符直接返回
char rotate(char c, int n)
{
    if (c > 64 && c < 91)
    {
        c = ((c - 65 + n) % 26 + 65);
    }
    if (c > 96 && c < 123)
    {
        c = ((c - 97 + n) % 26 + 97);
    }
    else
    {
        return c;
    }
    return c;
}

问题原因

C语言中,字符串必须以**空字符'\0'**作为结束标记。printf("%s", ...)会从起始地址开始读取字符,直到遇到'\0'才停止输出。当前代码中,cyphertext数组虽然分配了x+1的空间(足够容纳x个字符加结束符),但循环只填充了前x个字符,没有手动添加'\0',导致printf继续读取数组后面的随机内存数据,从而出现问号、乱码等异常字符。

输入恰好为5个字符时正常是偶然情况——此时数组后面的内存恰好存在一个'\0',属于未定义行为的巧合结果。

解决方法

在循环结束后,给cyphertext的第x个位置赋值为'\0',明确标记字符串结束:

for (int i = 0; i < x; i++)
{
    cyphertext[i] = rotate(plaintext[i], key);
}
// 添加结束符
cyphertext[x] = '\0';
printf("cyphertext: %s\n", cyphertext);

额外优化建议

  1. only_digits函数逻辑优化:当前仅允许单个数字作为密钥,实际凯撒密码的密钥可以是任意正整数,修改函数支持多位数输入:
bool only_digits(string s)
{
    for (int i = 0; s[i] != '\0'; i++)
    {
        if (!(s[i] >= '0' && s[i] <= '9'))
        {
            return false;
        }
    }
    return true;
}
  1. rotate函数逻辑优化:将双if改为else if让逻辑更严谨,同时用字符常量替代ASCII数值提升可读性:
char rotate(char c, int n)
{
    if (c >= 'A' && c <= 'Z')
    {
        c = ((c - 'A' + n) % 26 + 'A');
    }
    else if (c >= 'a' && c <= 'z')
    {
        c = ((c - 'a' + n) % 26 + 'a');
    }
    // 非字母直接返回原字符
    return c;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:27:22