C 为什么多个FGET需要大于sizeof(类型)的值

C 为什么多个FGET需要大于sizeof(类型)的值,c,input,fgets,C,Input,Fgets,我希望有人能帮助我解释使用多个FGET时的以下行为 以下代码起作用,用户需要为每个FGET输入一些内容: char input[1]; // to store a character fgets(input,3,stdin); // read a character from the keyboard char test[5];// for second fgets fgets(test,3,stdin); // to test if this asks for user input too

我希望有人能帮助我解释使用多个FGET时的以下行为

以下代码起作用,用户需要为每个FGET输入一些内容:

char input[1]; // to store a character
fgets(input,3,stdin); // read a character from the keyboard

char test[5];// for second fgets
fgets(test,3,stdin); // to test if this asks for user input too

printf("The character input is %c",input[0]);

==========OUTPUT============
Enter a character please: 
e
f
The character input is e
=============================
但是,以下代码仅允许用户输入第一个FGET的输入:

char input[1]; 
fgets(input,2,stdin); // THIS IS THE DIFFERENCE, USING 2 INSTEAD OF 3

char test[5];
fgets(test,3,stdin);

printf("The character input is %c",input[0]);
=====OUTPUT=============
Enter a character please: 
e
The character input is e
=========================
区别在于这一行:

fgets(input,2,stdin);
其中,使用少于3表示以下FGET不要求用户输入。 我认为这可能是因为对于大小3,当用户在输入字符后按Enter键时,当大小为3或更大时,第一个FGET会使用\n。 但是,如果大小小于3,则第一个FGET不会使用\n,将其保留在stdin上,因此第二个FGET会使用\n,这就是为什么第二个FGET会在不等待用户输入的情况下终止

如果我使用sizeof(char)作为该值,则得到输出:

=============OUTPUT============
Enter a character please: 
e
The character input is 
===============================
这很奇怪,因为我看到有人建议对该参数使用sizeof(type)


我希望有人能解释为什么需要3来使用\n,我希望2就足够了,例如,1字节用于字符,1字节用于使用\n,如果是这样的话,那么建议选择sizeof(type)是错误的,因为您需要sizeof(type)+1,但看起来您实际上需要sizeof(type)+2以允许使用\n并从stdin中删除。请帮助我理解这一点,谢谢

您有两个不同的问题:

第一种情况是写入超出数组
输入的界限,这会导致未定义的行为

对于第二个问题,当您告诉fgets
缓冲区的大小为
3
时,它将读取字符和换行符,并将两者添加到您提供的缓冲区中,并添加字符串空终止符。当您说大小为
2
时,它将读取字符而不是换行符,因为该大小包括字符串null终止符。这意味着下一个
fgets
调用将读取换行符并认为它是一个空行

通过使用足够大的缓冲区来容纳所有字符,再加上换行符和字符串空终止符,可以解决这些问题。对于单个字符,这意味着您的数组必须包含三个元素:

char input[3];
fgets(input, sizeof input, stdin);

作为可选解决方案,您可以读取单个字符(例如使用或)

然后,在读取换行符之前,您需要在循环中读取(但不要存储)字符

也许是这样的:

int input = getchar();

// Discard the rest of the line
for (int temp = getchar(); temp != '\n' && temp != EOF; temp = getchar())
{
    // Empty
}

您有两个不同的问题:

第一种情况是写入超出数组
输入的界限,这会导致未定义的行为

对于第二个问题,当您告诉fgets
缓冲区的大小为
3
时,它将读取字符和换行符,并将两者添加到您提供的缓冲区中,并添加字符串空终止符。当您说大小为
2
时,它将读取字符而不是换行符,因为该大小包括字符串null终止符。这意味着下一个
fgets
调用将读取换行符并认为它是一个空行

通过使用足够大的缓冲区来容纳所有字符,再加上换行符和字符串空终止符,可以解决这些问题。对于单个字符,这意味着您的数组必须包含三个元素:

char input[3];
fgets(input, sizeof input, stdin);

作为可选解决方案,您可以读取单个字符(例如使用或)

然后,在读取换行符之前,您需要在循环中读取(但不要存储)字符

也许是这样的:

int input = getchar();

// Discard the rest of the line
for (int temp = getchar(); temp != '\n' && temp != EOF; temp = getchar())
{
    // Empty
}
输入变量, 如果用户输入“new”这样的字符串,则会导致分段错误, 当值超过fgets中的字符时(输入,3,标准输入) stdin将忽略它们, 实际上,我无法说明这个fgets()背后的设计与char数组具有相同的值

输入变量, 如果用户输入“new”这样的字符串,则会导致分段错误, 当值超过fgets中的字符时(输入,3,标准输入) stdin将忽略它们,
实际上,我无法说明这个fgets()背后的设计与char数组具有相同的值。

谢谢您这么快的回复。然而,使用char输入[3]我仍然有相同的问题,那就是fgets(输入,2,stdin);仍然阻止以下FGET接受用户输入。如果我使用char输入[3]和fgets(输入,sizeof(char),stdin),然后输入说“e”,它根本不存储这是输入[0]。这就是为什么最好使用
fgets(输入,sizeof输入,stdin)
您需要“1字节用于字符,1字节用于使用
\n
,”1字节用于终止nul字符。请使用足够大的缓冲区。字母、换行符、空字节。需要三个字节。正常情况下,从
字符输入[2048]开始-如果需要,您可以随时将其变大。你必须在一个很小的系统上,2千磅才会成为一个问题。感谢Weather Vane和Jonathan Leffler,这听起来像是答案。这意味着必须使用fgets(输入,sizeof(char)+2,stdin);不,别那样玩。首先分配一个大的缓冲区。谢谢你这么快回复。然而,使用char输入[3]我仍然有相同的问题,那就是fgets(输入,2,stdin);仍然阻止以下FGET接受用户输入。如果我使用char输入[3]和fgets(输入,sizeof(char),stdin),然后输入说“e”,它根本不存储这是输入[0]。这就是为什么最好使用
fgets(输入,sizeof输入,stdin)
您需要“1字节用于字符,1字节用于使用
\n
,”1字节用于终止nul字符。请使用足够大的缓冲区。字母、换行符、空字节。需要三个字节。正常情况下,从
字符输入[2048]开始-如果需要,您可以随时将其变大。你必须在一个很小的系统上2千磅才能成为一个问题。多亏了Weather Vane和Jonathan Leffler,听起来像