Search code examples
c++cscanfcingets

incorrect results with gets () due to the stray \n in istream BUT not with scanf() or cin?


In the program printed below the problem with gets () is that it takes the data for the first time only, and every subsequent call results in a null, due to the stray \n in the istream left while entering the number.

main()
{
    char name[20];
    int number;
    for(int i=0;i<5;i++)
    {
        printf("enter name");
        gets(s);
        printf("enter phone number");
        cin>>a;
    }
}

Now my question is that why isn't the same happening for when I use scanf() or cin ? I mean whats the difference in the way cin and gets() takes their values which enables cin (and scanf ) to successfully leave that stray \n but not gets() ?

PS: I know about fgets(), and that gets() is deprecated and its ill-effects, and generally dont use it as well.


Solution

  • scanf and cin >> both read fields delimeted by whitespace, and ignore leading whitespace. Now whitepsace is spaces, tabs, AND NEWLINES, so extra newlines in the input doesn't bother them. More importantly, after reading something, they DO NOT read any of the following whitespace, instead leaving it on the input for the next call to read.

    Now with scanf, you can tell it explicitly to read (and throw away) as much whitespace as it can by using a space at the end of the format string, but that will work poorly for interactive input, as it will KEEP trying to read until it gets some non-whitepsace. so if you change the end of your loop to:

    printf("enter phone number");
    scanf("%d ", &a);
    

    it will seem to hang after entering the phone number, as its waiting for you to enter some non-whitespace, which will ultimately be read by the next loop iteration as the next name.

    You CAN use scanf to do what you want -- read and consume the text following the phone number up to the newline -- but its not pretty:

    scanf("%d%*[^\n]", &a); scanf("%*1[\n]");
    

    You actually need two scanf calls to consume the newline as well as any space or other cruft that might be on the line.