1

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.

Haskell-newb
  • 149
  • 1
  • 10
  • 1
    Possible duplicate of [Checking the stdin buffer if it's empty](https://stackoverflow.com/questions/26948723/checking-the-stdin-buffer-if-its-empty) – Tim Mar 19 '18 at 23:53
  • 1
    When you run `TEST`, stdin is not empty. Instead, stdin is whatever you enter on the terminal. You will have to press Ctrl+D for the terminal input to be considered empty. I would strongly encourage you to rethink your interface and work *with* the system instead of against it. Canonical behavior is easier to implement and easier to use. – that other guy Mar 19 '18 at 23:58
  • @Tim No it's not the same , it is pretty similar i agree but in his case he read the `EOF` from the buffer so he had to send it with` Ctrl+d` , in my case i want to do it automatically without getting in the if statement . Even if i have to change the if statement. – Haskell-newb Mar 20 '18 at 00:02
  • @thatotherguy Could you provide me with a small example if possible. like i said i'm pretty new to C prog.language. – Haskell-newb Mar 20 '18 at 00:07
  • @Haskell-newb How does the computer know whether you're not going to type something, or whether you are going to type something but you haven't yet? – user253751 Mar 20 '18 at 02:12

1 Answers1

2

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");
    }
}
user3386109
  • 34,287
  • 7
  • 49
  • 68