3

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");
}
Sufian Latif
  • 13,086
  • 3
  • 33
  • 70
asaf
  • 119
  • 2
  • 10
  • 3
    `scanf("%d ", &num);` does not return until non-white space is entered after the number. – chux - Reinstate Monica Sep 07 '17 at 20:13
  • 8
    Do not *ever* use gets. You shouldn't worry about how it interacts with `scanf`, because you should *never* use it. – William Pursell Sep 07 '17 at 20:15
  • 2
    Also do not use `fflush(stdin)` – Ed Heal Sep 07 '17 at 20:16
  • 3
    Perhaps it might be useful to read the manual pages – Ed Heal Sep 07 '17 at 20:17
  • 5
    There's **no** `gets()` function in C. `main` must return `int`. – n. m. could be an AI Sep 07 '17 at 20:21
  • 1
    When saying "it works" and "it doesn't work", please provide the exact input, expected output, and actual output. – Weather Vane Sep 07 '17 at 20:21
  • The C FAQ covers all these problems with `scanf`. See [*Why does everyone say not to use scanf? What should I use instead?*](http://c-faq.com/stdio/scanfprobs.html) and associated entries. – Schwern Sep 07 '17 at 20:21
  • 1
    @n.m. "*7.19.7.7 The gets function*" unless you're subtly pointing out it's dangerous to use which newbies aren't going to understand. `void main` is technically correct because the standard allows for `main` to be defined "*in some other implementation-defined manner.*", though it's not a good idea. – Schwern Sep 07 '17 at 20:24
  • 1
    `fflush(stdin)` invokes undefined behaviour and ther is no standard function `_flushall`. – too honest for this site Sep 07 '17 at 20:31
  • @Schwern: [7.19 is about `stddef.h`](http://port70.net/~nsz/c/c11/n1570.html#7.19) which does not cover stream I/O. What are you refering to? – too honest for this site Sep 07 '17 at 20:33
  • @Olaf ISO/IEC 9899:TC3 and ISO/IEC 9899:201x is what I have available. The numbers might have drifted. Yes technically `gets` was removed in C11, but it's not about being technically correct, it's about communicating to a newbie. – Schwern Sep 07 '17 at 20:41
  • Concerning `main()`, C11 5.1.2.2.1 1 has "It (`main`) shall be defined with a return type of `int` and with no parameters: ... or with two parameters... or equivalent; or in some other implementation-defined manner". – chux - Reinstate Monica Sep 07 '17 at 20:43
  • @Schwern: Those are not the standard. While technically also not the standard, n1570 as the final draft is exactly the same as he standard, except for two irrrelevant changed predefined macros. And that does not include `gets`, except for the foreword where it is very clear about it having been removed. – too honest for this site Sep 07 '17 at 20:44
  • @chux: While agree with you, I've given up as the full section is indeed unclear about what exactly "or in some other implementation-defined manner" refers to exactly: the full declaration, declarator only or just the "It shall be defined" part. But you are right that e.g. POSIX requires the two listed variants (plus an extra optional argument, IIRC). – too honest for this site Sep 07 '17 at 20:46
  • @Olaf True there is potential ambiguity in "some other implementation-defined manner" referring to 1) the parameters or 2) the parameters and return type. IAC, OP is evidently able to compile with `void main()` and the key issue lies elsewhere. – chux - Reinstate Monica Sep 07 '17 at 20:49
  • @chux: AFIAK only Windows as a full-size OS allows `void main…`. The others are POSIX compliant, not allowing that. The compiler not warning is - as I'm sure you know - needs not warn, though. And for freestanding implemtations this section does not apply at all. – too honest for this site Sep 07 '17 at 20:56
  • @Schwern Update your copy. "This third edition cancels and replaces \[...] Major changes from the previous edition include: \[...] removed the gets function". *void main is technically correct* yes, but it's not *right*. – n. m. could be an AI Sep 07 '17 at 21:02
  • [Why is the gets function so dangerous that it should not be used?](https://stackoverflow.com/q/1694036/995714). It has been removed since C99 – phuclv Jan 06 '18 at 08:47

2 Answers2

3
  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().

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
3

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.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • The question is tagged without any specific version, so we have to assume standard C, which is **only** C11 - just read the tag-wiki! If you consider this significant, the correct way would be to ask OP for clarification. – too honest for this site Sep 07 '17 at 20:58
  • 1
    @Olaf A person asking basic questions about `scanf` probably doesn't even know C11 or the C standard exist. If you're technically correct, but the person asking the question doesn't understand, what's the point? Who are you talking to? – Schwern Sep 07 '17 at 21:00
  • "C compilers and documentation lag very, very, very far behind the standard." - Of the high-end compilers for full-OS hosted environments, only MSVC is lagging behind - since at least 18 years. gcc and clang are fine, together with most relevant parts of the libraries (they are not part of those two compilers, btw). – too honest for this site Sep 07 '17 at 21:01
  • @Olaf A lot of people use MSVC, unfortunately. Or learn on out of date compilers using out of date material. If they're asking about `scanf` and `gets`, they're probably one of those people. – Schwern Sep 07 '17 at 21:03