Haskell-newb
Haskell-newb

Reputation: 149

Check if the input stream is empty in C

I'm learning C language, I'm having trouble with my program.

So, I have this program called TEST this program should allow me to read the argument either with argv[] or by using the input stream $ TEST < argsTest.json.

argsTest.json :
{
"a" = 2,
"b" = 3
}

to simplify my question I will use this simple program :

Struct {
    int a;
    int b;
} number;

int main(int argc, char **argv) {
    json_t * root;
    struct number numbers;
    int c = 0, i = 0 , result;
    char str[1024]; // I'm not using malloc just to simplify my question
    // default values
    numbers.a = 0;
    number.b = 0;

    if (argc == 1 && !feof(stdin)) {
        while((c = fgetc(stdin)) != EOF) {
            str[i]=c;
            ++i;
        }
        str[i] = '\0';

        .... // code that use jansson library to extract value

        /** let's suppose we have extracted the two value int json_a
          * and int json_b.
          */

        numbers.a = json_a;
        numbers.b = json_b;

    } else if (argc == 3) {
        scanf("%d", numbers.a);
        scanf("%d", numbers.b);
    }

    result = numbers.a + number.b;
    printf("%d\n", result);

    return 0;
}

So, I'm trying to implement three behaviors :

  1. $ TEST it should display 0 ( we used the default values).
  2. $ TEST < argsTest.json display 5.
  3. $ TEST 4 3 display 7.

My problem is that if statement if (argc == 1 && !feof(stdin)) , actually $ TEST and $ TEST < argsTest.json have the same statement argc == 1, so when run $ TEST it bug because he enters the first condition.

I want an if statement that will check if the input stream is empty and having 0 argument, so I can implement the first case without getting in the if statement.

Thank you.

Upvotes: 1

Views: 1813

Answers (1)

user3386109
user3386109

Reputation: 34829

The general idea is

  • check argc first to see if you should use the values in argv
  • check whether the terminal is interactive
    • if it is then just print 0
    • if it's not interactive then you can read from stdin

The problem is that there's no portable way to check if stdin is interactive. However, on POSIX systems, you can use the isatty function, as explained in this question.

So assuming that you are on a POSIX system, the code looks like this:

int main(int argc, char *argv[])
{
    struct number numbers;

    if (argc == 3)
    {
        if (sscanf(argv[1], "%d", &numbers.a) == 1 && sscanf(argv[2], "%d", &numbers.b) == 1)
            printf("From argv the answer is %d\n", numbers.a + numbers.b);
        else
            printf("Bad strings in argv\n");
    }
    else if (isatty(STDIN_FILENO))
    {
        printf("Nothing in argv or on stdin, so the answer is 0\n");
    }
    else
    {
        if (scanf("%d%d", &numbers.a, &numbers.b) == 2)
            printf("From stdin the answer is %d\n", numbers.a + numbers.b);
        else
            printf("Found junk on stdin\n");
    }
}

Upvotes: 2

Related Questions