scanf and sscanf

  • Thread starter Bill Cunningham
  • Start date
B

Bill Cunningham

What would be a practical reason to use sscanf? I read an example of how
it works but I can pretty much use scanf to do the same thing.

B
 
B

Bill Cunningham

Bill said:
What would be a practical reason to use sscanf? I read an example
of how it works but I can pretty much use scanf to do the same thing.

B

Also the FAQ 12.20 answer ¶3 or so says use fgets and then sscanf. BTW
What's it mean by scanf's big %s problem? Is the %s the same with any other
specifiers?

B
 
G

glen herrmannsfeldt

Bill Cunningham said:
What would be a practical reason to use sscanf?

I use it for converting strings to numbers, such as for numeric
arguments.

-- glen
 
B

Bill Cunningham

glen said:
I use it for converting strings to numbers, such as for numeric
arguments.

Really. Can you show me an example? I would use functions from string.h
to do that like strtol or atoi strtoul and so on.

B
 
G

glen herrmannsfeldt

Bill Cunningham said:
glen herrmannsfeldt wrote:
Really. Can you show me an example? I would use functions
from string.h to do that like strtol or atoi strtoul and so on.

I usually use sscanf() instead, but yes you could do that.

sscanf(argv[1],"%d",&n);

with the usual int main(int argc, char **argv).

-- glen
 
A

Alain Ketterlin

Bill Cunningham said:
Really. Can you show me an example? I would use functions from string.h
to do that like strtol or atoi strtoul and so on.

sscanf has primitive pattern matching, which is useful for simple cases,
e.g.,

n = sscanf(somestring,"(%d,%d)",&x,&y);

(scanf has the same capabilities I think; I never use it).

I don't know whether this is standard, though.

-- Alain.
 
B

Barry Schwarz

scanf extracts data from the stdin stream. sscanf extracts data form
a string. Both functions ignore leading white space characters when
extracting strings or numbers. Thus it is possible that scanf will
silently skip to the next line. If you don't want this to happen, you
use fgets to read an entire line and sscanf to process the data. The
string produced by fgets will never contain more than one line of data
from the file or stream.

There are also times when you may want to process the data multiple
times, possibly with different conversion specifications. Once scanf
has read the data, it is no longer in the stream so you cannot
reprocess it. On the other hand, sscanf does not destroy the data in
the string so you can process it repeatedly if needed.
Also the FAQ 12.20 answer ¶3 or so says use fgets and then sscanf. BTW
What's it mean by scanf's big %s problem? Is the %s the same with any other
specifiers?

With either scanf or sscanf, the %s format will not extract a string
with embedded spaces or other white space characters. Thus %s can not
be used to read a name like John Doe. Both functions would stop at
the space and extract the string John. If you use fgets, you could
then use strncpy or a similar function to extract both the first and
last names to a single string.

The problem does not exist with other specifiers since you cannot have
embedded white space in a number and %c does not treat white space as
special.
 
N

Nobody

Also the FAQ 12.20 answer ¶3 or so says use fgets and then sscanf.

fgets()+sscanf() is appropriate when newlines are significant, i.e. each
"chunk" of input is on its own line. If the input contains too few values,
fgets()+sscanf() will parse one line of input and tell you how many
values it obtained, whereas fscanf() will start reading values from the
next line().

fscanf() is appropriate when newlines are merely whitespace (e.g. as is
the case for C source code).
BTW What's it mean by scanf's big %s problem? Is the %s the same with
any other specifiers?

I presume that it refers to the fact that "%s" will copy an arbitrary
number of characters into the buffer pointed to by the corresponding
argument. If the number of characters exceeds the size of the buffer, you
get an overflow.

Note that %[ has the same issue.
 
J

James Kuyper

On 07/08/2013 03:29 AM, Alain Ketterlin wrote:
....
sscanf has primitive pattern matching, which is useful for simple cases,
e.g.,

n = sscanf(somestring,"(%d,%d)",&x,&y);

(scanf has the same capabilities I think; I never use it).

"The sscanf function is equivalent to fscanf, except that input is
obtained from a string (specified by the argument s) rather than from a
stream." 7.21.6.7p2.

Note that if the input string represents a number too large to be stored
in an 'int', the behavior is undefined (7.21.6.2p10). This is a problem
that can be avoided by using strtol() instead; but at the cost of using
a more complicated interface.
I don't know whether this is standard, though.

Very much so.
 
B

Bill Cunningham

Barry said:
scanf extracts data from the stdin stream. sscanf extracts data form
a string. Both functions ignore leading white space characters when
extracting strings or numbers. Thus it is possible that scanf will
silently skip to the next line. If you don't want this to happen, you
use fgets to read an entire line and sscanf to process the data. The
string produced by fgets will never contain more than one line of data
from the file or stream.

There are also times when you may want to process the data multiple
times, possibly with different conversion specifications. Once scanf
has read the data, it is no longer in the stream so you cannot
reprocess it. On the other hand, sscanf does not destroy the data in
the string so you can process it repeatedly if needed.


With either scanf or sscanf, the %s format will not extract a string
with embedded spaces or other white space characters. Thus %s can not
be used to read a name like John Doe. Both functions would stop at
the space and extract the string John. If you use fgets, you could
then use strncpy or a similar function to extract both the first and
last names to a single string.

The problem does not exist with other specifiers since you cannot have
embedded white space in a number and %c does not treat white space as
special.

Thanks much. That answers my question.
 
J

James Kuyper

On 07/08/2013 05:12 AM, Nobody wrote:
....
fgets()+sscanf() is appropriate when newlines are significant, i.e. each
"chunk" of input is on its own line. If the input contains too few values,
fgets()+sscanf() will parse one line of input and tell you how many
values it obtained, whereas fscanf() will start reading values from the
next line().

fscanf() is appropriate when newlines are merely whitespace ...
True

... (e.g. as is
the case for C source code).

Not true. In phase 7, "White-space characters separating tokens are no
longer significant", which renders new-line characters outside of tokens
insignificant (new-line characters can occur inside of character
constant and string literal tokens as a result of translation of \n
escape sequences during phase 6). However, many features of C which are
implemented prior to phase 7 depend upon correctly distinguishing
between new-line characters and other white-space characters:

Phase 2: "Each instance of a backslash character (\) immediately
followed by a new-line character is deleted, splicing physical source
lines to form logical source lines."

Phase 3:
* It is a syntax error for a header name, character constant, or string
literal to contain a new-line character.

Phase 4:
* The # character that distinguishes pre-processing directives must be
the first non-whitespace character after a new-line character or the
start of the source code file.
* Preprocessing directives are terminated by new-line characters - even
if doing so would interrupt what would otherwise be the invocation of a
function-like macro.
* __LINE__ must expand into 1 more than then number of new-line
characters were read during translation phase 1 at the point where that
token is parsed.
* assert(condition) must expand into code which, if condition is false,
causes (among other things) the line number to be printed out. The most
obvious way to do this is by use of __LINE__, though that's not required.

....
I presume that it refers to the fact that "%s" will copy an arbitrary
number of characters into the buffer pointed to by the corresponding
argument. If the number of characters exceeds the size of the buffer, you
get an overflow.

Note that %[ has the same issue.

Buffer overflow can be avoided by specification of a maximum field
width: "%32s". This is even mentioned in a footnote to the FAQ
<http://www.c-faq.com/stdio/overflow.html>
 
J

John Gordon

In said:
What would be a practical reason to use sscanf? I read an example of how
it works but I can pretty much use scanf to do the same thing.

scanf consumes its input directly from the input stream. Once scanf reads
something, it's gone; you can't go back and read it again.
 
K

Ken Brody

scanf consumes its input directly from the input stream. Once scanf reads
something, it's gone; you can't go back and read it again.

And, IIRC, if it encounters an error, scanf() leaves the rest of the line in
the input stream, possibly leading to other problems.
 
K

Keith Thompson

David Harmon said:
On Sun, 7 Jul 2013 22:03:14 -0400 in comp.lang.c, "Bill Cunningham"


The problem is that people forget that the length specification is
*essential* to using %s safely.

sscanf can be used safely with "%s", if you exercise caerful control
over the string being scanned. Such control is (usually) not possible
for scanf, which reads from stdin.
 

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

Scanf is being prioritized over printf ? 1
scanf() 2
question about scanf 11
sscanf to parse? 7
sscanf question 31
scanf() 32
scanf internals 11
sscanf help 7

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top