#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    39
    Rep Power
    3

    Problems on 'scanf'


    Hey, every one,I wrote some codes in which I called the function fgets and scanf.
    With scanf first called and then next calling but some wield problems arose. I wrote a piece of short codes to illastrate it. I know it's something about the buffer problem but I can not deal with . Can you help me? Thank you in advance....

    Code:
     
    #include <stdio.h>
    
    int main(){
      char string[20];
      int num;
      printf("input your number\n");
      scanf("%d",&num);
      fflush(stdout);
      printf("input your name\n");
      fgets(string,10,stdin);
      printf("your num is:%d,and your name is:%x\n",num,string[0]);
      printf("thank you\n");
    }
    if I input a number the hit the Enter key ,it just jump over the fgets(...) and ends.
    I input 23 and hit Enter. it prints 23 and 'a'. Why?????
  2. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,379
    Rep Power
    1871
    The thing you have to remember is that most scanf conversions ignore newlines, and that newline is special to fgets().

    The other thing to remember is that scanf only takes the characters it can use. So if you type in "123\n", then the \n is typically left behind as being the first character that does NOT match the format conversion.

    However, the naive scanf("%d\n",&num); to consume the \n runs into another problem, which we sometimes see here as "why won't my scanf function return?". To scanf, a single "\n" doesn't mean a single "\n", but means any combination of any number of white-space characters (space, newline, tabs).

    So, the immediate fix is to have something like
    Code:
    { int ch; while ( (ch=getchar()) != EOF && ch != '\n' ); }
    when you switch from scanf to fgets.


    Perhaps the best long-term approach is to not mix input methods.
    Eg.
    Code:
    char temp[100];
    fgets( temp, sizeof(temp), stdin );
    sscanf( temp, "%d", &num );
    Yes, it is a bit longer than a simple scanf, but by the time you add FULL error checking, the difference isn't that great.
    Code:
    char temp[100];
    if ( fgets( temp, sizeof(temp), stdin ) != NULL ) {
      if ( sscanf( temp, "%d", &num ) == 1 ) {
        // success!
      } else {
        // conversion error
      }
    } else {
      // EOF or I/O error
    }
    By the time you've made scanf() bullet-proof, AND cleaned up the input stream from conversion errors, you'll have just as much code.


    > fgets(string,10,stdin);
    You declared char string[20];
    Lying to fgets() about the size of the buffer can lead to hard to find bugs. You should always use a sizeof() or some symbolic constant for buffer sizes, not some magic number like 10. If you made your char buffer smaller, then the code would be broken.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. Lord of Dorkness
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2004
    Location
    Central New York. Texan via Arizona, out of his element!
    Posts
    8,524
    Rep Power
    3314
    You could gain a lot in several areas by browsing the "Commonly Asked Question" thread.
    Functionality rules and clarity matters; if you can work a little elegance in there, you're stylin'.
    If you can't spell "u", "ur", and "ne1", why would I hire you? 300 baud modem? Forget I mentioned it.
    DaWei on Pointers Politically Incorrect.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    39
    Rep Power
    3

    Thank you so much~~


    Originally Posted by salem
    The thing you have to remember is that most scanf conversions ignore newlines, and that newline is special to fgets().

    The other thing to remember is that scanf only takes the characters it can use. So if you type in "123\n", then the \n is typically left behind as being the first character that does NOT match the format conversion.

    However, the naive scanf("%d\n",&num); to consume the \n runs into another problem, which we sometimes see here as "why won't my scanf function return?". To scanf, a single "\n" doesn't mean a single "\n", but means any combination of any number of white-space characters (space, newline, tabs).

    So, the immediate fix is to have something like
    Code:
    { int ch; while ( (ch=getchar()) != EOF && ch != '\n' ); }
    when you switch from scanf to fgets.


    Perhaps the best long-term approach is to not mix input methods.
    Eg.
    Code:
    char temp[100];
    fgets( temp, sizeof(temp), stdin );
    sscanf( temp, "%d", &num );
    Yes, it is a bit longer than a simple scanf, but by the time you add FULL error checking, the difference isn't that great.
    Code:
    char temp[100];
    if ( fgets( temp, sizeof(temp), stdin ) != NULL ) {
      if ( sscanf( temp, "%d", &num ) == 1 ) {
        // success!
      } else {
        // conversion error
      }
    } else {
      // EOF or I/O error
    }
    By the time you've made scanf() bullet-proof, AND cleaned up the input stream from conversion errors, you'll have just as much code.


    > fgets(string,10,stdin);
    You declared char string[20];
    Lying to fgets() about the size of the buffer can lead to hard to find bugs. You should always use a sizeof() or some symbolic constant for buffer sizes, not some magic number like 10. If you made your char buffer smaller, then the code would be broken.
    Thank you for you patience and so detailed reply。I really appreciate it.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    39
    Rep Power
    3

    Ok


    Originally Posted by DaWei_M
    You could gain a lot in several areas by browsing the "Commonly Asked Question" thread.
    Thank you for your advice.I wil see it.

IMN logo majestic logo threadwatch logo seochat tools logo