How to Use the Feof() Function in C

Jinku Hu Feb 02, 2024
  1. Understanding the feof() Function in C
  2. Use the feof() Function to Check End-Of-File Indicator on File Stream in C
  3. Use the feof() and ferror() Functions to Test the Valid Position of the File Stream in C
  4. Use feof() in a While Loop to Process a File in C
  5. Combine feof() With fgetc() to Read a File in C
  6. Common Pitfalls With the feof() Function in C
  7. Combine feof() With Other File Stream Functions in C
  8. Conclusion
How to Use the Feof() Function in C

In the realm of C programming, handling file input and output is a fundamental skill. The feof function plays a crucial role in this context, allowing us to determine if we have reached the end of a file.

In this article, we’ll explore various methods to use the feof() function in C, providing detailed explanations and example codes for each approach.

Understanding the feof() Function in C

The feof function is part of the C Standard Library, found in the <stdio.h> header file. It is used to check for the end-of-file condition during input operations.

This function returns a non-zero value if the end of the file has been reached; otherwise, it returns zero.

Syntax:

int feof(FILE *stream);

Here, stream is a pointer to a FILE object, which represents the file being operated upon.

For all the example codes in this article, we will use a text file (input.txt) with the following contents:

Use the feof() Function in C
an article by DelftStack

Use the feof() Function to Check End-Of-File Indicator on File Stream in C

As mentioned above, the feof() function is part of the C standard input/output library, defined in the <stdio.h> header.

The feof function checks for the end-of-file indicator on the given file stream and returns a non-zero integer if EOF is set. It takes the FILE pointer as the only argument.

In the following example, we demonstrate when the file is read line by line using the getline function, which gets called until the feof returns zero, implying that the file stream has not reached the EOF.

Notice that we verify the getline function return value in a conditional statement, and only if successful do we call the printf to output the read line.

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

const char* filename = "input.txt";

int main(void) {
  FILE* in_file = fopen(filename, "r");
  if (!in_file) {
    perror("fopen");
    exit(EXIT_FAILURE);
  }

  struct stat sb;
  if (stat(filename, &sb) == -1) {
    perror("stat");
    exit(EXIT_FAILURE);
  }

  char* contents = NULL;
  size_t len = 0;

  while (!feof(in_file)) {
    if (getline(&contents, &len, in_file) != -1) {
      printf("%s", contents);
    }
  }

  fclose(in_file);
  exit(EXIT_SUCCESS);
}

This program reads the contents of a file named "input.txt" and prints them to the console. It does so using the fopen function to open the file, getline to read lines, and printf to display them.

The program also checks for errors during file operations and handles them appropriately. Additionally, it dynamically allocates memory for storing lines from the file. Finally, it closes the file and exits with a success status.

Output:

Use the feof() Function in C
an article by DelftStack

Use the feof() and ferror() Functions to Test the Valid Position of the File Stream in C

Alternatively, feof can be utilized to test the file stream position before we read the contents of the file. In this case, we are reading the file using the fread call, which takes the file’s size retrieved with the stat function call.

Notice that the buffer to store the read bytes is allocated on the heap using the malloc function. Also, we included the ferror function in the conditional statement to test the error state on the file stream together with the EOF indicator.

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

const char* filename = "input.txt";

int main(void) {
  FILE* in_file = fopen(filename, "r");
  if (!in_file) {
    perror("fopen");
    exit(EXIT_FAILURE);
  }

  struct stat sb;
  if (stat(filename, &sb) == -1) {
    perror("stat");
    exit(EXIT_FAILURE);
  }

  char* file_contents = malloc(sb.st_size);
  if (!feof(in_file) && !ferror(in_file))
    fread(file_contents, 1, sb.st_size, in_file);
  printf("read data: %s\n", file_contents);

  free(file_contents);

  fclose(in_file);
  exit(EXIT_SUCCESS);
}

Output:

read data: Use the feof() Function in C
an article by DelftStack

The program above reads the contents of a file named "input.txt" and prints them to the console. It does so by utilizing standard C libraries such as <stdio.h> for I/O operations, <stdlib.h> for memory allocation, and <sys/stat.h> for file status information.

The program begins by defining the constant filename as "input.txt". It then attempts to open the file in read mode, handling potential errors.

It uses stat to retrieve information about the file and allocates memory accordingly. The program checks for end-of-file and error conditions then reads and prints the file’s content.

After displaying the content, it frees the allocated memory, closes the file, and exits with a success status.

ferror is also part of the I/O library and can be called on the FILE pointer object. It returns a non-zero indicator if the error bit is set on the file stream.

Note that all three examples print the content of the file specified by the filename variable. In the previous sample code, we output the stored contents using the printf function, but the more error-prone method would be the fwrite call, which can print the given number of bytes to the FILE stream specified by the fourth argument.

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

const char* filename = "input.txt";

int main(void) {
  FILE* in_file = fopen(filename, "r");
  if (!in_file) {
    perror("fopen");
    exit(EXIT_FAILURE);
  }

  struct stat sb;
  if (stat(filename, &sb) == -1) {
    perror("stat");
    exit(EXIT_FAILURE);
  }

  char* file_contents = malloc(sb.st_size);
  if (!feof(in_file) && !ferror(in_file))
    fread(file_contents, 1, sb.st_size, in_file);
  fwrite(file_contents, 1, sb.st_size, stdout);

  free(file_contents);

  fclose(in_file);
  exit(EXIT_SUCCESS);
}

This program reads the contents of a file named "input.txt". It first opens the file, checks for any errors during the opening process, and retrieves information about the file using the stat function.

It then dynamically allocates memory to store the file’s contents based on its size. After ensuring no end-of-file or error conditions exist, it reads the file and writes its contents to the standard output.

The allocated memory is subsequently freed to prevent memory leaks. Finally, the file is closed, and the program exits with a success status.

Output:

Use the feof() Function in C
an article by DelftStack

Use feof() in a While Loop to Process a File in C

One of the most common use cases of feof is in combination with a while loop to efficiently read lines from a file. This approach ensures that the loop continues until the end of the file is reached.

#include <stdio.h>

int main() {
  FILE* file = fopen("input.txt", "r");
  if (!file) {
    perror("fopen");
    return 1;
  }

  char buffer[100];
  while (!feof(file)) {
    if (fgets(buffer, sizeof(buffer), file) != NULL) {
      printf("%s", buffer);
    }
  }

  fclose(file);
  return 0;
}

Output:

Use the feof() Function in C
an article by DelftStack

In this code, we begin by including the necessary header file stdio.h.

Next, we open a file named "input.txt" for reading using fopen. If the file does not exist or cannot be opened, an error message is printed using perror, and the program returns with a non-zero exit status.

We then declare a character array buffer to store each line of the file.

The while loop continues until feof(file) returns true, indicating that the end of the file has been reached.

Inside the loop, fgets is used to read a line from the file. If fgets returns NULL, it means the end of the file has been reached.

Finally, the line read from the file is then printed to the console using printf("%s", buffer).

By using feof in this manner, we efficiently read lines from a file until the end is reached, ensuring no extra lines are processed.

Handling File Reading Errors

It’s important to note that using feof alone may not be sufficient to handle all potential errors during file reading. Other conditions like file permission issues or unexpected end-of-file characters may still occur.

Therefore, it’s recommended to combine feof with other error-checking mechanisms, such as ferror, to ensure robust file reading operations.

In summary, using feof in a while loop is a powerful technique for efficient file reading in C. By checking for the end-of-file condition within the loop, you can process file contents in a controlled and reliable manner.

However, it’s crucial to supplement feof with additional error-handling mechanisms to ensure the highest level of robustness in your file-handling code.

Combine feof() With fgetc() to Read a File in C

The fgetc function reads a character from a specified file and advances the file position indicator. It returns the character read as an unsigned char or EOF if it encounters an end-of-file condition or an error.

Syntax:

int fgetc(FILE *stream);

Again, stream is a pointer to a FILE object.

The combination of feof and fgetc allows us to efficiently read characters from a file until the end is reached. This is typically done in a loop.

Here’s an example code snippet:

#include <stdio.h>

int main() {
  FILE *file = fopen("input.txt", "r");
  if (file == NULL) {
    perror("Error opening file");
    return 1;
  }

  while (!feof(file)) {
    int ch = fgetc(file);
    if (ch != EOF) {
      printf("%c", ch);
    }
  }

  fclose(file);
  return 0;
}

Output:

Use the feof() Function in C
an article by DelftStack

The program starts by including the necessary header file stdio.h.

Next, it attempts to open a file named "input.txt" in read mode using fopen. If the file does not exist or cannot be opened, an error message is printed using perror, and the program exits with an error code.

The while loop runs as long as fgetc(file) does not return EOF. Within the loop, ch = fgetc(file) reads a character from the file and assigns it to ch.

Also, inside the loop, if fgetc encounters the end-of-file condition, it returns EOF, causing the loop to exit. Then, printf("%c", ch); prints the character to the console.

After the loop finishes, the file is closed using fclose(file).

This combination of feof and fgetc is particularly useful when you want to process the characters in a file one by one until the end of the file is reached.

Common Pitfalls With the feof() Function in C

One common mistake when using feof is assuming that it can reliably predict the end of a file.

It is important to note that feof only returns true after an attempt to read past the end of the file has occurred. This means that you may need to read one extra character to detect the end of the file.

FILE *file = fopen("input.txt", "r");
if (file == NULL) {
  perror("Error opening file");
  return 1;
}

int ch;
while (1) {
  ch = fgetc(file);
  if (ch == EOF) {
    if (feof(file)) {
      break;  // End of file reached
    } else {
      // Error occurred during read
      perror("Error reading file");
      break;
    }
  }
  printf("%c", ch);
}

fclose(file);

In this modified example, we use a while(1) loop and explicitly check for EOF after attempting to read a character. If EOF is encountered, we use feof to confirm that it is indeed the end of the file.

Combine feof() With Other File Stream Functions in C

feof is often used in conjunction with other file stream functions like fread, fgets, and fscanf to ensure that reading operations proceed smoothly and terminate correctly when the end of the file is reached.

FILE *file = fopen("input.txt", "r");
if (file == NULL) {
  perror("Error opening file");
  return 1;
}

char buffer[100];
while (fgets(buffer, sizeof(buffer), file) != NULL) {
  printf("%s", buffer);
  if (feof(file)) {
    break;  // End of file reached
  }
}

fclose(file);

In this example, fgets is used to read a line of text from the file into a buffer. The loop continues as long as fgets does not return NULL.

Additionally, we check feof(file) inside the loop to ensure that we correctly detect the end of the file.

Conclusion

The article provides a comprehensive guide on using the feof function in C for efficient file handling.

It starts by explaining the purpose of feof, which is to check for the end-of-file condition during input operations. The syntax and usage of feof are introduced.

The article then presents practical examples to demonstrate different methods of using feof in conjunction with other file-handling functions. These examples include reading lines from a file using getline, testing file stream positions with fread, and using a while loop with fgetc to read characters until the end of the file.

Common pitfalls related to feof are addressed, emphasizing the importance of reading an extra character to reliably detect the end of a file.

The article concludes by highlighting the significance of combining feof with other file stream functions like fread, fgets, and fscanf for smooth and accurate reading operations. Overall, the article equips readers with a comprehensive understanding of how to effectively utilize the feof function in C programming for proficient file input and output operations.

Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Related Article - C IO