Home > Enterprise >  why does fread from stdin not stop
why does fread from stdin not stop

Time:09-01

I am trying to read input from stdin with fread(). However i am have a problem, the loop will not terminate and instead keeps reading.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "argument err");
        return -1;
    }
   
    FILE *in  = fopen(argv[1], "w");

    if (in == NULL) {
        fprintf(stderr, "failed to open file");
        return -1;
    }
   
    char buffer[20];
  
    size_t ret;

    while ((ret = fread(buffer, 1, 20, stdin)) > 0) {
           if (fwrite(buffer, 1, ret, in) != ret) {
               if (ferror(in) != 0) {
                    perror("write err:");
               } 
           }
    }
    
    return 0;
}

How can i make this loop terminate when EOF is reached? i have tried using ctrl D but that just seems like a strange way to stop taking input.

I guess what i want is to use fread() to read multiple arbitrary amounts of data in chunks of 20 bytes and then somehow stop.

CodePudding user response:

How can i make this loop terminate when EOF is reached?

When do you think EOF is reached? Really. When you are providing input interactively, how is the system or the program supposed to know that you've entered all the data you want the program to consume?

i have tried using ctrl D but that just seems like a strange way to stop taking input.

It is exactly the way to signal a soft EOF to a POSIX terminal. Since you want the loop to stop when EOF is encountered, it seems absolutely natural to me to ctrl D when providing data interactively. That's not the only way you could signal the end of the input, but it has a lot going for it.

I guess what i want is to use fread() to read multiple arbitrary amounts of data in chunks of 20 bytes and then somehow stop.

Again: how is the program supposed to know when it has consumed all the "multiple arbitrary amounts" of data that you decide to provide on a given run? An EOF signal is an eminently reasonable choice for multiple reasons, and the way to deliver that from a POSIX terminal interface is ctrl D.

CodePudding user response:

As pointed out before you are reading from an eternal stream, this means that stdin don't naturally have a EOF (or <=0) value.

If you want your loop to terminate, you will have to add a termination condition, like a certain character, word or all type of value. After that you could use a break or a return in some case. You could also search if your terminal emulator support the insertion of an EOF value into the stdin, which is pretty common (But very platform dependent).

ADD: On my system, typical linux, CTRL D is for an EOF insertion in stdin. It seems that you found this out yourself, and if you want your program to know where to stop you will need to use this.

You cand also send a signal to your program, usually done with a shortcut like CTRL D, CTRL C, CTRL T etc... there is all sort of signal, which can be sent by your system or/and your TE and you just have to implement in your program the corresponding signal receiver.

  • Related