scanf or n/scanf 
Author Message
 scanf or n/scanf

Many thanx for the input about returning info from functions and arrays.
Someone mentioned that scanf was a poor choice to take input from a stdin.
I also read something to that effect. An example was given using the
following code (Practical C;O'Reilly):

main() {

    char line[MAXV];
    int value;

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

    /* do something with value */

    return;

Quote:
}

Is this a good substitute? I can't find much on sscanf function in either
of my books so I am dubious about it's robustness(?) and behavior. I am
also i need of an explanation as to the problem with scanf. What I have
read sort of mentions the problem as poor end of line handling. I haven't
yet come across this problem but I am quite novice yet. Any takers?

 _____________________________________________________________________________

 Timothy A. Sherwood                                  

  http://www.*-*-*.com/ ~tasst15
 ______________________________________________________________________________

 Faber est quisque fortunae suae.

"There are many matters which remain to be investigated concerning the
attributes of God and the nature of myself or my mind; and perhaps I shall
take these up at another time. "
                                --Descartes, 5th Meditation
--



Sun, 05 Nov 2000 03:00:00 GMT  
 scanf or n/scanf


Quote:

> Someone mentioned that scanf was a poor choice to take input from a stdin.

I did.  Maybe others, too.

Quote:
> I also read something to that effect. An example was given using the
> following code (Practical C;O'Reilly):

Remember to include stdio.h first.

Quote:
> main() {

>     char line[MAXV];
>     int value;

>     fgets(line, sizeof(line), stdin);
>     sscanf(line, %d, &value);

>     /* do something with value */

>     return;

Remember that main has type int (which *is* implied when you leave out
the type, so that's all right), so the return statement should have an
int as a parameter.  Usually 0 or EXIT_SUCCESS to denote successful
termination.

Quote:
> }
> Is this a good substitute?

Well, it is one that I often use.  Also, note that you may want to test
the return values of fgets and sscanf in real code.

Quote:
>  I can't find much on sscanf function in either
> of my books so I am dubious about it's robustness(?) and behavior.

It is perfectly standardized, and should be just as robust as the other
..scanf functions.  It uses the same format string as the others.
Possibly, the format string and return value is described in detail
under scanf or fscanf, so the writer has neglected to go in detail for
the other ..scanf functions.

Quote:
>  I am
> also i need of an explanation as to the problem with scanf. What I have
> read sort of mentions the problem as poor end of line handling. I haven't
> yet come across this problem but I am quite novice yet. Any takers?

Well, for one thing, simply pressing return before you have exhausted
the specifiers in the format string will not make the function return at
all.  It will just be taken as whitespace, while the function still
waits for the user to satisfy the next specifier.  Only when all the
specifiers have been exhausted, or the user typed a character that could
not be interpreted for the specifier, will the function return.

And once all specifiers *have* been exhausted, the function returns
immediately, and leaves any remaining characters on the line unread for
the next call, including the newline character.  Unless the format
string ends with a whitespace character (such as space, or, indeed,
newline), scanf will *continue* to read whitespace and won't return
until you've typed a non-whitespace character.  To read up to and
including the newline character, you have to end the scanf format string
with something like:

        "%*[^\n]%*c"

Rather unwieldy.

Yngvar
--



Sat, 11 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

Quote:

> Many thanx for the input about returning info from functions and arrays.
> Someone mentioned that scanf was a poor choice to take input from a stdin.
> I also read something to that effect. An example was given using the
> following code (Practical C;O'Reilly):

> main() {

>     char line[MAXV];
>     int value;

>     fgets(line, sizeof(line), stdin);
>     sscanf(line, %d, &value);

>     /* do something with value */

>     return;
> }
> Is this a good substitute? I can't find much on sscanf function in either
> of my books so I am dubious about it's robustness(?) and behavior. I am
> also i need of an explanation as to the problem with scanf. What I have
> read sort of mentions the problem as poor end of line handling. I haven't
> yet come across this problem but I am quite novice yet. Any takers?

sscanf behaves the same way as [f]scanf.  The difference is this: say
you've got a loop doing scanf to read input, and suppose the input
presented to your program doesn't match what scanf is trying to read.
Unless you check for such errors and handle them appropriately, you'll
read the same bad input each time through the loop, and you'll be
stuck at that place in the file.  OTOH, using fgets and sscanf, you're
guaranteed to read any line only once.  If there's a matching failure
and you ignore it, you may get bad results for that line of input, but
you will be able to continue on and process the rest of your input.

paul
--



Sat, 11 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

Groovy hepcat T.A. Sherwood was jivin' on Wed, 20 May 1998 14:06:12
GMT in comp.lang.c.moderated.
scanf or n/scanf's a cool scene! Dig it!

Quote:
>Someone mentioned that scanf was a poor choice to take input from a stdin.

  Absolutely correct. Avoid it like the plague.

#include <stdio.h>

int main(void)
{

Quote:
>    char line[MAXV];
>    int value;

>    fgets(line, sizeof(line), stdin);
>    sscanf(line, %d, &value);
>    /* do something with value */

    return 0;

Quote:
>}
>Is this a good substitute? I can't find much on sscanf function in either

  Yes, this is much better. The reason this is better is that if
sscanf() doesn't return the value expected, then the string read with
fgets() is a typographical error by the user. This is easilly
remedied. scanf() alone has many problems which make it absolutely
revolting for user input when the user makes a mistake. Even when the
user has done exactly as expected, scanf() can often be a real pain.

Quote:
>of my books so I am dubious about it's robustness(?) and behavior. I am

  sscanf()'s behaviour is (or should be) exactly the same as
scanf()'s, but using fgets() to read a full line of user input then
scanning that input with sscanf() is preferable to simply scanning the
user input directly with scanf(). The reasons are too many and varied
to go into great detail here yet again (as this is a FAQ).

Quote:
>also i need of an explanation as to the problem with scanf. What I have

  Read the FAQ list. The section entitled "Why does everyone say not
to use scanf()? What should I use instead?" is particularly pertinent
to your question.

----- Dig the EVEN NEWER, MORE IMPROVED news sig!! -----

-------------- Shaggy was here! ---------------
    http://aardvark.apana.org.au/~phaywood/
============= Ain't I'm a dawg!! ==============
--



Sat, 11 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

:main() {
:
:    char line[MAXV];
:    int value;
:
:    fgets(line, sizeof(line), stdin);
:    sscanf(line, %d, &value);  
:    
:    /* do something with value */
:
:    return;
:}
:Is this a good substitute? [for scanf]

even better if you did :
if(1==sscanf(line," %d ", &value))
   ; /* do something with value */
else
   ; /* try some other conversion */

:                   -- I can't find much on sscanf function in either
:of my books so I am dubious about it's robustness(?) and behavior. I am

Hmm ... The %n argument specifier is most useful:

int n=0;

  if(1==sscanf(line," %d %n", &value,&n))
     line+=n;/* move forwards as far as the conversions has succeeded */

But I am not sure if the above piece of code will make one conversion or
two. From Linux man:
.................................................................
       n      Nothing is expected; instead, the number of charac-
              ters consumed thus far from  the  input  is  stored
              through  the  next pointer, which must be a pointer
              to int.  This is not a conversion, although it  can
              be  suppressed  with  the  *  flag.  The C standard
              says: `Execution of a %n directive does not  incre-
              ment  the  assignment count returned at the comple-
              tion of execution' but  the  Corrigendum  seems  to
              contradict  this.  Probably  it is wise not to make
              any assumptions on the effect of %n conversions  on
              the return value.
.................................................................

So for the robustness:
  if(1==sscanf(line," %d %*n", &value,&n))
  /* etc, etc ... */

:also i need of an explanation as to the problem with scanf. What I have
:read sort of mentions the problem as poor end of line handling. I haven't
:yet come across this problem but I am quite novice yet. Any takers?

Dunno about end of line.

 (
  )
c[]  // Jens M Andreasen
--



Sat, 11 Nov 2000 03:00:00 GMT  
 scanf or n/scanf


Quote:

>:main() {
>:
>:    char line[MAXV];
>:    int value;
>:
>:    fgets(line, sizeof(line), stdin);
>:    sscanf(line, %d, &value);  
>:    
>:    /* do something with value */
>:
>:    return;
>:}
>:Is this a good substitute? [for scanf]

>even better if you did :
>if(1==sscanf(line," %d ", &value))

And even better:

    if (sscanf(line," %d ", &value) == 1)

Since ``sscanf(line," %d ", &value) = 1'' is illegal code anyway,
reversing the operands of the == operator only obfuscates the code,
without buying you anything.

Dan
--
Dan Pop
CERN, IT Division

Mail:  CERN - PPE, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland
--



Mon, 13 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

Quote:


> >even better if you did :
> >if(1==sscanf(line," %d ", &value))

> And even better:

>     if (sscanf(line," %d ", &value) == 1)

> Since ``sscanf(line," %d ", &value) = 1'' is illegal code anyway,
> reversing the operands of the == operator only obfuscates the code,
> without buying you anything.

It's obfuscated only if it's not what you're used to.  If a program
uses `if (constant==expression)' everywhere else to protect against
accidental assignment, it would be inconsistent to switch the order in
this case.
`(expression==constant)' may be easier on the eyes for most of us, but
there's no objective reason to prefer it, AFAIK.

paul
--



Tue, 14 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

Quote:


> >even better if you did :
> >if(1==sscanf(line," %d ", &value))
> And even better:
>     if (sscanf(line," %d ", &value) == 1)
> Since ``sscanf(line," %d ", &value) = 1'' is illegal code anyway,
> reversing the operands of the == operator only obfuscates the code,
> without buying you anything.

No?  If a programmer was flawless, it wouldn't matter.  Since nobody
are, the point would be to write the comparison in a way that minimizes
the chance of a mistake passing through uncaught by the compiler.

And it seems to me that deciding if the variable part of the comparison
is an lvalue or not would be *more* work than writing == correctly is in
the first place.  It would reduce the risk of an error creeping through,
as it sould only happen when you *both* typed = for == *and* by mistake
put an lvalue to the left.  But if you *always* put the constant to the
left, it wouldn't happen at all.

Granted, it is by far more common to put the constant to the right.
However, if you find advantages to putting it to the left in *some*
cases, and the two ways are equivalent (as they are), what's wrong with
being consistent throughout your code?

Yngvar
--



Thu, 16 Nov 2000 03:00:00 GMT  
 scanf or n/scanf



Quote:
>even better if you did :
>if(1==sscanf(line," %d ", &value))
>   ; /* do something with value */
>else
>   ; /* try some other conversion */

Others have already griped about the "constant == expr" form, but this
is a style choice, even if I happen to disagree with it. :-)

More interesting are the spaces in the " %d " directive.  In this
case, they serve no useful purpose.  Whitespace in a scanf-family
directive means "skip whitespace in the input stream", but a "%d"
conversion also implies "skip leading whitespace".  The second blank
will then skip subsequent whitespace in the string, but since there
are no further directives, this is useless effort.  If there were
more directives, it would have an effect:

Quote:
>Hmm ... The %n argument specifier is most useful:

>int n=0;
>  if(1==sscanf(line," %d %n", &value,&n))
>     line+=n;/* move forwards as far as the conversions has succeeded */

Here the first blank is redundant with the %d conversion, but the
second blank will skip any trailing whitespace before applying the
`%n' directive.

As Jens Andreasen quotes from the Linux man page, %n's total effect
is a bit confusing; it was also an ANSI addition, and may not exist
in some older, non-standard compilers.  Another alternative is to
break up the input manually (e.g., via strtok() or strspn()/strcspn()
or a series of calls to strtol(), strtod(), etc.).
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc

Antispam notice: unsolicited commercial email will be handled at my
consulting rate; pyramid-scheme mail will be forwarded to the FTC.
--



Mon, 20 Nov 2000 03:00:00 GMT  
 scanf or n/scanf



Quote:


> writes:

>> >even better if you did :
>> >if(1==sscanf(line," %d ", &value))

>> And even better:

>>     if (sscanf(line," %d ", &value) == 1)

>> Since ``sscanf(line," %d ", &value) = 1'' is illegal code anyway,
>> reversing the operands of the == operator only obfuscates the code,
>> without buying you anything.

>No?  If a programmer was flawless, it wouldn't matter.  Since nobody
>are, the point would be to write the comparison in a way that minimizes
>the chance of a mistake passing through uncaught by the compiler.

In my experience by far the best solution is to make use of a compiler
or lint utility that warns about assignment in a test context. That
detects problems that the reversal method does not, and allows the programmer
to concentrate on writing clear, readable code which is important.

Quote:
>And it seems to me that deciding if the variable part of the comparison
>is an lvalue or not would be *more* work than writing == correctly is in
>the first place.  It would reduce the risk of an error creeping through,
>as it sould only happen when you *both* typed = for == *and* by mistake
>put an lvalue to the left.  But if you *always* put the constant to the
>left, it wouldn't happen at all.

>Granted, it is by far more common to put the constant to the right.
>However, if you find advantages to putting it to the left in *some*
>cases, and the two ways are equivalent (as they are), what's wrong with
>being consistent throughout your code?

It makes code less readable (at least to the majority of other people).
I don't think that the reversal method is consistent with the
logical interpretation of code. The example above is effectively putting
the result before the calculation which is unnatural.

--
-----------------------------------------


-----------------------------------------
--



Wed, 22 Nov 2000 03:00:00 GMT  
 scanf or n/scanf


[snip]

Quote:
> ...If a programmer was flawless, it wouldn't matter.  Since nobody
> are

 ^^^ is.
What was are; proof of concept? ;p

Cheers, g.

gary         -=-  The C Programmers' Reference  -=-
              http://www.gator.net/~garyg/C/c.html
        -=-  Avenue Programmers' Classes' Requests  -=-
             http://www.gator.net/~garyg/class.htm
--



Sun, 26 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

Quote:








Quote:
>> writes:

>>> >even better if you did :
>>> >if(1==sscanf(line," %d ", &value))
[SNIP]
>>No?  If a programmer was flawless, it wouldn't matter.  Since nobody
>>are, the point would be to write the comparison in a way that minimizes
>>the chance of a mistake passing through uncaught by the compiler.

>In my experience by far the best solution is to make use of a compiler
>or lint utility that warns about assignment in a test context. That
>detects problems that the reversal method does not, and allows the
programmer
>to concentrate on writing clear, readable code which is important.
[SNIP8<]
>>Granted, it is by far more common to put the constant to the right.
>>However, if you find advantages to putting it to the left in *some*
>>cases, and the two ways are equivalent (as they are), what's wrong with
>>being consistent throughout your code?

>It makes code less readable (at least to the majority of other people).
>I don't think that the reversal method is consistent with the
>logical interpretation of code. The example above is effectively putting
>the result before the calculation which is unnatural.

Uncommon, maybe, but why unnatural?  In those cases where you have a
constant to compare to, isn't that constant determined _before_ the
calculation?  (In fact, pre-determined!)  Therefore if you are adopting a
"natural order == order of computation" the constant should come first.

What you're probably experiencing is the unnatural way that reading the
expression "sounds" since in English we usually express the computation and
then the condition.  I don't think that the bias of our natural language
should carry more weight than catching potential errors.  It is quite easy
to get used to reading comparisons with the constant first.

--



Sun, 26 Nov 2000 03:00:00 GMT  
 scanf or n/scanf

Quote:


> >No?  If a programmer was flawless, it wouldn't matter.  Since nobody
> >are, the point would be to write the comparison in a way that minimizes
> >the chance of a mistake passing through uncaught by the compiler.


Quote:

> In my experience by far the best solution is to make use of a compiler
> or lint utility that warns about assignment in a test context. That
> detects problems that the reversal method does not, and allows the programmer
> to concentrate on writing clear, readable code which is important.

For the record, this *is* what I do, so we don't really disagree much.
However, it does depend on the compiler producing diagnostics for
something that isn't an error.  Occasionally, I really do want to make
an assignment in such a context, and so I have to insert an extra
comparison to zero, which also involves an extra level of parentheses.

I wrote the above not as an argument about whether the technique is
appropriate in the first place, but just, given that it *is* used,
whether it should be used all the time or only when you knew that the
variable part was an lvalue.

Quote:
> It makes code less readable (at least to the majority of other people).
> I don't think that the reversal method is consistent with the
> logical interpretation of code. The example above is effectively putting
> the result before the calculation which is unnatural.

It puts the constant that is being compared to before the calculation.
The result is not in the code.  It is evaluated at runtime.

Yngvar
--



Sun, 26 Nov 2000 03:00:00 GMT  
 scanf or n/scanf



Quote:


>> >No?  If a programmer was flawless, it wouldn't matter.  Since nobody
>> >are, the point would be to write the comparison in a way that minimizes
>> >the chance of a mistake passing through uncaught by the compiler.



>> In my experience by far the best solution is to make use of a compiler
>> or lint utility that warns about assignment in a test context. That
>> detects problems that the reversal method does not, and allows the programmer
>> to concentrate on writing clear, readable code which is important.

>For the record, this *is* what I do, so we don't really disagree much.
>However, it does depend on the compiler producing diagnostics for
>something that isn't an error.  Occasionally, I really do want to make
>an assignment in such a context, and so I have to insert an extra
>comparison to zero, which also involves an extra level of parentheses.

That is a very good thing to do anyway since it is an indication to anybody
reading the code that that is really what you intended.

Quote:
>I wrote the above not as an argument about whether the technique is
>appropriate in the first place, but just, given that it *is* used,
>whether it should be used all the time or only when you knew that the
>variable part was an lvalue.

IMO this technique is most beneficial when it is used consistently.

Quote:
>> It makes code less readable (at least to the majority of other people).
>> I don't think that the reversal method is consistent with the
>> logical interpretation of code. The example above is effectively putting
>> the result before the calculation which is unnatural.

>It puts the constant that is being compared to before the calculation.
>The result is not in the code.  It is evaluated at runtime.

I'm referring to how somebody looking at the source code interprets it.

--
-----------------------------------------


-----------------------------------------
--



Tue, 28 Nov 2000 03:00:00 GMT  
 scanf or n/scanf



Quote:








>>> writes:

>>>> >even better if you did :
>>>> >if(1==sscanf(line," %d ", &value))
>[SNIP]
>>>No?  If a programmer was flawless, it wouldn't matter.  Since nobody
>>>are, the point would be to write the comparison in a way that minimizes
>>>the chance of a mistake passing through uncaught by the compiler.

>>In my experience by far the best solution is to make use of a compiler
>>or lint utility that warns about assignment in a test context. That
>>detects problems that the reversal method does not, and allows the
>programmer
>>to concentrate on writing clear, readable code which is important.
>[SNIP8<]
>>>Granted, it is by far more common to put the constant to the right.
>>>However, if you find advantages to putting it to the left in *some*
>>>cases, and the two ways are equivalent (as they are), what's wrong with
>>>being consistent throughout your code?

>>It makes code less readable (at least to the majority of other people).
>>I don't think that the reversal method is consistent with the
>>logical interpretation of code. The example above is effectively putting
>>the result before the calculation which is unnatural.
>Uncommon, maybe, but why unnatural?  In those cases where you have a
>constant to compare to, isn't that constant determined _before_ the
>calculation?  (In fact, pre-determined!)  Therefore if you are adopting a
>"natural order == order of computation" the constant should come first.

How the compiler deals with it is not important (I suspect that in most
cases the constant will be accessed in the object code after the function
has returned). What is important is how people read and interpret the code.
The constant isn't important until after the function has returned. Put
it before the function call then it has to be remembered while the function
call is analysed. Putting it after brings both the constant and the
return value from the function close to where they will be used i.e.
for the comparison. It is the form most people expect and are used to
and it works well for a natural left-to-right reading of the code.

As an interesting parallel compilers have a choice of what order to evaluate
the operands of operators such as + and ==. A common heuristic for this
is that the most complex expression (where the compiler will have some
measure of omplexity built in) is evaluated first. That reduces the
maximum amount of information that the runtime code has to hold at any
one time. That is in effect an overall reduction in complexity. The
same principles can be applied to source code if you assume that it is
most natually read left to right (or in a generally forwards direction
in the source file).

Quote:
>What you're probably experiencing is the unnatural way that reading the
>expression "sounds" since in English we usually express the computation and
>then the condition.  I don't think that the bias of our natural language
>should carry more weight than catching potential errors.  It is quite easy
>to get used to reading comparisons with the constant first.

It would be a big mistake to ignore natural language issues when writing
source code, natural language is what the human mind is designed to be
good at. My point is that there are much better ways of catching the
potential errors than this.

--
-----------------------------------------


-----------------------------------------
--



Tue, 28 Nov 2000 03:00:00 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. scanf("%s", string) or scanf("%s", &string)? Both work, yet...

2. scanf doesnt take doubles???

3. "scanf" function with assignment-suppression

4. Scanf problems

5. Buffer overflow Protection for Scanf

6. Widespread bug in scanf?

7. fgets vs scanf

8. scanf

9. scanf: is this a bug?

10. Using getchar() instead of fgets or scanf

11. source-code for scanf-functions

12. Format specifiers and scanf

 

 
Powered by phpBB® Forum Software