不确定为什么toupper()会切断C中的最后一个字母

所以这个程序的目标基本上是在终端(通过argv[])中获取一个 26 个字母的“键”,并使用它的索引作为替代指南。因此,您在终端中输入了 2 个输入,一个在 the 中argv[],一个只是普通get_string()输入。该argv[]输入将是这样的:./s YTNSHKVEFXRBAUQZCLWDMIPGJO这里s是文件名。然后get_string()输入如下所示:plaintext: HELLO。(输入是HELLO)。然后程序将循环遍历纯文本输入中的所有字母,并根据键的索引替换其字母索引argv[]。例如,H有一个按字母顺序排列的索引7(其中a= 0 和z= 25),因此我们查看键中的第 7 个索引YTNSHKV(E)FXRBAUQZCLWDMIPGJO,在本例中为E. 它对输入中的每个字母执行此操作,我们将得到输出ciphertext: EHBBQ。这是它在终端中的样子:

./s YTNSHKVEFXRBAUQZCLWDMIPGJO
plaintext:  HELLO
ciphertext: EHBBQ

但是我的输出是EHBB,因为当我使用toupper().

而且,大小写取决于明文输入,如果明文输入是hello, worldargv[]键是YTNSHKVEFXRBAUQZCLWDMIPGJO,则输出是jrssb, ybwsp,如果输入HellO, world具有相同的键,则输出是JrssB, ybwsp

我基本上已经解决了这个问题,我的程序根据通过命令行输入的密钥将给出的明文替换为正确的密文。现在,假设明文输入是HELLO,并且键是vchprzgjntlskfbdqwaxeuymoi(全部小写),那么它应该返回HELLO而不是hello。这是因为我的程序将命令行键中的所有字母放入长度为 26 的数组中,然后我遍历所有纯文本字母并将其 ascii 值(减去某个数字以使其进入 0-25 索引范围)与键中的索引。所以E有一个字母索引 4 所以在这种情况下我的程序会p变成小写,但我需要它P,所以这就是我使用toupper().

当我使用 时tolower(),一切正常,一旦我开始使用toupper(), 的最后一个字母ciphertext由于某种原因被切断了。这是我使用前的输出toupper()

ciphertext: EHBBQ

这是我使用后的输出toupper()

ciphertext: EHBB

这是我的代码:

int main(int argc, string argv[]) {
    string plaintext = get_string("plaintext: ");
    
    // Putting all the argv letters into an array called key
    char key[26]; // change 4 to 26
    for (int i = 0; i < 26; i++) // change 4 to 26
    {
        key[i] = argv[1][i];
    }
    
    // Assigning array called ciphertext, the length of the inputted text, to hold cipertext chars
    char ciphertext[strlen(plaintext)];
    
    // Looping through the inputted text, checking for upper and lower case letters
    for (int i = 0; i < strlen(plaintext); i++)
    {
        // The letter is lower case
        if (islower(plaintext[i]) != 0)
        {
            int asciiVal = plaintext[i] - 97; // Converting from ascii to decimal value and getting it into alphabetical index (0-25)
            char l = tolower(key[asciiVal]); // tolower() works properly
            //printf("%c", l);
            strncat(ciphertext, &l, 1); // Using strncat() to append the converted plaintext char to ciphertext
        }
        // The letter is uppercase
        else if (isupper(plaintext[i]) != 0)
        {
            int asciiVal = plaintext[i] - 65; // Converting from ascii to decimal value and getting it into alphabetical index (0-25)
            char u = toupper(key[asciiVal]);  // For some reason having this cuts off the last letter 
            strncat(ciphertext, &u, 1); // Using strncat() to append the converted plaintext char to ciphertext
        }
        // If its a space, comma, apostrophe, etc...
        else
        {
            strncat(ciphertext, &plaintext[i], 1);
        }
    }
    
    // prints out ciphertext output
    printf("ciphertext: ");
    for (int i = 0; i < strlen(plaintext); i++)
    {
        printf("%c", ciphertext[i]);
    }
    printf("n");
    printf("%cn", ciphertext[1]);
    printf("%cn", ciphertext[4]);
    //printf("%sn", ciphertext);
    return 0;
}

回答

strncat函数期望它的第一个参数是它附加到的以空字符结尾的字符串。你在ciphertext它未初始化时调用它。这意味着您正在读取未初始化的内存,可能会读取数组的末尾,触发未定义的行为。

ciphertext在调用strncat它之前,您需要创建一个空字符串。此外,您需要将此数组的大小加 1 以说明已完成字符串上的终止空字节,以防止写掉它的末尾。

char ciphertext[strlen(plaintext)+1];
ciphertext[0] = 0;

  • 附加建议:`plaintext` 需要在程序结束时释放。这就是为什么`#define`-ing 指针类型不是一个好主意的原因:它掩盖了指针。

以上是不确定为什么toupper()会切断C中的最后一个字母的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>