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

C语言使用toupper()实现替换密码时密文最后一位被截断问题

问题原因排查

你遇到的丢字符问题本质是未定义行为触发的栈内存异常,和toupper本身没有直接关系,之前用tolower没出问题只是巧合,具体问题点如下:

  • 第一个错误:strncat的入参要求目标必须是合法的、以\0结尾的C字符串。你声明char ciphertext[strlen(plaintext)];后没有做初始化,数组内全是栈上的随机垃圾值,strncat会从第一个找到的\0位置开始拼接,位置完全随机。你修改为toupper后改变了栈内存的布局,随机\0的位置发生变化,就触发了丢字符的现象。
  • 第二个错误:ciphertext数组长度不足。如果要存储和明文等长的密文字符,还要额外预留1个字节存储字符串结束符\0,你的数组长度只和明文长度相同,空间不够。
  • 冗余操作:完全不需要用strncat拼接单个字符,直接按索引给ciphertext的对应位置赋值即可,性能更高也不会触发字符串操作的异常。
修复后的代码示例
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <cs50.h> // get_string、string类型为CS50库提供,需引入对应头文件

int main(int argc, string argv[]) {
    // 前置参数合法性校验,避免非法输入崩溃
    if (argc != 2 || strlen(argv[1]) != 26) {
        printf("参数错误,请传入26位密钥\n");
        return 1;
    }
    
    string plaintext = get_string("plaintext: ");
    int plain_len = strlen(plaintext);
    char key[26];
    for (int i = 0; i < 26; i++)
    {
        key[i] = argv[1][i];
    }
    
    // 数组长度+1,预留结束符位置
    char ciphertext[plain_len + 1];
    
    // 直接按索引赋值,无需使用strncat
    for (int i = 0; i < plain_len; i++)
    {
        if (islower(plaintext[i]))
        {
            int idx = plaintext[i] - 'a';
            ciphertext[i] = tolower(key[idx]);
        }
        else if (isupper(plaintext[i]))
        {
            int idx = plaintext[i] - 'A';
            ciphertext[i] = toupper(key[idx]);
        }
        else
        {
            ciphertext[i] = plaintext[i];
        }
    }
    // 手动添加字符串结束符
    ciphertext[plain_len] = '\0';
    
    printf("ciphertext: %s\n", ciphertext);
    return 0;
}

使用你给出的密钥YTNSHKVEFXRBAUQZCLWDMIPGJO、明文HELLO测试,可正常输出预期密文EHBBQ。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:39:02