Hey there! In this article, we’ll be diving into the fscanf function. This function is pretty similar to scanf, but instead of reading values from standard input, it reads them from a file. We’ll kick things off with an overview using examples and then delve into the format specifiers this function supports (which are the same as scanf, so if you’re familiar with it, you will find them familiar). At the end, there are some exercises for further practice.
How to read values from a file using fscanf
To read values from a file, you can make use of the fscanf function. This function is declared in the header file <stdio.h>. In C++, you can include <cstdio>. The function looks like this:
intfscanf( FILE * stream,constchar* format,...);
The first argument should be a pointer to the file from which you want to read.
The second argument is the format string which dictates how the file should be read.
Then, you pass as many arguments as fscanf expects based on the format string.
The function returns the number of values it read from the file. If everything goes well, this number should be equal to the number of arguments following the format string.
Let’s look at a few examples:
FILE * f =fopen("input.txt","r");int x;int n =fscanf(f,"x: %d",&x);fclose(f);printf("x = %d, n = %d", x, n);return0;}
x = 4, n = 1
In the program above, we read an int variable from a file using the format specifier %d (more on specifiers shortly). After reading, we printed out x and the number of arguments read.
Now, let’s try reading something a bit more complex:
FILE* f =fopen("input.txt","r");unsignedint x;char s;float pi;int n =fscanf(f,"hex: %x, s = %s\nfloat <- %f",&x, s,&pi);fclose(f);printf("x = %d, s = %s, pi = %f, n = %d", x, s, pi, n);return0;}
hex: 0xABC, s = fscanf
float <- 3.14
x = 2748, s = fscanf, pi = 3.140000, n = 3
As you can see, fscanf managed the complex format just fine. Let’s now “mess up” the input.txt file so that fscanf can only read the first two values:
hex: 0xABC, s = fscanf
UNKNOWN <- 3.14
With the start of the second line altered, let’s run the program again and see the output:
x = 2748, s = fscanf, pi = 0.000000, n = 2
Everything here is as expected:
fscanf could read the first two values since they remained unchanged.
However, when reading the second line of the file, fscanf hits the unexpected ‘U’ character and stops reading.
Ultimately, we see that only two values were read (n equals two). pi remains with its default value (in this case, zero).
What will be displayed on the screen?
FILE* f =fopen("data.txt","r");char word;double number;int n =fscanf(f,"%s = %lf", word,&number);fclose(f);printf("word = %s, number = %lf, n = %d", word, number, n);return0;}
result = 42.58
word = result, number = 42.580000, n = 2
word = 42.58, number = 0.000000, n = 1
word = result, number = 42.580000, n = 1
word = result, number = 0.000000, n = 2
fscanf uses the format specifier %s to read a string and %lf to read a floating-point number. The data.txt file contains the string “result” and the number 42.58, hence, both values will be successfully read. The value n, which represents the number of read elements, is two.
Now, let’s have a look at all the possible format specifiers you can use with the fscanf function.
The structure of the specifier in fscanf differs slightly from the one in fprintf. Here’s a look (optional modifiers are in square brackets):
From this, only the percentage sign and type are mandatory; you can skip the rest. These specifiers are pretty much the same as the ones in scanf (yeah, the one that reads from standard input, not a file).
Reads an integer in octal, decimal, or hexadecimal.
fscanf(f, "%i", &x); // x = 987 fscanf(f, "%i", &x); // x = -987 fscanf(f, "%i", &x); // x = 987
01733 -987 0x3db
Reads a decimal integer.
fscanf(f, "%d", &x); // x = -987
Reads a positive decimal integer.
fscanf(f, "%u", &x); // x = 987
Reads an octal integer.
fscanf(f, "%o", &x); // x = -987
Reads a hexadecimal integer.
fscanf(f, "%x", &x); // x = -987 fscanf(f, "%x", &x); // x = 987
f, e, g, a
Reads a floating-point number.
fscanf(f, "%f", &x); // x = 12.34 fscanf(f, "%f", &x); // x = 12.34 fscanf(f, "%f", &x); // x = 12.34 fscanf(f, "%f", &x); // x = 12.34
1.234e+01 12.34 987 0x1.8ap+3
Reads a character.
fscanf(f, "%c", &x); // x = 'C'
Reads a string until the first whitespace.
fscanf(f, "%s", &x); // x = "C++"
Reads a memory address.
fscanf(f, "%p", &x); // x = 0x16dc
Reads a string until it finds a character that isn’t among those inside the brackets.
fscanf(f, "%[1a]", &x); // x = "aa1"
Reads a string until it encounters a character that matches one from inside the brackets, after the ^.
fscanf(f, "%[^a1]", &x); // x = "C++"
Doesn’t read anything. Writes the number of characters read up to this point.
fscanf(f, "C++%n11", &x); // x = 3
Reads the percentage sign.
fscanf(f, "%%%c", &x); // x = 'd'
You can add an asterisk right after the percentage sign if you’re like, “I don’t wanna save this value”:
FILE * f =fopen("input.txt","r");int x;fscanf(f,"Skip: %*d, save: %d",&x);printf("Number: %d", x);
Skip: 123, save: 456
You can slap that asterisk on any type from the table above, not just numbers.
We can define the maximum number of characters to be read by the fscanf function:
Just like the asterisk, you can specify a width for any type.
By default, fscanf reads values of type int, unsigned int, float, and char (depending on the specifier type). To read, say, a value into a long long int variable, we need to explicitly state the length:
FILE * f =fopen("input.txt","r");longlongint x;printf("Number: ");fscanf(f,"%lld",&x);// ^ added ll for long long intprintf("Read: %lld\n", x);// ^ don't forget this in printf eitherreturn0;}
Without specifying the size, the output might look something like this:
This odd output is because ten billion just doesn’t fit into the int type, which fscanf tries to read without a specified size.
Here’s a quick size chart for you:
signed char / unsigned char
short int / unsigned short int
long int / unsigned long int
long long int / unsigned long long int
intmax_t / uintmax_t
Reading various data types:
Write a C++ program that uses fscanf to read different data types from a file. The file should have an integer, a float, and a string. After reading, the program should display these values.
Handling read errors:
Modify your data file so one of the lines doesn’t match the format you’re expecting. Then tweak your program to handle this gracefully, like maybe by printing an error message.
Using different format specifiers:
Write a program showcasing the use of different format specifiers with fscanf. Set up a file with various data (like integers, floats, strings, hex numbers) and pull them from the file, displaying the results.