1

After wasting too much time searching why my program doesn't execute gets() after using scanf(), I found a solution which is to use fflush(stdin) after scanf() to enable gets() to get a string.

The problem is that fflush(stdin) doesn't do what is expected from it: The program continues skipping gets() and I can't write any phrase in the console to be read.

My code is the next one:

#include <string.h>
#include <stdio.h>

int main(){
    char nombre[10];
    char mensaje[80];

    printf("Type your name:\n");
    scanf("%s", nombre);

    fflush(stdin);

    printf("Now, type a message:\n");
    gets(mensaje);

    printf("3/%s:%s",nombre,mensaje);
    return 0;
}
Joe Hackerberg
  • 457
  • 7
  • 20
  • Please read: http://stackoverflow.com/questions/2979209/using-fflushstdin (unrelated to your issue though). – Mat Mar 06 '14 at 13:54
  • possible duplicate of [Input in C. Scanf before gets. Problem](http://stackoverflow.com/questions/2366509/input-in-c-scanf-before-gets-problem) – Mat Mar 06 '14 at 13:55
  • Change the last `printf` into `printf("3/%s:%s\n",nombre,mensaje);` – Jabberwocky Mar 06 '14 at 13:55
  • Michael it doesn't run good because when the program reaches that line, the message (mensaje) has to be written and I can't write anything because the gets() keeps skipping – Joe Hackerberg Mar 06 '14 at 14:05
  • 1
    Don't `fflush(stdin)`. – Kevin Mar 06 '14 at 16:24
  • `fflush(stdin)` causes undefined behaviour. It has no expectation. On my compiler it just does nothing (which is arguably a better option than crashing). The `fflush` function means to write any buffered output that hasn't been written yet, but `stdin` is not writable. – M.M Mar 06 '14 at 19:24

5 Answers5

6

If flushing std doesn't work, then try reading in the extra characters and discarding, as suggested here.

This will work:

#include <string.h>
#include <stdio.h>

int main(){
    char nombre[10];
    char mensaje[80];
    int c;

    printf("Type your name:\n");
    scanf("%9s", nombre);

    while((c= getchar()) != '\n' && c != EOF)
            /* discard */ ;

    printf("Now, type a message:\n");
    gets(mensaje);

    printf("%s:%s",nombre,mensaje);
    return 0;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
emsworth
  • 1,149
  • 10
  • 21
4

Two big, major issues:

  1. DO NOT USE fflush ON INPUT STREAMS; the behavior of fflush on input streams is not defined. Just because it appears to work in this situation does not mean it is correct.

  2. NEVER NEVER NEVER NEVER NEVER NEVER NEVER use gets - it was deprecated in the C99 standard and has been removed completely from the C2011 standard. It will (not might, will) introduce a major point of failure in your code.

It's never a good idea to follow a scanf call with a gets call, since gets won't skip over any leading newlines left in the input stream by scanf. Use scanf to read both nombre and mesaje.

printf("Type your name:\n");
scanf("%9s", nombre);

printf("Now, type a message:\n");
scanf("%79s", mensaje);

It's a good idea to use an explicit length specifier in the scanf call for %s and %[, otherwise you introduce the same security hole that gets does.

EDIT

D'oh. I'm an idiot. If you're trying to read a string containing spaces, you can't use the %s conversion specifier. Use the %[ conversion specifier instead:

scanf( "%79[^\n]", mensage );

That will read up to the next 79 characters or the newline, whichever comes first, and leaves the newline in the input stream.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • I don't know why, but happens the same if I use "%79s" or "%s": scanf only get the first word of the whole phrase, so that I've been using gets(). – Joe Hackerberg Mar 06 '14 at 18:45
  • `scanf( "%79[^\n]", mensage );` after `scanf("%9s", nombre);` can easily read nothing as the first character may be `'\n'`. `scanf( " %79[^\n]", mensage );` is a bit better, yet loses leading spaces. – chux - Reinstate Monica Oct 23 '18 at 20:37
0

Try this instead:

scanf("%s\n", nombre);

scanf stops at whitespace when reading a part. gets reads until the first new line. So what happens is scanf leaves behind a newline in the buffer, which gets immediately sees and thinks it was given a blank line.

If you take your original code and enter "name message", two pieces all on one line, you can see this in action - gets will still immediately return, but it will see the second part.

The \n in the scanf thing tells it to go ahead and consume that too.

Adam D. Ruppe
  • 25,382
  • 4
  • 41
  • 60
  • Thank you for answering but it's not the solution because after I enter the name, press enter and it keeps blank until I type something and press enter, then the console shows me "Now, type a message:" – Joe Hackerberg Mar 06 '14 at 14:02
  • Bad solution. `scanf("%s\n", nombre);` " tells it to go ahead and consume that too." and continue reading until non-white scape detected. Then it returns. – chux - Reinstate Monica Oct 23 '18 at 20:40
0

Try gets(stdin); instead of

fflush(stdin);
Smitt
  • 178
  • 7
  • sorry, typo, my bad, use getc(stdin), instead of fflush(stdin), The fflush function does not flush data out of an input stream; it is instead used to push data buffered in an output stream. – Smitt Mar 06 '14 at 14:13
  • Thank u Smitt! using getc(stdin) runs perfectly as well. Sorry, i've seen another answer first and accepted it, but I'll give you a positive vote at least. ;) – Joe Hackerberg Mar 06 '14 at 18:53
-1
while (fgetc(stdin) != '\n'); // seems to work
xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • 1
    Welcome to StackOverflow, user9816128. Would you like to augment your code-only answer with some explanation? In the current form it is unlikely to attract upvotes. – Yunnosch May 19 '18 at 15:59