Programmer wannabee question about sscanf

Discussion in 'C Programming' started by broeisi, Mar 4, 2006.

  1. broeisi

    broeisi Guest

    What advantages does sscanf offer over scanf?

    I had the following code:

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

    int main(void)
    {
    int start, finish, values;
    char line[10];

    memset(line,0, 10);

    printf("Event numbers ? ");


    fgets(line, sizeof(line), stdin);
    values = sscanf(line,"%d %d", &start, &finish);

    printf("start = %d en finish = %d values = %d\n",
    start, finish, values);

    return 0;
    }

    but if tha user inputted for example : erte 5 6 ..the output of start
    and finished would not be 5 or 6 but some strange value...

    I thought that sscanf would find values that are integers and assign
    those integer values to the variables?

    If not how can I accomplish this?
     
    broeisi, Mar 4, 2006
    #1
    1. Advertising

  2. broeisi

    Guest

    sscanf does no more than scanf does; it just gets its input from a
    string rather than from standard input. Both scanf and sscanf are
    extremely strict; they expect input that would have been created by the
    exact same formatting string using printf.
    The most straight-forward way to get the first two numbers from a
    string is to loop through the string, character by character, testing
    each character to see if it is a digit. Then, when a digit is reached
    (and you can, if you want, require and check that the digit either be
    the first character in the string or preceded by whitespace) use strtol
    to convert the number starting with that digit into the string.
    strtol takes a pointer as its second argument, and will put a pointer
    to the first character after the number into the variable pointed to by
    that second argument. It returns the number.
    You then continue to loop through the string until you reach another
    digit, after which you can call strtol again!
    In general, it is better to write your own code to parse input strings,
    rather than use scanf.
    I note that you are using memset in your code to zero your buffer
    before reading input into it. The code will work equally well without
    it, but I don't know the true context this code is used in, so perhaps
    it is valid.
    Also, you are putting an artificial 10-character limit on the user's
    input. If the user wants to define a range between two five digit
    numbers, it will not fit, and the end of the second number will be
    chopped off. I usually use a function I have written to read the entire
    line into dynamically allocated memory, which can be extended as
    needed, but increasing the buffer size to 256 would do as well in this
    case.
    The function I have written to read lines from standard input can be
    downloaded at http://www.nic-nac-project.de/~baseball/code/readline.c;
    feel free to use it in your code.
    I hope all this helps!
    Jimmy Hartzell
     
    , Mar 4, 2006
    #2
    1. Advertising

  3. broeisi wrote:
    > What advantages does sscanf offer over scanf?


    It does not create potential buffer overflow vulnerability when used
    with %s.

    > I had the following code:
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int main(void)
    > {
    > int start, finish, values;
    > char line[10];
    >
    > memset(line,0, 10);


    Not really necessary...

    >
    > printf("Event numbers ? ");


    Not terminating printf() with \n may result in no output until an \n is
    emitted, or fflush(stdout) is executed.

    > fgets(line, sizeof(line), stdin);
    > values = sscanf(line,"%d %d", &start, &finish);
    >
    > printf("start = %d en finish = %d values = %d\n",
    > start, finish, values);
    >
    > return 0;
    > }
    >
    > but if tha user inputted for example : erte 5 6 ..the output of start
    > and finished would not be 5 or 6 but some strange value...
    >
    > I thought that sscanf would find values that are integers and assign
    > those integer values to the variables?


    No, sscanf() will try to get it's values as specified and will
    terminated as soon as it gets them, or as soon as it fails. In your
    example above, it fails immediately (for "erte") and `start` and
    `finish` remain uninitialised (you'd have been better initialising them
    than the string). You should have checked `value` for errors, and you'd
    have discovered this.

    > If not how can I accomplish this?


    If you want to get the first two valid integers out of anything user
    might decide to input, you'd have to process it yourself. AFAIK,
    there's no C function that'll do it for you.

    PS
    Please ignore post by `` as it has more than it's
    fair share of inaccuracies.

    --
    BR, Vladimir

    Avoid the Gates of Hell. Use Linux
    (Unknown source)
     
    Vladimir S. Oka, Mar 4, 2006
    #3
  4. Re: comp.lang.c

    > What advantages does sscanf offer over scanf?
    >
    > I had the following code:
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > int main(void)
    > {
    > int start, finish, values;
    > char line[10];
    >
    > memset(line,0, 10);
    >
    > printf("Event numbers ? ");
    >
    >
    > fgets(line, sizeof(line), stdin);
    > values = sscanf(line,"%d %d", &start, &finish);
    >
    > printf("start = %d en finish = %d values = %d\n",
    > start, finish, values);
    >
    > return 0;
    > }
    >
    > but if tha user inputted for example : erte 5 6 ..the output of start
    > and finished would not be 5 or 6 but some strange value...
    >
    > I thought that sscanf would find values that are integers and assign
    > those integer values to the variables?
    >
    > If not how can I accomplish this?
    >


    If possible on your system, use getline(), even if extensions are not
    usually reccomended. Imposing arbitary limits on a program is not a
    good habit to get into.

    Here lies the problem:

    values = sscanf(line,"%d %d", &start, &finish);

    The problem with your slice of code is that you are assigning the
    return value of the statement as well as expecting two decimals with a
    space between them.:

    The should-work way should be:

    int start, finish, values;
    char line[10];

    memset(line,0, 10);

    printf("Event numbers ? ");

    fgets (line, sizeof(line), stdin);
    sscanf (line, "%d","%d", &start, &finish);
    sscanf (line, "%d %d", &value);

    Hopw that helps and has no compile problems.
     
    Flashes of Sky, Mar 4, 2006
    #4
  5. "Vladimir S. Oka" <> writes:
    > broeisi wrote:
    >> What advantages does sscanf offer over scanf?

    >
    > It does not create potential buffer overflow vulnerability when used
    > with %s.

    [...]

    It does, but the vulnerability is easily controlled for sscanf()
    (since you can know the size of the input string), but not easily
    controlled for scanf() (since the program generally can't control how
    long an input line might be).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Mar 4, 2006
    #5
  6. "broeisi" <> writes:
    > What advantages does sscanf offer over scanf?

    [snip]

    By using fgets() and sscanf(), you divide the task into two parts:
    getting the input line and extracting information from it.

    scanf() consumes a variable number of characters from stdin, depending
    on the format string and what's actually in the input line. It
    commonly leaves a newline character on stdin, to be consumed by the
    next input routine you call (which may not be able to handle it
    properly). If you're trying to read, say, 3 input fields, and the
    input only has 2 valid fields, scanf() will consume those two fields
    and may leave you in the middle of the line.

    In some cases, scanf() skips whitespace, *including* new-line
    characters. If the user doesn't provide all the required fields on a
    line, it keeps reading lines until you get all of them (or an error);
    that's probably not what you want.

    By contrast, fgets() consumes an entire line, including the trailing
    newline. (That's not *quite* true; it only reads up to the maximum
    number of characters you specify. You can either discard the rest of
    the line after fgets(), or you can use a routine like the non-standard
    but freely available ggets() that reads the entire line.) Once you
    have the line in memory, you can use sscanf() to extract the required
    information from it. sscanf(), like scanf(), returns the number of
    items successfully translated. If that's less than the number you
    asked for, you can reject the entire input line. If your program is
    interactive, you can then prompt the user to try again.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Mar 4, 2006
    #6
  7. Keith Thompson wrote:

    > "Vladimir S. Oka" <> writes:
    >> broeisi wrote:
    >>> What advantages does sscanf offer over scanf?

    >>
    >> It does not create potential buffer overflow vulnerability when used
    >> with %s.

    > [...]
    >
    > It does, but the vulnerability is easily controlled for sscanf()
    > (since you can know the size of the input string), but not easily
    > controlled for scanf() (since the program generally can't control how
    > long an input line might be).


    Yes, but that's self-inflicted (i.e. bad programming by choice).

    --
    BR, Vladimir

    His heart was yours from the first moment that you met.
     
    Vladimir S. Oka, Mar 4, 2006
    #7
  8. broeisi

    Chad Guest

    Vladimir S. Oka wrote:
    > broeisi wrote:
    > > What advantages does sscanf offer over scanf?

    >
    > It does not create potential buffer overflow vulnerability when used
    > with %s.
    >
    > > I had the following code:
    > >
    > > #include <stdio.h>
    > > #include <string.h>
    > >
    > > int main(void)
    > > {
    > > int start, finish, values;
    > > char line[10];
    > >
    > > memset(line,0, 10);

    >
    > Not really necessary...
    >
    > >
    > > printf("Event numbers ? ");

    >
    > Not terminating printf() with \n may result in no output until an \n is
    > emitted, or fflush(stdout) is executed.
    >


    How could omitting '\n' possibly result with no output until an '\n' or
    fllush is executed? Care to give some kind of example?

    Thanks,
    Chad
     
    Chad, Mar 4, 2006
    #8
  9. broeisi

    Chad Guest

    I meant *or fflush()*.
     
    Chad, Mar 4, 2006
    #9
  10. Chad wrote:
    > Vladimir S. Oka wrote:
    >> broeisi wrote:
    >> >
    >> > printf("Event numbers ? ");

    >>
    >> Not terminating printf() with \n may result in no output until an \n
    >> is emitted, or fflush(stdout) is executed.

    >
    > How could omitting '\n' possibly result with no output until an '\n'
    > or fllush is executed? Care to give some kind of example?


    No need for an example. Have a look at the Standard.

    --
    BR, Vladimir

    My theology, briefly, is that the universe was dictated but not signed.
    -- Christopher Morley
     
    Vladimir S. Oka, Mar 5, 2006
    #10
  11. broeisi

    CBFalconer Guest

    Chad wrote:
    > Vladimir S. Oka wrote:
    >

    .... snip ...
    >>
    >> Not terminating printf() with \n may result in no output until
    >> an \n is emitted, or fflush(stdout) is executed.

    >
    > How could omitting '\n' possibly result with no output until an
    > '\n' or fllush is executed? Care to give some kind of example?


    Because a C stream will normally collect output in a buffer until
    it has enough to spend the time on a operating system call to
    output it. The appearance of a '\n' or a call to fflush() on that
    file will force the actual output.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
     
    CBFalconer, Mar 5, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dan Smith

    Question on sscanf

    Dan Smith, Aug 14, 2003, in forum: C Programming
    Replies:
    3
    Views:
    426
    Martin Ambuhl
    Aug 14, 2003
  2. Sanny
    Replies:
    391
    Views:
    42,496
    anish.mathew84
    Jan 6, 2010
  3. Sanny
    Replies:
    396
    Views:
    7,188
    Noah Roberts
    Dec 17, 2008
  4. Isaac
    Replies:
    0
    Views:
    403
    Isaac
    Dec 8, 2010
  5. Isaac
    Replies:
    0
    Views:
    384
    Isaac
    Dec 8, 2010
Loading...

Share This Page