Reading file contents in C
Tags: c, files, reading, beginners
Published: 2020-01-02 15:02:57

---
title: Reading file contents in C
published: true
description: Getting data fromd files in the C programming language
tags: C, files, reading, beginners
series: Basics of the C programming language
---

###Overview

There are a number of functions in the standard library for reading the contents of a file, some that read individual characters, and others that will read strings. The more efficient and useful of the two will be the ones dealing with strings, but the functions that deal with characters will be covered first because there are situations in which reading specific characters may be preferred. These functions are intended to work in conjunction with files that have been already been opened by `fopen()`, which returns a pointer, and thus take a file pointer as an argument.

####Reading characters from files with "file get character" function `fgetc()`

The `fgetc()` function takes a file pointer as an argument, and reads a single character from a file. After reading the character, the file pointer is advanced to next character. It will read newline characters as well. If pointer is at end of file, or if an error occurs, EOF is returned by this function.
Note: the return type of is int (not char), so it is recommended to assign the returned values of these functions to an integer type variable. See <a href="https://en.wikipedia.org/wiki/C_file_input/output#The_EOF_pitfall" target=”_blank” >this</a> for more details.

```c
// Syntax
char *fgetc(FILE *pointerToFileToBeRead);
```

To use the function in practice, the following example demonstrates basic usage and recommended practices (e.g. validity checks).

```c
#include <stdio.h>

int main()
{
  // pointer to the file to be read
  FILE *filePointer = NULL;

  // declare an int to hold the value of the current character being read
  int thisCharacter;

  // open the file to be read, in read mode "r"
  filePointer = fopen("test-fgetc.txt", "r");

  // check the result of opening the file for errors
  if (filePointer == NULL)
  {
    // perror displays the system error message after whatever text is in the parentheses
    perror("Error: ");
    return (-1);
  }

  // read a single char in for each loop iteration
  while ((thisCharacter = fgetc(filePointer)) != EOF)
  {
    //print the character to a string
    printf("%c", thisCharacter);
  }

  // close the file
  fclose(filePointer);

  // set the pointer to null to reset it and free the memory
  filePointer = NULL;

  return 0;
}
```

The comments in the code above hopefully make it clear what is happening.

The complementary function for writing characters to files is `fputc()`.

####Reading strings from files with "file get string" - `fgets()`

To read files, use `fgets()`, which I read in my mind as "file get string".
A simplified explanation is that it reads text from a file until is hits the newline character. In other words, it will read one line from a file at a time.

The more complete explanation is that the `fgets()` function will read in the entire string up until the 'new line' `\n` character, null terminator (aka 'end of string') character `\0`, EOF, or the number of user-specified characters (passed in as one of the arguments) is reached - whichever one of these happens first. An area of memory to store the data that is read by `fgets()` should be created prior to calling the function, which will be where the data read by the function is stored.

It takes 3 arguments: a pointer to a character array where the data that is read will be stored, the maximum number of characters to read in (an int, including the terminating null-character), and a pointer to the file to be read.
It will return the first argument (the string that was read in).
An error or EOF encountered will return NULL from the function.

A null terminator will be added to the end of the string by the function, so bear this in mind when allocating space for the first two arguments.

Note that this function will work with any stream (i.e. it can be used to store any received data such as user input or API calls), but for simplicity I'm sticking to only reading files. If you're not familiar with the concept of streams in C, it's worth doing some research.

Syntax:

```c
fgets(char *stringToStoreDataThatIsRead, int numberOfCharsToRead, FILE *fileToBeRead);
```

How it is used:

```c
#include <stdio.h>

int main()
{
  // create the pointer to the file to be read
  FILE *filePointer = NULL;

  // create the character array (aka string) to store the data that is read
  char savedString[61];

  filePointer = fopen("testFile.txt", "r");

  // check there is no error opening the file
  if (filePointer == NULL)
  {
    perror("Error: ");
    return(-1);
  }

  if(fgets(savedString, 60, filePointer) != NULL) {
    // print the return value (aka string read in) to terminal
    printf("%s", savedString);
  }

  fclose(filePointer);
  filePointer = NULL;

  return 0;
}
```

There is also the function `gets()`, but is not considered as safe to use as `fgets()`, and so it will not be covered.
The complementary function for writing to files is `fputs()`.

####Reading formatted input from a file

To get formatted input from a file, there is a an `fscanf()` function that works like `scanf()` for files. It takes any number of arguments: starting with the file to search, and then a list of any number of formats to check. It returns the number of input items successfully matched and assigned. If the operations complete successfully, it will return the integer 1.
The syntax is:

```c
int fscanf(FILE *fileToCheck, const char *firstFormatToLookFor, *secondFormatToLookFor, ...etc);
```

The example below reads a file and checks each string separated by whitespace (i.e. each word) in the format specified:
Let's assume the file, "names.txt", is a list of names, as below:

```
Names
Joe
Bob
Sally
```

Using a loop in the example below will continue reading the file until the EOF is reached, which returns a value of `1` (an integer) after each success. When it fails or reaches the end of the file, it will return `EOF` or `-1`. So, the condition in the while loop below is like saying "while it keeps returning success, keep trying to scan the file, and break out of the loop when it fails."

```c
#include <stdio.h>
#include <stdlib.h>

int main()
{
  // create a character array (i.e. string) to hold the values from fscanf()
  char *thisString[50];

  // create a pointer to the file that will be opened
  FILE *filePointer = NULL;

  // assign the pointer to the result of opening the file with fopen()
  filePointer = fopen("names.txt", "w+");

  // check there are no errors when opening the file
  if (filePointer != NULL)
  {
    // check the file and print out the result
    while (fscanf(filePointer, "%s", thisString) == 1)
    {
      printf("%s \n", thisString);
    }
  }

  fclose(filePointer);
  filePointer = NULL;

  return 0;
}
```

Many of the examples I came across made use of unfamiliar syntax, so I tried to use the simplest one I could above that also seemed to convey both how it's used, and a real use case. Feel free to let me know if it's not clear in the comments.  
Many would also make use of another syntax that will be handy to know when scanning files, the `%*s`. Including the asterisk before the 's' means "ignore this string and move on to the next." So if you had a list of users first names, last names, and ages, separated by spaces:

```
Joe Blow 25
Jane Doe 35
Luke Skywalker 62
```

If you wanted to save only the numbers, you could pluck out the third item in each line using the following syntax with `fscanf()`, and assign it to an int:

```c
// create a variable (and space in memory) to hold the integer age
int age;

// note that the 'address of' operator is used since we are getting integers,
// which are handled differently than strings
fscanf("%*s %*s %d", &age);
printf("%d", age);

/*
output:
25
35
62
*/

```

Both `fgets()` and `fscanf()` are somewhat complicated functions, so using them yourself, researching, and reading more is recommended, as this just scratches the surface of how they can be used.