【问题标题】:Why does program terminate without taking input?为什么程序没有输入就终止?
【发布时间】:2021-07-03 21:20:27
【问题描述】:

这是我的程序示例:

#include <stdio.h>
void sum();
int main()
{
    char choice[4];
    do
    {
        sum();
        printf("\nDo You want to restart the program: yes or no:\n");
        fgets(choice, 4, stdin); //error point
    } while (choice[0] == 'y' || choice[0] == 'Y');
    printf("\nThanking You");
    return 0;
}
void sum()
{
    int a = 3, b = 4;
    printf("sum of two number is %d", a + b);
}

在这个程序中,只有在while 的第一次迭代中,它才会要求choice 中的输入,并且在下一次迭代中,程序会通过取choice 中的任何值自动终止。

以下是代码执行后的结果:

sum of two number is 7
Do You want to restart the program: yes or no:
yes
sum of two number is 7
Do You want to restart the program: yes or no:

Thanking You
[Program finished]

我无法理解它需要在choice 中输入,而我没有使用scanf()(它将换行符留在缓冲区中)。可能是它从可能是空格或其他字符的缓冲区中获取输入,但我不知道它来自哪里?

【问题讨论】:

    标签: arrays c string


    【解决方案1】:

    您的程序在第一次提示后在输入缓冲区中留下一个换行符,因为缓冲区中没有足够的空间。

    在第一次调用fgets 时,您输入字符串“yes”,后跟换行符。缓冲区的大小为 4,您将该大小传递给 fgets,因此它最多读取那么多字符 1 来解释终止的空字节。所以缓冲区中还剩下一个换行符。

    下次调用 fgets 时会立即读取该换行符。

    您应该扩大缓冲区以处理更多字符。

    【讨论】:

    • 但是如果我写 yes 那么它包含三个字符然后我按 enter 被 fgets() 转换为 NULL 字符,所以它变成了 4 个字符,没有数组小尺寸的机会。
    • @Suraj 不,没有将换行符转换为空值。如果您的缓冲区有空间容纳换行符,它将被包含在字符串中。使choice 5 或更多元素宽。
    • 谢谢 知道了。这意味着 fgets() 也可以采用换行符。如果是这样,那么这就是当我们打印一个字符串时,每个字符串的最后都会打印一个 \n 的原因。
    【解决方案2】:

    您的choice 数组不够大,无法容纳来自第一个循环的所有输入。 fgets 函数的第二个参数 (4) 告诉它读取 最多 3 个字符(然后在输入中附加一个 nul-终止符)。因此,它将换行符留在输入流中,并在第二个循环中读取(单独)。

    只需将您的 choice 数组大小和输入限制增加到 5(或更多):

    #include <stdio.h>
    void sum();
    int main()
    {
        char choice[5]; // Increase space for newline and nul
        do {
            sum();
            printf("\nDo You want to restart the program: yes or no:\n");
            fgets(choice, 5, stdin); // Inputs 'y', 'e', 's' and newline (4 chars) and appends a nul.
        } while (choice[0] == 'y' || choice[0] == 'Y');
        printf("\nThanking You");
        return 0;
    }
    void sum()
    {
        int a = 3, b = 4;
        printf("sum of two number is %d", a + b);
    }
    

    来自fgets - cppreference(我的粗体字):

    从给定的文件流中读取最多 count - 1 个字符,并且 将它们存储在 str 指向的字符数组中。解析停止如果 找到换行符,在这种情况下 str 将包含该 换行符,或者如果出现文件结尾。如果字节被读取并且没有 发生错误,立即在该位置写入一个空字符 在写入 str 的最后一个字符之后。

    【讨论】:

    • 我研究过 fgets() 将换行符转换为 NULL 字符,而 printf() 或 puts() 将那个 NULL 字符转换为换行符,对吗?
    • @Suraj。不,没有转换。在您的代码中,在第一个循环中不会读取换行符。一旦读取了 3 (4 - 1) 个字符,该函数将停止读取并将 nul 终止符附加到输入缓冲区。如果您只是键入“y”,然后按 ENTER 键,您的代码将起作用 - 输入将是一个包含“y”字符、换行符和 nul 终止符的缓冲区。
    • 是的,我明白了。但是我想知道,当我们打印一个字符串时,它总是会留下一个换行符,那么它背后的原因是什么。我们需要将零分配给数组的最后一个元素以避免换行符。
    • 好的,谢谢。明白了
    猜你喜欢
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2019-12-21
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    相关资源
    最近更新 更多