Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Proper use of scanf

Reply
Thread Tools

Proper use of scanf

 
 
Jean-Claude Arbaut
Guest
Posts: n/a
 
      06-20-2005



On 20/06/2005 05:19, Jack Klein wrote:

> On Sun, 19 Jun 2005 02:08:52 +0200, Jean-Claude Arbaut
> <(E-Mail Removed)> wrote in comp.lang.c:
>
>>

> That's actually not a reference to how to use the function safely, nor
> even a recommendation that it should be used.
>
> See 7.19.7.7, which describes the gets() function, and includes not so
> much as a hint of a warning about buffer overflows.


Oopss


> The general consensus here, which I agree with, is that the *scanf()
> functions are best avoided by all except extreme experts on their use.
> If non-experts avoid them, the will never become extreme experts,
> making the point moot.


Anyway it's certainly good practice not to use a function when one has
doubts on its use. Concerning scanf, it's rarely useful, because of its
strange behaviour, at least on some implementations (if I remember well, you
may enter an infinite loop if you enter wrong data when an integer is
expected, not merely because of scanf, because of the program that uses it).
I mainly use it in toy programs.

 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      06-20-2005
Jack Klein wrote:
> [...]
> The general consensus here, which I agree with, is that the *scanf()
> functions are best avoided by all except extreme experts on their use.
> If non-experts avoid them, the will never become extreme experts,
> making the point moot.


I'd agree that scanf() and fscanf() are best avoided,
but sscanf() is both usable and useful. fgets()/sscanf()
make a good combination.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
 
 
 
robert.thorpe@antenova.com
Guest
Posts: n/a
 
      06-20-2005
Lefty Bigfoot wrote:
> Hello,
>
> I am aware that a lot of people are wary of using scanf,
> because doing it improperly can be dangerous. I have
> tried to find a good tutorial on all the ins and outs
> of scanf() but been unsuccessful.
>
> Is there a well-respected (by the c.l.c crowd) book
> or tutorial that really covers scanf in detail?


There is also a useful reference in the documentation of the GNU
standard C library

http://www.gnu.org/software/libc/man...ut%20Functions

This also mentions many GNU extensions though.

 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      06-20-2005
Eric Sosman <(E-Mail Removed)> writes:

> I'd agree that scanf() and fscanf() are best avoided,
> but sscanf() is both usable and useful.


Only if one doesn't mind the nasal demons that are emitted when a
conversion's value cannot be represented in the object it is
stored into, e.g. when an out-of-range number is read.
--
"The expression isn't unclear *at all* and only an expert could actually
have doubts about it"
--Dan Pop
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-20-2005


Ben Pfaff wrote:
> Eric Sosman <(E-Mail Removed)> writes:
>
>
>> I'd agree that scanf() and fscanf() are best avoided,
>>but sscanf() is both usable and useful.

>
>
> Only if one doesn't mind the nasal demons that are emitted when a
> conversion's value cannot be represented in the object it is
> stored into, e.g. when an out-of-range number is read.


Hmmm ... I'd always assumed that'd be a "matching
failure," but no: trying to derive an eight-bit `char'
value from "666" is, indeed, U.B. You learn something
new every day.

--
(E-Mail Removed)

 
Reply With Quote
 
Jack Klein
Guest
Posts: n/a
 
      06-21-2005
On Mon, 20 Jun 2005 07:39:46 -0400, Eric Sosman
<(E-Mail Removed)> wrote in comp.lang.c:

> Jack Klein wrote:
> > [...]
> > The general consensus here, which I agree with, is that the *scanf()
> > functions are best avoided by all except extreme experts on their use.
> > If non-experts avoid them, the will never become extreme experts,
> > making the point moot.

>
> I'd agree that scanf() and fscanf() are best avoided,
> but sscanf() is both usable and useful. fgets()/sscanf()
> make a good combination.


As Ben already pointed out, all the members of *scanf() produce
undefined behavior if the result of a numeric conversion is out of
range for the destination type.

Which means to use them safely, you need to pre-check the numeric
digits before converting. If you are going to check them by hand, you
might as well do the conversion yourself, it takes little additional
effort.

Now fgets() and { strol(), strtod(), strtoul(), strtoll(), stroull() }
make a robust combination.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      06-21-2005
Jack Klein wrote:
> On Mon, 20 Jun 2005 07:39:46 -0400, Eric Sosman
> > Jack Klein wrote:

>
>>> [...]
>>> The general consensus here, which I agree with, is that the
>>> *scanf() functions are best avoided by all except extreme
>>> experts on their use. If non-experts avoid them, the will
>>> never become extreme experts, making the point moot.

>>
>> I'd agree that scanf() and fscanf() are best avoided,
>> but sscanf() is both usable and useful. fgets()/sscanf()
>> make a good combination.

>
> As Ben already pointed out, all the members of *scanf() produce
> undefined behavior if the result of a numeric conversion is out
> of range for the destination type.
>
> Which means to use them safely, you need to pre-check the numeric
> digits before converting. If you are going to check them by hand,
> you might as well do the conversion yourself, it takes little
> additional effort.
>
> Now fgets() and { strol(), strtod(), strtoul(), strtoll(),
> stroull() } make a robust combination.


The only problem with that is that you have to assign a buffer. I
have published some routines which operate directly on the input
stream, and need no buffers (as does scanf). However my routines
are not variadic, and do not involve loading a large interpreter
system. They also have comprehensive error reporting, and do such
things as absorbing a complete numeric field even when the value
overflows. These are worthwhile considerations, especially in a
resource starved embedded system.

The following is a sample of the routines:

/*--------------------------------------------------------------
* Read an unsigned value. Signal error for overflow or no
* valid number found. Returns true for error, false for noerror
*
* Skip all leading whitespace on f. At completion getc(f) will
* return the character terminating the number, which may be \n
* or EOF among others. Barring EOF it will NOT be a digit. The
* combination of error, zero, and the following getc returning
* \n indicates that no numerical value was found on the line.
*
* If the user wants to skip all leading white space including
* \n, \f, \v, \r, he should first call "skipwhite(f);"
*
* Peculiarity: This specifically forbids a leading '+' or '-'.
* Peculiarity: This forbids overflow, unlike C unsigned usage.
* on overflow, UINT_MAX is returned.
*/
int readxwd(unsigned int *wd, FILE *f)
{
unsigned int value, digit;
int status;
int ch;

#define UWARNLVL (UINT_MAX / 10U)
#define UWARNDIG (UINT_MAX - UWARNLVL * 10U)

value = 0; /* default */
status = 1; /* default error */

do {
ch = getc(f);
} while ((' ' == ch) || ('\t' == ch)); /* skipblanks */
/* while (isblank((UCHAR)ch)); */ /* for C99 */

if (!(EOF == ch)) {
if (isdigit((UCHAR)ch)) /* digit, no error */
status = 0;
while (isdigit((UCHAR)ch)) {
digit = (unsigned) (ch - '0');
if ((value < UWARNLVL) ||
((UWARNLVL == value) && (UWARNDIG >= digit)))
value = 10 * value + digit;
else { /* overflow */
status = 1;
value = UINT_MAX;
}
ch = getc(f);
} /* while (ch is a digit) */
}
*wd = value;
ungetc(ch, f);
return status;
} /* readxwd */

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html


 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      06-21-2005
CBFalconer wrote:
> ...
> int ch;
> ch = getc(f);
> ...
> if (!(EOF == ch)) {
> if (isdigit((UCHAR)ch)) /* digit, no error */


Since getc already returns a value in the range of unsigned
char, there's nothing to gain by adding the UCHAR (presumably
unsigned char) cast.

If you're worried that UCHAR_MAX > INT_MAX, then you should
be performing a specific feof check.

> status = 0;
> while (isdigit((UCHAR)ch)) {
> digit = (unsigned) (ch - '0');
> if ((value < UWARNLVL) ||
> ((UWARNLVL == value) && (UWARNDIG >= digit)))
> value = 10 * value + digit;
> else { /* overflow */
> status = 1;
> value = UINT_MAX;
> }
> ch = getc(f);
> } /* while (ch is a digit) */


For unsigned int, you can simplify the overflow check to...

while (isdigit(ch))
{
new_value = 10 * value + ch - '0';
if (new_value < value) { status = 1; new_value = -1; }
value = new_value;
ch = getc(f);
}

--
Peter

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005? =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 18 05-02-2006 10:53 AM
scanf (yes/no) - doesn't work + deprecation errors scanf, fopen etc. =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 185 04-03-2006 02:49 PM
how to use scanf()? =?utf-8?B?55ee5a2Q?= C Programming 1 05-24-2005 07:10 AM
why to use '&' in scanf( ) but not in printf( ) sushant C Programming 4 01-10-2005 04:22 PM
Proper way to use an imported constant under 'use strict'? H. Wade Minter Perl Misc 8 04-25-2004 12:58 AM



Advertisments