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