为什么在使用 printf 打印随机文本时代码的输出会发生变化?

Why does the output of the code changes, when printing a random text with printf?

以下代码将输入的字母更改为 k。 k 是第一个参数。例如,如果输入应更改为 2 个字母,则命令行参数将为“./caesar 2”,如果为三个字母,则为“./caesar 3”。等等 换字母的意思是,比如换2,那么输入'a'就变成了'c'。改变 3 表示输入 "abc" 变为 "def",等等。 如果 (a) 数字参数是精确的 2,(b) 参数是数字,则正在检查用户提供的输入。

执行的代码如下所写代码输出缩短了一个字母。例如,"hello" 改变 1 个字母就变成了 "iffm"。 如果只输入一个字母,它会显示正确的输出,后面跟着一些未定义的字母。例如,'a' 变为 "b��P" 或 "bm>�" 或 "b;���"。

当 (1) 输入检查 (b) [如果参数是一个数字] 被删除或 (2) 带有随机语句(它甚至可以是空字符串)的 printf 行被完全插入两者之间get_string 函数,当要求用户输入和 for 循环时,当更改字母时,输出是预期的。或者 (3) 如果输入的最后一个字符是特殊字符,则输出符合预期(特殊字符是任何非字母字符)。例如,"hello1" or "hello!" 改变一个字母就变成 "ifmmp1" or "ifmmp!".

我真的很绝望,我不知道发生了什么,更重要的是,我不知道为什么会这样。 所以我的问题是: (1) 为什么输出缩短了一个字母?当输入只有一个字母时,为什么输出错误? (我想这是同样的问题)。 (2) (a) 为什么当删除数字检查或 (b) 随机 printf 行恰好插入上述行之间或 (c) 最后一个字符是非字母字符?

非常感谢任何帮助,请原谅任何奇怪的英语,因为它不是我的母语:)。非常感谢!绝望的代码学习者:)

这是代码:

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

bool isNumber(string numberToCheck);

int main(int argc, string argv[])
{
    // checking, if arguments are correct
    // checking, if input is correct (i.e. 2)
    if(argc != 2)
    {
        printf("Usage: ./cesar key\n");
        exit(1);
    }

    // checking, if input is a number, if the following if statement is removed the output changes
    if(!isNumber(argv[1]))
    {
        printf("Usage: ./caesar key\n");
        exit(1);
    }

    // variables
    int k = atoi(argv[1]);
    string plaintext;
    int plaintextLength;

    // getting the plaintext from user input, creating ciphertext string of same length
    plaintext = get_string("paintext: ");

    // checking the length of the input
    plaintextLength = strlen(plaintext);

    //the output changes, when the next line is being inserted
    printf("");

    // creating new empty string with plaintextLength
    char ciphertext[plaintextLength];

    // iterating through plaintext char by char
    for(int i = 0; i < plaintextLength;i++)
    {
        // in case of capital letter
        if(plaintext[i] >= 65 && plaintext[i] <= 90)
        {
            ciphertext[i] = 65 + (((plaintext[i] - 65) + k) % 26);
        } 
        // else in case of small letter
        else if(plaintext[i] >= 97 && plaintext[i] <= 122)
        {
            ciphertext[i] = 97 + (((plaintext[i] - 97) + k) % 26);
        }
        // else in case of non alphabetical letter
        else
        {
            ciphertext[i] = plaintext[i];
        }
    }
    printf("ciphertext: %s\n", ciphertext);
}

bool isNumber(string numberToCheck)
{
    for(int i = 0;i < strlen(numberToCheck); i++)
        {
            if(!isdigit(numberToCheck[i]))
            {
                return false;
            }
        }
    return true;
}
    int i;
    // iterating through plaintext char by char
    for(i = 0; i < plaintextLength;i++)
    {
        // in case of capital letter
        if(plaintext[i] >= 65 && plaintext[i] <= 90)
        {
            ciphertext[i] = 65 + (((plaintext[i] - 65) + k) % 26);
        } 
        // else in case of small letter
        else if(plaintext[i] >= 97 && plaintext[i] <= 122)
        {
            ciphertext[i] = 97 + (((plaintext[i] - 97) + k) % 26);
        }
        // else in case of non alphabetical letter
        else
        {
            ciphertext[i] = plaintext[i];
        }
    }
    ciphertext[i] = '[=10=]';
    printf("ciphertext: %s\n", ciphertext);
}

在 C 中,每个字符串都使用 \0 来告诉计算机它已到达字符串的末尾。

如果没有这个 NULL 终止运算符,计算机可能会尝试将字符串读入内存,这就是您遇到随机符号的原因。

因此,当您创建字符串时,请确保在其末尾添加 \0,这就是我在此处对您的代码所做的。 我在 for 循环外声明了 "i" 它不会在循环结束时停止存在。 当您到达循环的末尾时,"i" 将等于您的字符串的长度。

如果我的明文是"lol",密钥是5,那么"i"就等于3,密文就是"qtq"。 Ciphertext[i] 将指向最后一个 "q" 之后,因为我们从 0 开始计数,这是您要放置 \0.

的位置

您的 getstring 中也有错别字。

希望我的解释清楚,如果您有任何问题,请直接提问:)