4

I've searched the forum for the solution, but still in confusion about the output my code produces.

So, the program is pretty simple.

It gets two numbers at the input until reaches the end of file.
If the input is bad, it should print error to stdout and proceed to the next pair.
If both are primes, it prints out prime. Otherwise, it prints their GCD.

Problem is, that if the input is bad, i.e either one or both numbers are not actually numbers, the program skips scanf and keeps on printing error to stderr.
Yet, during debugging, I found out that all the next iterations scanf() goes through, it returns 0 as if nothing was inputted at all.
And the prompt is inactive for inputting, since the program constantly prints to stderr.

nd and nsd are functions returning greatest divider and greatest common divisor respectively.

The main program is following:

#include <stdio.h>
#include "nd.h"
#include "nsd.h"

int main() 
{
int a;
int b;
int inp_status = 0;
while (1){
        inp_status=scanf(" %d %d", &a, &b);
        if (inp_status == EOF){
            break;
        } else if (inp_status < 2){
            fprintf(stderr, "Error: bad input\n");
        } else {
            if (a == 1 || b == 1){
                printf("1\n");
            } else if (nd(a) == 1 && nd(b) == 1){
                printf("prime\n");
            } else {
                printf("%d\n",nsd(a,b));
            }
        }
}
fprintf(stderr, "DONE\n");
return 0;
}
Suraj Jain
  • 4,463
  • 28
  • 39
Lev Kolomazov
  • 87
  • 1
  • 7
  • 1
    Curious, @Lev, why does code not use `fgets()` instead of `scanf()`? – chux - Reinstate Monica Nov 19 '16 at 22:54
  • honestly, i considered line processing using `fgets()` to be more difficult since I haven't observed proper string type in C. But, gonna try and learn now. Also, can't link removing the input stream and not gaining access to it again in the next iteration. Does stderr causes it? – Lev Kolomazov Nov 19 '16 at 23:07
  • 2
    If the input contains say `'A'` then `scanf` will remain stuck trying to get past that. As @chux says, use `fgets`, and then apply `sscanf` to that string. If it fails you can dump the whole string and get another. Then you avoid all that horrible get-around in the next comment. – Weather Vane Nov 19 '16 at 23:12
  • Thank you @chux, @Weather Vane, @user3121023 for anwers. `fgets()` is really more reliable. question is closed now. – Lev Kolomazov Nov 19 '16 at 23:46
  • 1
    In case of error, do `while ((c = getchar()) != '\n' && c != EOF) { }` in order to clear the buffer. – barak manos Feb 09 '17 at 14:13

1 Answers1

1

I put together a simple program to validate the return value:

#include <stdio.h>

int main()
{
    int a;
    int b;
    int inp_status = 0;

    inp_status = scanf(" %d %d", &a, &b);
    printf("INP status: %d\n", inp_status);
    printf("EOF = %d\n", EOF);

    return 0;
}

Here's that results of that program: INP INP

That's because the letters are actually being stored.

#include <stdio.h>

int main()
{
    int a;
    int b;
    int inp_status = 0;

    inp_status = scanf(" %d %d", &a, &b);
    printf("INP status: %d\n", inp_status);
    printf("EOF = %d\n", EOF);
    printf("Values stored: a = %d, b = %d\n", a, b);

    return 0;
}

Values

The values are being stored incorrectly, but the program is still making do. By storing the results with scanf, they aren't actually causing an error.

The most robust way of validating the inputs would be to make sure that you have both, like with this solution. Basically,

if (inp_status != 2){
    break;
}

instead of

if (inp_status == EOF){
    break;
}
Scott Forsythe
  • 360
  • 6
  • 18