c - how gets() work after scanf? [duplicate]

爱⌒轻易说出口 提交于 2021-02-04 05:10:39

问题


I have two questions:

  1. why only when i do space in "%d " --> scanf("%d ", &num); it works?

I tried fflush(stdin) \ _flushall() between the scnaf and the gets and it doesn't works, it skips the gets.

  1. When I do the space, it first does scanf then the gets and after that it print the number and print the string.
void main()
{
    char ch, str[10];
    int num;
    printf("Enter your number : ");
    scanf("%d ", &num);
    printf("%d\n",num);
    gets(str);
    puts(str);
    system("pause");
}

回答1:


  1. why only when i do space in "%d " --> scanf("%d ", &num); it works?

scanf("%d", &num); without a space after the "%d", stops scanning after reading a number. So with input 123Enter, the '\n' remains in stdin for the next input function like the now non-standard gets(). gets() reads that single '\n' and returns. By adding a space, scanf("%d ", &num); consumes the white-space after the number and does not return until non-white-scape is entered after the number.

  1. When I do the space, it first does scanf then the gets and after that it print the number and print the string.

By adding a space, scanf("%d ", &num); does not return until non-white-space is entered after the number (as in 'a' in the following). Since stdin is usually line buffered, this means input of 2 lines needs to first occur. 123Enter abcEnter.


Recommend to instead use fgets() to read a line of user input.

char str[10*2]; // no need for such a small buffer
int num;
printf("Enter your number : ");
fflush(stdout);
fgets(str, sizeof str, stdin);
sscanf(str, "%d", &num);
printf("%d\n",num);

printf("Enter data : ");
fflush(stdout);
fgets(str, sizeof str, stdin);
fputs(str, stdout);

More robust code would check the results of fgets(), sscanf() and use strtol() rather than sscanf().




回答2:


The C FAQ covers all these problems with scanf. See Why does everyone say not to use scanf? What should I use instead? and associated entries. Generally you'll use fgets followed by processing the resulting line such as with sscanf and checking that sscanf succeeded. This avoids leaving unparsed input and risking an infinite loop.

int number;
char line[255];

fgets( line, sizeof(line), stdin );
if( sscanf( line, "%d", &number ) != 1 ) {
    fputs("That doesn't look like a number.\n", stdin);
}

Note that fgets will read to a newline or as much as your buffer can hold. If the line is larger than your buffer, it might only read part of the line. Next read from input will get the rest of the line. There's ways to avoid this, such as the POSIX getline function, but at least you don't wind up in an infinite loop.

Let's decipher some comments.

Do not ever use gets. Use fgets.

The reason you don't use gets is because there's no way to limit how much is read from stdin. This means the user can overflow the buffer causing havoc.

char buffer[32];

// What the line is more than 31 characters?
gets(buffer);

fgets() takes the size of the buffer and will read that many characters at most. This prevents a buffer overflow.

char buffer[32];

// If there's more than 31 characters it will stop reading.
// The next read of stdin will get the rest of the line.
fgets( buffer, sizeof(buffer), stdin );

"There's no gets() function in C."

Yes, there is a gets() function in C.

Yes, there isn't a gets() function in C.

It depends on which C you're talking about.

Some people when they say "C" mean C11, the current standard. Others when they say "C" mean C99 the previous standard. Some still adhere to C90, the original standard. There is a gets() function in C90. It was deprecated in C99. It was removed from the language in C11.

C compilers and documentation lag very, very, very far behind the standard. Many are still working on full support of C99. If you work to C11 you're going to be very surprised by the lack of support. If you want your code to work on most any compiler, write to C99.

Anyway, don't use gets.



来源:https://stackoverflow.com/questions/46104371/c-how-gets-work-after-scanf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!