Code unnecessarily overflows when scanning INT_MIN
. parse_int(char **s) parse_int(char **s) offers a candidate solution.
Code unnecessarily overflows when scanning INT_MIN
. parse_int(char **s) offers a candidate solution.
Code unnecessarily overflows when scanning INT_MIN
. parse_int(char **s) offers a candidate solution.
One character of pushback is guaranteed. If the
ungetc
function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail. C11dr §7.21.7.10 3
One character of pushback is guaranteed. If the
ungetc
function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail.
One character of pushback is guaranteed. If the
ungetc
function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail. C11dr §7.21.7.10 3
OP's dropping of ungetc()
is incorrect. OP's thought of "it'll just unget this char and read it again in the next function call." assumes the next function call will be a repeated call to getint()
- this is not warrented. Since the calling code should inspect the return value and noting it is not 1, execute other code to consume the data in stdin
.
if(!isdigit(c) && c != '+' && c != '-') {
ungetch(c); // not present in OP code, but present in K&R
return 0;
}
The though being, if getint(int *pn)
cannot read the int
, leave stdin
alone as much as practicable. Other functionality could be to at least consume 1 character, but I find the first more in keeping with C I/O functions.
A quandary:
In other cases, OP's code below does "Fix it to push such a character back on the input" but IMO does not push back properly. The sign character is not push-backed, only the digit. Instead the sign
is consumed by getint()
.
c = getch()
...
sign = (c == '-') ? -1 : 1;
if(c == '+' || c == '-')
c = getch();
if(!isdigit(c)) {
ungetch(c); // non-digit push-backed, but not sign.
return 0;
}
But portably using ungetc()
twice in a row is not guaranteed.
One character of pushback is guaranteed. If the
ungetc
function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail.
Since code really should "unget" 2 characters (+/-
and the following non-digit), but it is not portable - what to do? Since many systems do support pushing back more than 1 character with restrictions, consider attempting it.
Of course, all the consumed white-space characters are not push-backed either. Yet pushing back the sign is prudent - many systems do this with scanf("%d", ...)
.
Checking the return value of ungetc()
would discern success. A slight variation follows:
int c;
int sign = EOF;
while(isspace(c = getch()))
;
if(c == EOF)
return EOF;
sign = c;
if (sign == '+' || sign == '-')
c = getch();
if (!isdigit(c)) {
ungetch(c); // Pedantic code would check this return value.
if (sign == '+' || sign == '-') {
// attempt to push-back sign
if (ungetch(sign) == EOF) {
; // Operation failed
}
}
return 0;
}
...
if (sign == '-') *pn = -(*pn);
Other code issues:
Code does not detect overflow.
Code unnecessarily overflows when scanning INT_MIN
. parse_int(char **s) offers a candidate solution.
Code does not differentiate between an EOF
received from getch()
due to end-of-file and input error. Coding goal is "return EOF when end of file is reached". OTOH, code has no specification concerning input error, so returning EOF
for both conditions is reasonable.