1

A user can enter various different amounts of numbers (as long as they don't enter over 5000 numbers). However, when the user presses CTRL+D, the program should stop requesting user input. I've done this so far. However, I have to press CTRL+D twice before it stops. Could someone help me to fix it?

int input_array[MAX_NUMBERS] = {0};

scanf("%d", &input_array[0]);

int eof_detector = getchar();

int i = 0;
while ((i < 5000) && (eof_detector != EOF)) {
    i++;
    scanf("%d", &input_array[i]);
    eof_detector = getchar();
}
Boiethios
  • 38,438
  • 19
  • 134
  • 183
Zoey Malkov
  • 776
  • 6
  • 16

4 Answers4

2

Here's a more simpler solution.

// When the person presses CTRL+D, scanf will return EOF.
// Since the return value is EOF and not 1, it will break
// out of the scanning while loop.
// Also note, you can scan numbers as a while loop
// condition.
int input_array[MAX_NUMBERS] = {0};

int i = 0;
while (
       (scanf("%d", &input_array[0]) == 1) &&
       (i < MAX_NUMBERS)
      ) {
    i++;
}
Aniket
  • 449
  • 1
  • 3
  • 12
0

you no need to use getchar() separately before loop & inside loop. use getchar() in condition & also scanf() will return EOF if it encounters end of input so check the return value of scanf(). Do like this

int main() {
        int input_array[MAX_NUMBERS] = {0};
        int i = 0,ret;

        do {
                ret = scanf("%d", &input_array[i]);/* if you pressed
                                              CTRL+D, scanf return EOF */
                if(ret == EOF)/* if ctrl+d pressed,condition becomes true */
                        break;
                i++;
        }while ((i < 5000) && (getchar() != EOF));/* it won't check this
                                             bcz of break statement if CTRL+d pressed */
        return 0;
}
Achal
  • 11,821
  • 2
  • 15
  • 37
  • 1
    As expected. `scanf` will read once and `getchar` a second time. You need to get rid of `getchar` if you want to read only once. – Noufal Ibrahim Apr 18 '18 at 10:08
  • @NoufalIbrahim If I get rid of getchar how can I detect EOF? – Zoey Malkov Apr 18 '18 at 10:10
  • Check my answer and the first comment to your question. `scanf` itself will return `EOF` it if encounters the end of input. – Noufal Ibrahim Apr 18 '18 at 10:11
  • I modified my answer @ZoeyMalkov check. As told by Noufal `Scanf()` itself will return `EOF` if it encounters end of input. – Achal Apr 18 '18 at 10:17
  • @achal I can't use the function do. I also don't know what it is. Is there a way to do it using an if statement or something? – Zoey Malkov Apr 18 '18 at 10:20
  • `do` is not a `function`, its a `loop` called `do..while` loop & you can use, its best suitable for this scenario. – Achal Apr 18 '18 at 10:23
  • _Is there a way to do it using an if statement ?_ I shown above right ? check the return value of `scanf()` – Achal Apr 18 '18 at 10:24
  • @achal I don't quiet understand do, I can't use `do` either. Is do like a while loop within a while loop? Or is do, just saying do this when its in the loop? if its like this, couldn't I remove `do` and place its conents within the while loop and the program will do the same thing? – Zoey Malkov Apr 18 '18 at 10:29
  • `do..while` is one of iterative control statement, you can't separate `do` from `while` . just check the syntax of here https://en.wikipedia.org/wiki/Do_while_loop – Achal Apr 18 '18 at 10:41
0

You're likely to encounter the EOF while in scanf, so what you should do is test the return value of scanf and when it fails call feof(stdin) to see whether the failure was due to an EOF or an error.

for(i=1;i<4999;i++){
   if(EOF==scanf("%d", &input_array[i])){
      if(feof(stdin)) /*EOF*/; else /*error*/;
      break;
   }
}

As the scanf(3) manpage indicates, scanf returns EOF on either an error (in which case errno is set to one of the values listed in the manpage) or EOF.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • Sorry, I'm sort of new to programming. What value does scanf return or show when it fails (so I can do the if statement for it). Also I can't use feof(stdin) because we haven't learnt it in class. We can only use things we learnt, which is like if statements – Zoey Malkov Apr 18 '18 at 10:08
  • @ZoeyMalkov scanf returns EOF on error/EOF. It's in the manpage (or the standard). I've added the details to the answer. – Petr Skocik Apr 18 '18 at 10:12
  • Thanks for the help but I can't use things like feof or break since I haven't learnt them. Is there any other way? – Zoey Malkov Apr 18 '18 at 10:15
  • If Scanf returns EOF too, how can I write an if statement for that? would it be like `if (input_array[i] != EOF)`? – Zoey Malkov Apr 18 '18 at 10:19
0

You don't need the getchar separately to check whether EOF has been reached. scanf will itself return an EOF if it encounters the end of data. Your loop will work like so

  do {
      ret = scanf("%d", &input_array[i]);
      i++;
     } while ((i < 5000) && (ret != EOF));
Noufal Ibrahim
  • 71,383
  • 13
  • 135
  • 169
  • I can't use functions like do. I don't know if ret is a function or not, but I can't use it. I can use things like if statements? – Zoey Malkov Apr 18 '18 at 10:17
  • `ret` is an `int` variable. `do` is not a function. It's part of `C` and is a variant of `while` with the test at the end rather than the beginning. You can do this like you've done as well. Put one extra `scanf` and `if` test outside the loop. Then you can use a `while` instead. – Noufal Ibrahim Apr 18 '18 at 10:20
  • if I use fgets, can fgets read integers as integers? Then somehow use atoi function? – Zoey Malkov Apr 18 '18 at 10:25
  • @ZoeyMalkov [Don't use `atoi()`](https://stackoverflow.com/questions/17710018/why-shouldnt-i-use-atoi?noredirect=1&lq=1). – Andrew Henle Apr 18 '18 at 11:10
  • @ZoeyMalkov The bottom line is to avoid using `getchar` and to rely on the return value of `scanf`. The rest is upto you. – Noufal Ibrahim Apr 19 '18 at 06:47