Re: Proper use of scanf



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


.



Relevant Pages

  • Bulletproof reading of ints (was Re: string concatenation)
    ... this overflow is not caught. ... not happy with the EOF treatment on systems with non-sticky EOF ... return positive int for error, 0 for no error, and EOF for EOF. ... /* These stream input routines are written so that simple ...
    (comp.unix.programmer)
  • Bulletproof reading of ints (was Re: string concatenation)
    ... this overflow is not caught. ... not happy with the EOF treatment on systems with non-sticky EOF ... return positive int for error, 0 for no error, and EOF for EOF. ... /* These stream input routines are written so that simple ...
    (comp.lang.c)
  • Re: integer overflow in atoi
    ... int i, num; ... range of int? ... overflow. ... Telling whether you can add a digit between 0 and 9 is the easy ...
    (comp.lang.c)
  • Re: size_t overflow
    ... than overflow. ... question is about size_t arithmetics. ... means all computations involving unsigned char promoted to int, ... After promotion to int, ...
    (comp.std.c)
  • Re: dynamic vs. static: the age-old debate
    ... int addx+y; ... orthogonal to static/dynamic/soft typing. ... $ dynamic-compiler program.source -o program ... will overflow, leaving the "overflow behavior is ...
    (comp.lang.misc)