为什么我的 Caesar 解决方案 (CS50) 会重复输入大写字符?

Why is my Caesar solution (CS50) double-typing uppercase characters?

我的程序可以正确地加密小写字母,但对于大写字母,输出将双打字符。例如,如果我输入“BARFOO”,我的程序将输出“EBDAURIFRORO”。代码如下所示。

printf("ciphertext: ");
for (int i = 0, n = strlen(plain); i < n; i++) 
{
    if (isalpha(plain[i]) && isupper(plain[i])) //problem must be here
    {
        int c = 65;
        printf("%c", (plain[i] - c + key) % 26 + c); 
    }
    
    if (isalpha(plain[i]) && islower(plain[i])) //this works
    {
        int c = 97;
        printf("%c", (plain[i] - c + key) % 26 + c);
    }
    
    else //this preserves punctuation, space, etc.
    {
        printf("%c", plain[i]);
    }
}
printf("\n");

我在第一个 if 循环中尝试做的是检查大写字母字符。然后我遍历每个字符,将其转换为字母索引,其中 'A' 在 [0] 处索引,B 在 [1] 处索引,依此类推。最后你可以看到我把它转换回了 Ascii 索引。为什么它只用大写字母这样做?我的数学错了吗?对于小写字母,数学原理基本相同,但它的行为应该如此。我假设这是我的 for 循环的问题,但我不确定我必须做些什么来改变它。

你的第一个“如果”是独立的。所以当输入是大写时,它会在第一个“if”中编码并显示,然后绕过并在“else”中显示,因为它不是大写。

你可以让“else”绕过每个非字母字符而不是绕过非小写字符来解决这个问题,像这样:

printf("ciphertext: ");
for (int i = 0, n = strlen(plain); i < n; i++)
{
    if (isalpha(plain[i]))
    {
        if(isupper(plain[i])) //problem must be here
        {
            int c = 65;
            printf("%c", (plain[i] - c + key) % 26 + c);
        }else{
            int c = 97;
            printf("%c", (plain[i] - c + key) % 26 + c);
        }

    }else //this preserves punctuation, space, etc.
    {
        printf("%c", plain[i]);
    }
}
printf("\n");