2

I'm trying to write a program that reads various user inputs. These string inputs can contain or not whitespace. I made a version that works good, but needs a while loop (inside clearStdin function) as show below:

#include <stdio.h> 
#include <stdlib.h> 

void clearStdin(void);

int main(void)
{
    char name1[8], name2[5];

    printf("Write a name: ");
    fgets(name1, sizeof name1, stdin);
    clearStdin();

    printf("Write another name: ");
    fgets(name2, sizeof name2, stdin);
    clearStdin();

    printf("First name is: %s\n", name1);  
    printf("Second name is: %s\n", name2);

    return 0;
}

void clearStdin(void){  

    int c;

    while(( c = getchar() ) != '\n' && ( c != EOF ));
}

I tried to use

scanf("%7[^\n]", name1);
scanf("%*[^\n]");
scanf("%*c");

and also other ways. My question is: There is other ways for the program to work without using the while (or another) loop? Any scanf or fgets way only?

Exemple input:

 Write a name: RafaelBluhm
 Write another name: Tainah Julião

Required output:

First name is: RafaelB
Second name is: Tain

Fails outputs (Other ways):

First name is:Tain
Second name is:@�
Rafael Bluhm
  • 129
  • 5
  • is it possible that you did not use \0 to close your string? – Philipp Braun Jan 20 '15 at 22:34
  • 2
    BTW `char c;` at `clearStdin()` : should be `int c;` – BLUEPIXY Jan 20 '15 at 22:34
  • always check the returned value from each call to 'fgets; and/ or 'scanf' to assure the operation was successful. always place a leading ' ' (space) in the format string of scanf() so it will skip over any leading white space. always place a limit/max length on when using %s in scanf() so no buffer overrun will occur. suggest using fscanf() rather than scanf() Finally, I suggest input whole line with fgets(), the use sscanf() to extract first/last name. and always clear each first/last name buffer to '\0' before using sscanf() so when no last name, nothing is printed. – user3629249 Jan 21 '15 at 02:18
  • 1
    `scanf("%8[^\n]", name1);` should be `scanf("%7[^\n]", name1);` – chux - Reinstate Monica Jan 21 '15 at 02:23
  • OT: It's more common (and will cause less trouble with buffering) to use `stderr` for a prompt: `fputs("Write a name: ", stderr)` or `fprintf(stderr, "Write a name: ");` – mafso Jan 21 '15 at 10:11

3 Answers3

3

For general implementation: No, there is no other way to clear the input buffer.

For a given specific environment, there might be an environment-specific way. For example, on Linux/Unix, there is a way to see how many terminal buffer characters are pending through ioctl() and another way to clear them.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • 1
    This is correct. More detail at http://stackoverflow.com/questions/22901901/what-does-fflushstdin-do-in-c-programing - however, on Linux (and, apparently, DOS), `fflush(stdin)` *does* actually work - see the man page. – abligh Jan 20 '15 at 23:00
  • Even if it was reliable, it would still be terrible. Imagine if stdin came from a pipe or redirected file (which is a great thing to do; everyone hates typing repeated stuff just for the sake of testing)! – Rafael Lerm Jan 20 '15 at 23:20
2

If you want to use scanf, you can use

scanf("%*[^\n]%*1[\n]");

This is equivalent to your clearStdin function.

I'd suggest that you indicate EOF by the return value (scanf returns EOF on end-of-file or error here), and check for that -- a program shouldn't attempt to read further input after the first end-of-file.

mafso
  • 5,433
  • 2
  • 19
  • 40
  • Works good. But only to clear `fgets` imput. I tried to use with `scanf` and it did not work. I heard that is not good to mix this two functions. – Rafael Bluhm Jan 21 '15 at 14:23
  • @RafaelBluhm, iIt's not necessarily bad to mix them (actually, it's bad to use either of them (some `scanf` calls are OK), but that's another discussion), you must keep in mind that they work differently. This `scanf` call should do exactly the same as the `clearStdin` function. With what `scanf` call doesn't this work? And btw, you probably want to check if `fgets` has read a newline (`strchr`) or not (and only clear `stdin` if it hasn't). – mafso Jan 21 '15 at 14:31
  • 1
    @ mafso `scanf("%*[^\n]%*c");` works well too. Ty for the sugests. – Rafael Bluhm Jan 21 '15 at 23:24
-1

I think you can use fflush(stdin); I have use it before but I'm not sure if its stantard C , test it and let me know.

Luis Tellez
  • 2,785
  • 1
  • 20
  • 28
  • `fflush(stdin);` donts works. It's not in standard C. The rest of buffter stored in the first string is placed in the second – Rafael Bluhm Jan 20 '15 at 22:46
  • Please, let's abolish [this abomination[(http://stackoverflow.com/questions/2979209/using-fflushstdin) from the face of the earth! – Rafael Lerm Jan 20 '15 at 23:01
  • Whilst it's not POSIX compliant, it does work under Linux (and allegedly DoS) - see link on other post. The answerer did say he wasn't sure it was standard C so let's not be too harsh. – abligh Jan 20 '15 at 23:02
  • 2
    Even if it was standard, it would still be terrible. The OP's loop will consume up to and including the next newline; if `fflush(stdin)` where to reliably work, it would just throw away the rest of the buffer. Now imagine if stdin doesn't come from a human typing in a terminal, but from a pipe or a redirected file. – Rafael Lerm Jan 20 '15 at 23:17
  • This solution is to solve THIS problem... in this case that's how you get the input. – Luis Tellez Jan 21 '15 at 01:43