使用printf打印随机文本时,为什么代码的输出会改变?

时间:2019-05-29 00:47:33

标签: c string printf

以下代码将输入的字母更改为k。 k是第一个参数。例如,如果输入应更改2个字母,则命令行参数将为“ ./caesar 2”,如果三个则为“ ./caesar 3”。等等 更改字母表示例如更改2,然后输入“ a”变为“ c”。改变3意味着输入“ abc”变为“ def”,依此类推。 正在检查用户提供的输入是否(a)数字参数是精确的2,(b)参数是数字。

在输出下方写入代码时执行的代码将缩短一个字母。例如,由1个字母更改的“ hello”变为“ iffm”。 如果仅输入一个字母,它将显示正确的输出,并跟随一些未定义的字母。例如,'a'变为“b��P”或“ bm>�”或“ b;���”。

在以下任一情况下(1)输入检查(b)[如果参数是数字]被删除,或(2)在get_string之间精确地插入带有随机语句(甚至可以是空字符串)的printf行功能,当询问用户输入和for循环时,当更改字母时,输出符合预期。或(3)如果输入的最后一个字符是特殊字符,则输出符合预期(特殊字符是任何非字母字符)。例如“ hello1”或“ hello!”更改一个字母将变成“ ifmmp1”或“ 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;
}

1 个答案:

答案 0 :(得分:1)

    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] = '\0';
    printf("ciphertext: %s\n", ciphertext);
}

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

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

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

如果我的明文为“ lol”,密钥为5,则“ i”等于3,密文为“ qtq”。 密文[i]会指向最后一个“ q”,因为我们从0开始算,这就是您要放置\ 0的地方。

您的getstring中也有错字。

希望您的解释很清楚,如果您有任何疑问,请问:)