Search code examples
cfgetsfeof

feof becomes true prematurely


I am trying to send a file over a socket by reading one character at a time until the buffer (an array of chars) is full, sending it, then repeating until the end of the file. But for some reason feof becomes true before the file ends (I believe it might be when the buffer array is full).

int c;
int end_loop = 1;
char to_send[BUFFER_LENGTH];
while (end_loop == 1) { //For the entire file
    printf("creating next data\n");
    bzero(to_send, BUFFER_LENGTH);
    for (int i = 0; i < BUFFER_LENGTH - 1; i++) { // read data from file until buffer full or EOF
        c = fgetc(f);
        if (c == EOF) { // If end of file break loop
            printf("EOF\n");
            end_loop = 0;
            break;
        }
        to_send[i] = c;
    }
    for (int i = 0; i < strlen(to_send); i++) {
        printf("%c", to_send[i]);
    }
    n = write(sockfd, to_send, strlen(to_send));
    if (n < 0) {
        perror("ERROR writing to socket");
        exit(1);
    }
}
n = write(sockfd, "EOF", 3);
if (n < 0) {
    perror("ERROR writing to socket\n");
    exit(1);
}

This is the output from a simple file client output

It is possible feof is not the issue, since the code seems to keep looping despite "EOF" being met.

EDIT: Added suggestions from the comments. Error still occurs.


Solution

  • Code needs to track how many characters read and then printf(), write() that many characters.

    while (end_loop == 1) {
        ...
        // for (int i = 0; i < BUFFER_LENGTH - 1; i++) {
        int i;
        for (i = 0; i < BUFFER_LENGTH - 1; i++) { 
          ...
        }
        // for (int i = 0; i < BUFFER_LENGTH - 1; i++) {
        //    printf("%c", to_send[j]);
        for (int j = 0; j < i; j++) {
          ...
        // n = write(sockfd, to_send, BUFFER_LENGTH);
        n = write(sockfd, to_send, i);
        ...
    }
    

    Other problems include

    Test for EOF, not only feof(f)

        c = fgetc(f);
        // if (feof(f)) { // If end of file break loop 
        if (c == EOF) { // If end of file break loop **or input error**
    

    No need for -1 when filling a char array. A -1 might be useful with strings, but using strings here is not the best idea here either as fgetc() may return a null character.

    //                                   vvv 
    // for (int i = 0; i < BUFFER_LENGTH - 1; i++)
    for (int i = 0; i < BUFFER_LENGTH; i++)
    // or better 
    size_t i; 
    for (i = 0; i < sizeof to_send; i++)
    

    OP amended code mid-answer Hmmmmmmmm.

    Do not use for (int i = 0; i < strlen(to_send); i++) {. Data read may include null characters which negates good use of strings here.


    If OP does not want to see "EOF\n" before the last line, print "EOF\n" after the while loop.