Форматируемый ввод-вывод


Еще один способ чтения и записи информации в файлах представляют функции fprintf() и fscanf(). Они позволяют отформатировать записываемые и считываемые данные соответственно.

Функция fprintf() имеет следующий прототип:

1
int fprintf(указатель_на_поток, строка_форматирования, список_аргументов);
Эта функция записывает данные, передаваемые в качестве третьего параметра, в файл с учетом форматирования, определяемого строкой форматирования. Первый параметр представляет указатель на файловый поток, в который производится запись.

Строка форматирования и передача в нее значений определяются также, как и в случае с функцией printf()

Например, запишем в файл массив структур:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

struct person
{
char name[20];
int age;
};
int main(void)
{
char * filename = "D://users.dat";
struct person people[] = { "Tom", 23, "Alice", 27, "Bob", 31, "Kate", 29 };
int n = sizeof(people)/sizeof(people[0]);
FILE *fp;
if ((fp = fopen(filename, "w")) == NULL)
{
perror("Error occured while opening file");
return 1;
}

for(int i=0; i<n; i++)
{
fprintf(fp, "%s %d\n", people[i].name, people[i].age);
}
fclose(fp);
return 0;
}
Каждая структура имеет два поля - строковое поле name и числовое поле age. Поэтому строка форматирования принимает соответствующие спецификаторы: "%s %d\n".

После записи мы получим текстовый файл users.dat, который сможем просмотреть в любом текстовом редакторе.

Для чтения данных в определенном формате применяется функция fscanf(), которая имеет следующий прототип:

1
int fscanf(указатель_на_поток, строка_форматирования, список_аргументов);
По факту эта функция похожа на функцию scanf(), которая используется для ввода с консоли, только теперь вод осуществляется из файла, указатель на который передается в качестве первого параметра.

Функция возвращает числовое значение. Если достигнут конец файла, то функция возвращает значение EOF.

Например, считаем и выведем на консоль ранее записанные в файл users.dat данные:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>

struct person
{
char name[20];
int age;
};

int main(void)
{
char * filename = "D://users.dat";
FILE *fp;
char name[20];
int age;
if ((fp = fopen(filename, "r")) == NULL)
{
perror("Error occured while opening file");
return 1;
}

while((fscanf(fp, "%s %d\n", &name, &age))!=EOF)
{
printf("%s %d\n", name, age);
}
fclose(fp);
return 0;
}
Для считывания данных здесь определены вспомогательные переменные name и age. И при вызове функции fscanf в качестве списка аргументов передаются адреса этих переменных. Кроме того, надо отметить, что строка форматирования совпадает со строкой, которая передавалась в предыдущем примере при записи в файл: "%s %d\n".

В итоге пока при считывании не будет достигнут конец файла и функция не вернет значение EOF, она будет считывать данные в переменные name и age, которые затем будут выводиться на консоль. В итоге мы получим следующий консольный вывод:

Tom 23
Alice 27
Bob 31
Kate 29