Programmer wannabee question about sscanf

B

broeisi

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?
 
J

jhartzell42

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
 
V

Vladimir S. Oka

broeisi said:
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 `[email protected]` as it has more than it's
fair share of inaccuracies.
 
F

Flashes of Sky

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.
 
K

Keith Thompson

Vladimir S. Oka said:
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).
 
K

Keith Thompson

broeisi said:
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.
 
V

Vladimir S. Oka

Keith said:
Vladimir S. Oka said:
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).
 
C

Chad

Vladimir said:
broeisi said:
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
 
V

Vladimir S. Oka

Chad said:
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.
 
C

CBFalconer

Chad said:
Vladimir S. Oka wrote:
.... snip ...

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/>
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top