last modified April 6, 2025
Formatted input from files is a crucial skill in C programming, enabling precise
data extraction. The vfscanf function provides powerful capabilities
for reading formatted data from files using variable arguments. This tutorial
explains vfscanf in depth, covering its syntax, usage patterns,
and safety considerations. Practical examples demonstrate how to leverage this
function effectively while avoiding common pitfalls in file operations.
The vfscanf function reads formatted input from a file stream using
a variable argument list. It's the file equivalent of vscanf and
works similarly to fscanf but with a va_list argument.
This function is declared in stdarg.h and stdio.h. It
returns the number of successfully matched and assigned input items, or EOF on
failure. Always validate the return value to ensure proper input processing.
This example demonstrates reading three different data types from a file using
vfscanf with a helper function.
#include <stdio.h>
#include <stdarg.h>
void read_formatted(FILE *fp, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfscanf(fp, fmt, args);
va_end(args);
}
int main() {
FILE *fp = fopen("data.txt", "r");
if (!fp) {
perror("Failed to open file");
return 1;
}
int num;
float value;
char text[50];
read_formatted(fp, "%d %f %49s", &num, &value, text);
printf("Read: %d, %.2f, %s\n", num, value, text);
fclose(fp);
return 0;
}
The example shows a wrapper function read_formatted that uses
vfscanf internally. The function takes a format string and variable
arguments, passing them to vfscanf. In main, we open
a file and read an integer, float, and string. Note the buffer size limitation
(49 characters) for safety. Always check file opening success and close files.
This example processes multiple structured records from a file using
vfscanf in a loop.
#include <stdio.h>
#include <stdarg.h>
int read_record(FILE *fp, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int result = vfscanf(fp, fmt, args);
va_end(args);
return result;
}
int main() {
FILE *fp = fopen("records.txt", "r");
if (!fp) {
perror("File open failed");
return 1;
}
int id;
char name[50];
double salary;
while (read_record(fp, "%d %49s %lf", &id, name, &salary) == 3) {
printf("ID: %d, Name: %s, Salary: %.2f\n", id, name, salary);
}
fclose(fp);
return 0;
}
Here we create a read_record helper function that returns the number
of successfully read items. The main loop continues as long as all three expected
fields (ID, name, salary) are read correctly. The format string specifies field
width for strings to prevent buffer overflow. The loop automatically stops at EOF
or invalid input format.
This example demonstrates robust error handling when using vfscanf.
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
int safe_vfscanf(FILE *fp, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int count = vfscanf(fp, fmt, args);
va_end(args);
if (count == EOF) {
if (feof(fp)) {
fprintf(stderr, "End of file reached\n");
} else if (ferror(fp)) {
perror("File read error");
}
} else if (count == 0) {
fprintf(stderr, "No fields matched\n");
}
return count;
}
int main() {
FILE *fp = fopen("values.txt", "r");
if (!fp) {
perror("Failed to open file");
return 1;
}
int a, b;
if (safe_vfscanf(fp, "%d %d", &a, &b) != 2) {
fprintf(stderr, "Failed to read two integers\n");
fclose(fp);
return 1;
}
printf("Sum: %d\n", a + b);
fclose(fp);
return 0;
}
The safe_vfscanf function enhances error reporting by checking for
EOF conditions and file errors. It differentiates between end-of-file and actual
read errors. The main function expects exactly two integers and handles the case
where fewer values are read. This approach provides better diagnostics than basic
vfscanf usage.
This example shows how to read various data types from a file using
vfscanf.
#include <stdio.h>
#include <stdarg.h>
void read_data(FILE *fp, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
if (vfscanf(fp, fmt, args) == EOF) {
fprintf(stderr, "Read error occurred\n");
}
va_end(args);
}
int main() {
FILE *fp = fopen("mixed.txt", "r");
if (!fp) {
perror("Failed to open file");
return 1;
}
int day, month, year;
char event[100];
double amount;
read_data(fp, "%d/%d/%d %99s %lf", &day, &month, &year, event, &amount);
printf("Date: %02d/%02d/%04d\n", day, month, year);
printf("Event: %s\n", event);
printf("Amount: %.2f\n", amount);
fclose(fp);
return 0;
}
The example reads a date in DD/MM/YYYY format, an event description, and a
monetary amount. Note the careful buffer size specification (99 characters) for
the string input. The read_data function handles the variable
argument passing to vfscanf. The output uses formatting to ensure
consistent date display with leading zeros where needed.
This example demonstrates advanced format specifiers with vfscanf.
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
void parse_config(FILE *fp, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int result = vfscanf(fp, fmt, args);
va_end(args);
if (result == EOF) {
fprintf(stderr, "Error reading configuration\n");
exit(EXIT_FAILURE);
}
}
int main() {
FILE *fp = fopen("config.txt", "r");
if (!fp) {
perror("Cannot open config file");
return 1;
}
char user[50];
int port;
char ip[16];
double timeout;
parse_config(fp, "user = %49[^\n]\n", user);
parse_config(fp, "port = %d\n", &port);
parse_config(fp, "ip = %15[^\n]\n", ip);
parse_config(fp, "timeout = %lf\n", &timeout);
printf("Configuration loaded:\n");
printf("User: %s\n", user);
printf("Port: %d\n", port);
printf("IP: %s\n", ip);
printf("Timeout: %.1f seconds\n", timeout);
fclose(fp);
return 0;
}
This example parses a configuration file with specific format requirements. The
%[^\n] format reads strings until a newline, allowing spaces in
values. Each configuration line has a strict format that must be matched. The
parse_config function exits the program on failure, which might be
appropriate for critical configuration files. Buffer sizes are carefully
specified to prevent overflow.
vfscanf over vscanf for better control.
This tutorial has explored the vfscanf function in depth, providing
practical examples from basic to advanced usage. Mastering formatted file input
is essential for building robust data processing applications in C. Remember to
always prioritize safety when handling file input and variable arguments.
My name is Jan Bodnar, and I'm a dedicated programmer with a deep passion for coding. Since 2007, I've been sharing my expertise through over 1,400 articles and 8 e-books. With more than a decade of teaching experience, I strive to make programming accessible and engaging.
List C Standard Library.