print binary

K

Keith Thompson

CBFalconer said:
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.
[...]

Alas, this is not true; there's no reliable way to check for overflow.

C99 7.19.6.2p10:

If this object does not have an appropriate type, or if the result
of the conversion cannot be represented in the object, the
behavior is undefined.
 
C

CBFalconer

Keith said:
.... snip ...
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.
[...]

Alas, this is not true; there's no reliable way to check for
overflow.

C99 7.19.6.2p10:
If this object does not have an appropriate type, or if the
result of the conversion cannot be represented in the object,
the behavior is undefined.

Well, here is an extract from some of my code. It doesn't include
helper routines, such as 'ignoreblks', 'skipwhite', and 'flushln'.
This has the advantage of working on streams and needing no
buffers. It should be revised to input an unsigned long. Signed
input calls this.

/*--------------------------------------------------------------
* Read an unsigned value. Signal error for overflow or no
* valid number found. Returns 1 for error, 0 for noerror, EOF
* for EOF encountered before parsing a value.
*
* Skip all leading blanks 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, 0 result, and the next 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 '-'.
*/
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 */

ch = ignoreblks(f);

if (EOF == ch) status = EOF;
else if (isdigit(ch)) status = 0; /* digit, no error */

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

*wd = value;
ungetc(ch, f);
return status;
} /* readxwd */
 
V

vippstar

... snip ...
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.

[...]

Alas, this is not true; there's no reliable way to check for overflow.

C99 7.19.6.2p10:

If this object does not have an appropriate type, or if the result
of the conversion cannot be represented in the object, the
behavior is undefined.
Are you saying that scanf("%d", &intvariable); is _not_ safe even if
the return value of scanf() is properly checked?
Which input would break it?
 
C

CBFalconer

Keith Thompson said:
.... snip ...
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.

[...]

Alas, this is not true; there's no reliable way to check for
overflow.

C99 7.19.6.2p10:

If this object does not have an appropriate type, or if the
result of the conversion cannot be represented in the object,
the behavior is undefined.

Are you saying that scanf("%d", &intvariable); is _not_ safe
even if the return value of scanf() is properly checked?
Which input would break it?

Yes. Any value larger than INT_MAX or smaller than INT_MIN.
 
S

santosh

CBFalconer said:
Flash Gordon wrote:
Kapteyn's Star wrote:
... snip ...

scanf is generally a poor choice of function for user input.
Better to use fgets and then pass the entered line possibly
using sscanf. Whatever you use you should check the value
returned by the input function.
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.

[...]

Alas, this is not true; there's no reliable way to check for
overflow.

C99 7.19.6.2p10:

If this object does not have an appropriate type, or if the
result of the conversion cannot be represented in the object, the
behavior is undefined.
Are you saying that scanf("%d", &intvariable); is _not_ safe even if
the return value of scanf() is properly checked?
Which input would break it?

An input sequence that would cause overflow upon assignment would break
it. In this case undefined behaviour is invoked, which means that scanf
is free to do anything. It might or might not set errno. That's QoI. A
signal might also be raised.

The only way to detect overflow is to either convert manually or employ
the strto* family of functions.
 
V

vippstar

Flash Gordon wrote:
Kapteyn's Star wrote:
... snip ...
scanf("%d",&val);
scanf is generally a poor choice of function for user input.
Better to use fgets and then pass the entered line possibly
using sscanf. Whatever you use you should check the value
returned by the input function.
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.
[...]
Alas, this is not true; there's no reliable way to check for
overflow.
C99 7.19.6.2p10:
If this object does not have an appropriate type, or if the
result of the conversion cannot be represented in the object, the
behavior is undefined.
Are you saying that scanf("%d", &intvariable); is _not_ safe even if
the return value of scanf() is properly checked?
Which input would break it?

An input sequence that would cause overflow upon assignment would break
it. In this case undefined behaviour is invoked, which means that scanf
is free to do anything. It might or might not set errno. That's QoI. A
signal might also be raised.
The only way to detect overflow is to either convert manually or employ
the strto* family of functions.
What about this: scanf("%4d", &inttype);
Surely that's safe, is it not?
I always thought scanf() could detect/avoid overflow. I start to
dislike scanf and friends.
 
S

santosh

Flash Gordon wrote:
Kapteyn's Star wrote:
... snip ...

scanf is generally a poor choice of function for user input.
Better to use fgets and then pass the entered line possibly
using sscanf. Whatever you use you should check the value
returned by the input function.
Actually scanf is a quite safe way to input single (emphasize
single) numeric values interactively, as long as you check its
return value.

Alas, this is not true; there's no reliable way to check for
overflow.
C99 7.19.6.2p10:
If this object does not have an appropriate type, or if the
result of the conversion cannot be represented in the object,
the behavior is undefined.
Are you saying that scanf("%d", &intvariable); is _not_ safe even
if the return value of scanf() is properly checked?
Which input would break it?

An input sequence that would cause overflow upon assignment would
break it. In this case undefined behaviour is invoked, which means
that scanf is free to do anything. It might or might not set errno.
That's QoI. A signal might also be raised.
The only way to detect overflow is to either convert manually or
employ the strto* family of functions.
What about this: scanf("%4d", &inttype);

Yes, I think this would be safe from overflow, but it rather restricts
the utility of the function, doesn't it? :)
Surely that's safe, is it not?
I always thought scanf() could detect/avoid overflow. I start to
dislike scanf and friends.

The scanf family of functions I understand were created in an era when
computers where operated only by trained specialists and garbage or
malformed input was most unlikely. It's still useful for reading
strictly formatted input from trusted sources, but not very robust for
program that might receive input interactively and from anyone. In
practise though, overflow is often not dealt with at all, or only very
rarely.
 
C

CBFalconer

santosh said:
(e-mail address removed) wrote:
.... snip ...


An input sequence that would cause overflow upon assignment would
break it. In this case undefined behaviour is invoked, which means
that scanf is free to do anything. It might or might not set errno.
That's QoI. A signal might also be raised.

The only way to detect overflow is to either convert manually or
employ the strto* family of functions.

Not so. Writing a routine that does what you want is adequate.
 
K

Keith Thompson

santosh said:
The scanf family of functions I understand were created in an era when
computers where operated only by trained specialists
Ok.

and garbage or
malformed input was most unlikely.

Oh really?

I think it's more likely that it was before the idea of "undefined
behavior" had been introduced. Programmers knew what happened on
overflow (typically silent wraparound, so entering "65535" when an int
was expected would yield -1). Or at least they knew what happened on
the system they were using, and didn't worry so much about what might
happen on other systems.

There was probably also an attitude that it's the user's
responsibility to provide correct input, not the programmer's
responsibility to handle bad input gracefully.

See also gets().

When the language was standardized, it wasn't considered practical to
define a single behavior for all systems, so it was left undefined.
 

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

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top