-3

I was trying to figure out whether my input is numeric or not and I found this example:

while ( (scanf ("%d", &number) ) == 0) {
     printf("Entered value is not integer");
}

I searched online but I did not find any explanation about this. Why it means not a integer (Does this mean your input contains alphabets?)if you scanf() a integer and equal to 0?

user1234567
  • 57
  • 2
  • 11

5 Answers5

3

There probably wasn't any explanation for the code:

while ( (scanf ("%d", &number) ) == 0) {
     printf("Entered value is not integer");
}

because there isn't a good explanation for it. It is bad code on multiple grounds, some of which have been covered by other answers, but some of which have not been mentioned.

The novel problems are:

  1. If the scanf() reports 0, the program goes into an infinite loop. The character that was rejected as 'not part of a number' still isn't part of a number on the next cycle, so scanf() will consistently return 0 until the program is interrupted in some way.

    You can work around this by eating (at minimum) the first character of the remaining input. It is probably better to eat up all the characters until the next newline is read. After all, if the user mistyped the number, whatever else is on the line is not reliably what they wanted to type.

  2. The diagnostic message doesn't end with a newline, so it may not appear until enough copies of the message have been generated to fill the standard output buffer, whereupon a number of copies of the message will appear. There's a chance that you won't see this behaviour because the standard input and standard output stream might be synchronized so that any pending output is flushed before an input operation, but it is not reliable.

Then there's the boring stuff everyone else mentioned:

  1. The scanf() function might return EOF, or 0, or 1 (because there is only one conversion specification). If it returns EOF, you have another cause for an infinite loop: it will return EOF each time it is called, but the code doesn't react to the information.

    Most often, the correct way to detect that scanf() worked is to check that the return value is the number of values you expected should be returned (the number of active conversion specifications — you don't count %*d or %n or %% in the number of active conversion specifications, and maybe active isn't the best word, but it suffices for now).

Putting fixes for these issues together, you might arrive at:

int rc;
while ((rc = scanf("%d", &number)) != 1)
{
    if (rc == EOF)
    {
        printf("EOF detected without a number\n");
        break;  // return, exit, ...
    }
    printf("Entered value is not an integer: ");
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        putchar(c);
    putchar('\n');
    // Optionally fflush(stdout);
}

See Using fflush(stdin) for why I didn't use fflush(stdin) instead of the loop. You may prefer not to echo the invalid entry, in which case you can replace the putchar(c); with just the semicolon (and adjust the error message before, and the putchar('\n'); after too), but it often helps people to understand what they did wrong if they see what the program thinks they typed. You might want to think about whether error messages should be written to standard error instead of standard output. If getchar() returns EOF, the next iteration of scanf() will also return EOF, so that case will be handled. Note the use of int c;getchar() returns an int, not a character.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

As mentioned in the man page, in case the matching is failure, scanf() retunes 0. IN other words, scanf() returns the number of successful matches.

These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

In case for a %d format specifier, the entered value is a char (i.e., not a match for an int) matching fails and scanf() returns 0.

So, the bottom line is, a return value of 0 here indicates, the input was improper and the scanning has failed. That also mentioned, the assignment of the value expected of scanf() has failed, leaving the possibility of usage of indeterminate value for the supplied argument.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

If user gives integer then scanf will return 1 [the no of successfully scanned variable(s)] else return 0.

ALREADY AVAILABLE HERE : Value returned by scanf function in c

Btw the code is not proper as if EOF reached then also it will show ".. not inte..." as scanf will return -1 [also != 0] .

Community
  • 1
  • 1
pPanda_beta
  • 618
  • 7
  • 10
0

See Value returned by scanf function in c

On success, the function returns the number of items successfully read. This count can match the expected number of readings or fewer, even zero, if a matching failure happens. In the case of an input failure before any data could be successfully read, EOF is returned.

  • If it successfully reads the number, it returns 1. The loop will end.
  • If it fails to read anything (probably due to EOF), it returns EOF, which is -1. The loop will end.
  • If it reads something, but unable to convert it to integer, it returns 0, the loop continues.
Community
  • 1
  • 1
user31264
  • 6,557
  • 3
  • 26
  • 40
0

From the man page for scanf:

Upon successful completion, these functions shall return the number of successfully matched and assigned input items

and

An input item shall be defined as the longest sequence of input bytes (up to any specified maximum field width, which may be measured in characters or bytes dependent on the conversion specifier) which is an initial subsequence of a matching sequence. The first byte, if any, after the input item shall remain unread. If the length of the input item is 0, the execution of the conversion specification shall fail; this condition is a matching failure, unless end-of-file, an encoding error, or a read error prevented input from the stream, in which case it is an input failure.

In your case, the input specifier is "%d", which Matches an optionally signed decimal integer.... So if the first character (after skipping any white space) is a numeric digit (or a +/- sign), this will convert the number (one or more digits), stopping when it sees any non-digit characters. The return value is the number of converted values, which will be 1 if it found a valid decimal number, or 0 if it didn't.

Beware that the result may not be what you expect, for example:

4-hydroxytoluene

would convert the number 4 and return 1, even though it doesn't appear to be the intent of the input. Similary 1337age, for "leetage", would convert the number 1337. I often use a code snippet like the following to avoid such cases:

char dummy;
int conversions = scanf("%d%c", &number, &dummy);
if ((conversions != 1) && ((conversion != 2) || !isspace(dummy)))
    printf("Entered value is not an integer.\n");
GTB
  • 38
  • 6