Thread: scanf oddities

  1. #1
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129

    scanf oddities

    Code:
    ~$ cat main.c
    #include <stdio.h>
    
    int main()
    {
            while(1)
            {
                    int input, num;
                    printf("type a number: ");
                    scanf("&#37;d\n%n", &input, &num);
                    printf(" %d ", num);
            }
    
            return 0;
    }
    ~$ gcc -Wall -Werror main.c
    ~$ ./a.out
    type a number: 2
    2
     2 type a number: 2
     2 type a number: 2
     2 type a number: 23
     2 type a number: 23
     3 type a number: 23
     3 type a number: 23
     3 type a number: 2
     3 type a number: 2
     2 type a number: 2
     2 type a number: 2
     2 type a number: 23
     2 type a number: 2
     3 type a number: 23
     2 type a number: 2
     3 type a number: 2
     2 type a number: 234
     2 type a number: 2
     4 type a number: 234
     2 type a number: 2
     4 type a number: 1
     2 type a number: 1
     2 type a number:
    ~$
    why does scanf require a second input in the first iteration? it messes up all the other iterations.

    the newline in the scanf call is to eat up the newline so that other inputs will be ok.

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >the newline in the scanf call is to eat up the newline so that other inputs will be ok.
    That's why you think it's there, but it's causing you problems. %d will skip leading whitespace and %n doesn't consume characters, so there's no need to remove a newline separately. Change your format string to "%d%n" and watch it work better.
    My best code is written with the delete key.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You may want to look at the return value from scanf too. This will indicate how many of your fields got filled in.

    I'm, by the way, more of the opinion that fgets() + sscanf() is the right way to read numbers from a user. scanf is far too fragile to let users "use" directly.

    Obviously it's fine for simple test apps where you just want to enter a number/string/what-have-you into it to get some data for testing - but if you want it at least a teensy bit stable, scanf() is no good. Just try entering 23A in your example above, and you'll get a flood of output, because scanf bails out on the basis of "no number in the buffer".

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Quote Originally Posted by Prelude View Post
    Change your format string to "%d%n" and watch it work better.
    yes, it does, it gets rid of the mismatch. I was able to get rid of the trailing newline as well by using "%d%n%*c".

    however I'm still confused as to what the \n was doing. Why was it messing it up so much?
    Quote Originally Posted by matsp View Post
    I'm, by the way, more of the opinion that fgets() + sscanf() is the right way to read numbers from a user. scanf is far too fragile to let users "use" directly.
    I'm more comfortable with fgets as well, but I still want to know how to use scanf.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by robwhit View Post
    however I'm still confused as to what the \n was doing. Why was it messing it up so much?
    For scanf(), if you indicate a whitespace character (which includes \n), it will accept zero or more whitespace characters of any type. So \n is not a valid way to match the end of a line.

    I'm more comfortable with fgets as well, but I still want to know how to use scanf.
    I personally think it's a worthless function, for exactly this reason. You can't distinguish newline from any other kind of whitespace, which makes it intrinsically impossible to handle line-based input in a robust way.

    sscanf(), on the other hand, is GREAT for parsing lines you have already stored somewhere.

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    oh ok, I think I get it now.

    Thanks all!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. scanf() consideres useless
    By Snafuist in forum C Programming
    Replies: 15
    Last Post: 02-18-2009, 08:35 AM
  2. Help with a basic scanf procedure.
    By killpoppop in forum C Programming
    Replies: 9
    Last Post: 11-03-2008, 04:39 PM
  3. Replies: 2
    Last Post: 02-20-2005, 01:48 PM
  4. scanf issue
    By fkheng in forum C Programming
    Replies: 6
    Last Post: 06-20-2003, 07:28 AM
  5. scanf - data is "put back" - screws up next scanf
    By voltson in forum C Programming
    Replies: 10
    Last Post: 10-14-2002, 04:34 AM