1

UPDATE BELOW

I need to test if an input is an integer, and if it is then continue doing something.

If the input is not an integer I need to print an error message and quit.

The method I'm using is scanf will return the number of read items, in my case I want it to return 1. So I test if scanf returns 1, and execute the rest of my code.

But, for some reason when scanf doesn't return 1 I run into an infinite loop

Code:

/*
 * Read in a number of values to read and then print the average
 * of those values.
 */

#include <stdio.h>
#include "tfdef.h"
#define DEBUGGING 1;

int main() {
    int expected;
    int count;
    double sum;
    int value;
    int flag;

    while (flag = scanf("%d", &expected) != EOF) {
#ifdef DEBUGGING
        printf("flag: %d  expected: %d\n", flag, expected);
#endif

        if (flag == 1) {
            sum = 0;
            for (count = 0; count < expected; count++) {
                scanf("%d", &value);
                sum += value;
            }
            printf("Average of %d values is %.2f\n",
                   count, count != 0 ? sum / count : 0.0);
        } else {
            printf("Error! Can't read number of expected values.\n");
        }
    }
}

UPDATE:

The following code seems to work except the case where the initial input is a number followed by letters. For example:

Input: eeee33333
Printed: Error! Can't read number of expected values.

Input: 333eeee
Printed: Debug1 flag:1 expected: 333

Code

#include <stdio.h>
#include "tfdef.h"
#define DEBUGGING 1;

int main() {
    int expected;
    int count;
    double sum;
    int value;
    int flag;

    while (flag = scanf("%d", &expected)) {
#ifdef DEBUGGING
        printf("Debug1 flag: %d  expected: %d\n", flag, expected);
#endif
        if (flag == EOF) { 
#ifdef DEBUGGING
            printf("Debug2 flag: %d  expected: %d\n", flag, expected);
#endif
            return 0; 
        }
        while (getchar() != '\n');

        if (flag == 1) {
            sum = 0;
            for (count = 0; count < expected; count++) {
                scanf("%d", &value);
                sum += value;
            }
            printf("Average of %d values is %.2f\n",
                   count, count != 0 ? sum / count : 0.0);
        }
    }
    printf("Error! Can't read number of expected values.\n");
}
20
  • 2
    Note that flag = scanf("%d", &expected) != EOF is equivalent to flag = (scanf("%d", &expected) != EOF). Maybe not what you want? Also note that if you enter a non-integer then scanf will return 0 and not EOF. Commented Oct 27, 2016 at 7:53
  • 1
    You must find a way to flush the input buffer, or the program will keep trying to read the . decimal point or whatever. But I would input with fgets and then apply sscanf, that way you can easily dump the rest of the input. Commented Oct 27, 2016 at 7:54
  • 1
    Lastly, you might want to consider using fgets and sscanf instead. Commented Oct 27, 2016 at 7:55
  • add a break; into else scope Commented Oct 27, 2016 at 7:55
  • @Someprogrammerdude I see.. So should I test if flag is EOF in another if statement? Will try that now ... Commented Oct 27, 2016 at 7:56

1 Answer 1

1

The best solution for this problem is to read the input with fgets() and parse it with sscanf(), but the reason you get an infinite loop is this: your test is incorrect:

while (flag = scanf("%d", &expected) != EOF)

flag receives the result of the comparison between the return value of scanf and EOF... You probably meant to write this instead:

while ((flag = scanf("%d", &expected)) != EOF)

But if the user types something that cannot be parsed as an int, such input lingers in the stdin buffer and scanf() will keep attempting to parse it in vain.

Try this approach:

#include <stdio.h>

int getnumber(int *valp) {
    char line[80];
    char last;

    while (fgets(line, sizeof line, stdin)) {
        flag = sscanf(line, "%d %c", &expected, &last);
        if (flag < 1) {
            printf("Input is not a number: %s", line);
            continue;
        }
        if (flag > 1) {
            printf("Extra characters after number input: %s", line);
            continue;
        }
        return 0;
    }
    return EOF;
}

int main(void) {
    int expected;
    int count;
    double sum;
    int value;

    while (getnumber(&expected) != EOF) {
        sum = 0;
        for (count = 0; count < expected; count++) {
            if (getnumber(&value) == EOF) {
                printf("Error! Can't read number of expected values.\n");
                break;
            }
            sum += value;
        }
        printf("Average of %d values is %.2f\n",
               count, count != 0 ? sum / count : 0.0);
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your input, I see now how the test is written incorrectly. The functions fgets() and strtol() aren't at our disposal. This is an introductory C course and the instructor explicitly stated to use only functions we have learned in the class (with the extra condition of not using break of continue statements in this particular problem) I know these seem like unrealistic and unnecessary parameters but that's how it is...
@StephenCadiz: if scanf() returns 0, you must deal with offending input and skip it. A simple way to do this is scanf("%*s"); that will read and discard a sequence of non white space characters. scanf() is very quirky, easy to misuse and a common source of software flaws. It is too bad it is still among the first library functions beginners see and use when learning the C language.
Thank you for writing that piece of code, I had to look up some functions but I think I can follow your train of thought. Further reading corroborates your statement about scanf, there are whole articles detailing why it shouldn't be used... Alas all I have available to me to read input is scanf and getchar at the moment. @chqrlie
@StephenCadiz: one classic problem with scanf() is the use of %s conversion specifiers: unless you have complete control over the input, this is as bad as using the infamous gets() function: sufficiently long input strings will cause a buffer overrun. See if your course warns about this and suggest using a length specifier to limit the input to one less than the size of the destination array: char buf[20]; n = scanf("%19s", buf);...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.