0

I am reading an Integer with scanf and at the same time checking the number of digit read by scanf with the format %n, the first output is always correct but after that the output increased one more. That is scanf reads the last "\n" for the second scanf.

I know this kind of problem with scanf and char that is scanf("%c",&cval) ---> to scanf(" %c",&cval) leaving some little space to avoid scanf reading the end of line. but what is with integers?

I have already seen some question here Link here and they all seems to think scanf() is "retarted" and fget() should always be used.. Is it really so and is it good to avoid it in projects? I mean to void all this kind of bugs and is there a way to prevent this. Do i have to use fget() for this or is there a way to fix this in scanf(). All comments are welcome, and thanks for your time. I just want to know if there is a way to fix it, i know how to use %n.

#include <stdio.h>
int main(void) {


    int i =0 ,byte_count = 0,val;

    printf("Enter a number: ");

    scanf("%d%n",&val,&byte_count);
    while (i < 3){
        printf("byte count is: %d\n",byte_count);


        scanf("%d%n",&val,&byte_count);
        i++;
    }

    return 0;
}

enter image description here

Community
  • 1
  • 1
Seek Addo
  • 1,871
  • 2
  • 18
  • 30

3 Answers3

5

the first output is always correct but after that the output increased one more.

The value of n in subsequent scans is one greater than expected because they scanned in the trailing '\n' of the previous entry. @BLUEPIXY

\n3876  --> 5 characters
not 
3876

Also reset n each loop in case the scan of "%d" failed.

int val = 0; // add initialization

while (i < 3){
    printf("byte count is: %d\n",byte_count);
    byte_count = 0; // add
    scanf("%d%n",&val,&byte_count);
    i++;
}

To consume white-space in the stdin use " "

while (i < 3){
    printf("byte count is: %d\n",byte_count);
    byte_count = 0;
    scanf(" "); scanf("%d%n",&val,&byte_count);
    i++;
}
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

Indeed you should always use fgets() plus sscanf() or strtod() or strtol() etc. Don't bother trying to make plain scanf() work, it's just not as effective as your other options.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Could you please elaborate why are those better; especially sscanf > scanf. – 2501 Oct 25 '16 at 12:32
  • 1
    This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - [From Review](/review/low-quality-posts/14092781) – Toby Speight Oct 25 '16 at 14:05
  • @TobySpeight: You are incorrect, the question literally says "fget() should always be used.. Is it really so and is it good to avoid it in projects?" I directly answered the question. – John Zwinck Oct 25 '16 at 14:13
  • 1
    Ah, sorry - I'd assumed that you were experienced enough to flag opinion-seeking questions rather than answer them. – Toby Speight Oct 25 '16 at 14:18
2

%n captures all the characters processed by scanf including leading whitespace. Using %n twice can correct that. The format string skips leading whitespace and then gets the beginning count of characters. Then the integer is scanned and finally the total count of characters is captured. The difference in the count is the characters in the integer.
Always check the return of scanf as the input stream may need cleaning.

    int begin = 0;
    int end = 0;
    int val = 0;
    int clean = 0;
    int result = 0;

    do {
        if ( ( result = scanf(" %n%d%n",&begin,&val,&endn)) != 1) {// scan one int
            while ( ( clean = getchar ( )) != '\n') {//clean bad input
                if ( clean == EOF) {
                    fprintf ( stderr, "problem reading input\n");
                    exit ( 1);
                }
            }
        }
        else {//scanf success
            printf("byte count is: %d\n",end-begin);
        }
    } while ( result != 1);
user3121023
  • 8,181
  • 5
  • 18
  • 16