-2

I have wrote the following code using c programming language (Standard 89):

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int cc,dd;
    scanf("%d/%d",&cc,&dd);

    int ll;
    scanf("%d",&ll);
    printf("Value of ll is: %d",ll);
    return 0;
}

If I submit the following as an input in one line: 4/5h I get the following output: Value of ll is: 67 So I have 2 questions;

1) where that 67 value came from? (I tried to change the input to something like 1/2t but got the same result) According to what I have read since there is no integers in the buffer the application should wait until one is available (For example to wait for a new input)

2) When I run my code using debug mode I can see that ll value is 65 but not 67!

  • 5
    Rule #1 of calling `scanf`: *always* check the return value. The second call is probably failing, storing nothing in `ll`. (And if you're curious, rule #2 of calling `scnaf` is "Don't", but that's a flameware for another day.) – Steve Summit Nov 04 '19 at 17:05
  • You'll also get more information by initialising the variables to known values first, for example `int cc = -1, dd = -2, ll = -3;` If the `scanf` does not scan a value, the initialised values will remain, whereas you don't know where `67` and `65` are coming from due to *undefined behaviour*. – Weather Vane Nov 04 '19 at 17:07
  • Initialize all variables, e.g. `int cc=0;`etc. – Bodo Nov 04 '19 at 17:08
  • `scanf()` doesn't wait for an integer. It tries to parse the input as an integer. If the parse is successful, it stores it in the variable. If not, it leaves the variable alone and returns a number less than the number of format operators. Since `h` can't be parsed as an integer, the latter happens. – Barmar Nov 04 '19 at 17:11
  • If you want to remove the `h` from the input stream you would have to call `char c; r = scanf("%c", &c);`. But this removes the next character from the input stream. If the `h` isn't present, it will "eat" the first digit of the next number. Finally, scanf is not usable to serious parsing of user or free text input. Consider reading line by line and parsing thereafter, e.g. with strtok, sscanf or similar. Don't expect to get it easy. – harper Nov 04 '19 at 17:21

1 Answers1

0

By typing non-digit characters in entries like "5h" or "2t" for dd, you're fouling up the read for ll in the second scanf call.

%d tells scanf to skip any leading whitespace, then to read decimal digit characters up to the first non-digit character. If you type a string like "5h" or "2t", that leading digit will be successfully converted and assigned to dd, but the trailing non-digit character will be left in the input stream, and that's fouling up the read for ll. No new value is being read into ll, you're getting whatever indeterminate value it had when the program started up.

Always check the result of scanf (and fscanf and sscanf) - if it's less than the number of inputs you expect, then you have a matching failure (you're not handling some input correctly). If it's EOF, then you have a failure on the input stream itself.

For this particular case, you can work around the problem by checking the result of scanf - if it's 0, then there's a bad character in the stream. Throw it away and try again:

int r;
while ( ( r = scanf( "%d", &ll ) ) != 1 && r != EOF ) 
  getchar();                      

This will call scanf and try to read a value into ll. We expect scanf to return a 1 on a successful input, so we'll loop while the result of scanf isn't 1 (and isn't EOF, either). If the read isn't successful, we assume there's a non-digit character stuck in the input stream, so we read and discard it with the getchar call.

John Bode
  • 119,563
  • 19
  • 122
  • 198