Файл – это именованный объект, хранящий данные (программа или любая другая информация) на каком-либо носителе (дискета,
В языке С файлом может быть все что угодно, начиная с дискового файла и заканчивая терминалом или принтером [12.2]. Поток связывают с определенным файлом, выполняя операцию открытия. Как только файл открыт, можно проводить обмен информацией между ним и программой.
Не у всех файлов одинаковые возможности. Например, к дисковому файлу прямой доступ возможен, в то время как к некоторым принтерам – нет. В языке С все потоки одинаковы, а файлы – нет [12.2].
Если файл может поддерживать запросы на местоположение (
Файл отсоединяется от определенного потока (т.е. разрывается связь между файлом и потоком) с помощью операции закрытия. При закрытии файла, открытого с целью вывода, содержимое (если оно есть) связанного с ним потока записывается на внешнее устройство. Этот процесс, который обычно называют дозаписью потока, гарантирует, что никакая информация случайно не останется в буфере диска. Если программа завершает работу нормально, т.е. либо функция main() возвращает управление операционной системе, либо вызывается функция exit(), то все файлы закрываются автоматически. В случае аварийного завершения программы, например, в случае краха или завершения путем вызова функции abort(), файлы не закрываются [12.2].
Файловая системы языка С предназначена для работы с самыми разнообразными устройствами, в том числе терминалами, дисками и накопителями на магнитной ленте. Даже если какое-то устройство сильно отличается от других, буферизованная файловая система все равно представит его в виде логического устройства, которое называется потоком. Потоки бывают двух видов: текстовые и двоичные [12.2].
Текстовый поток – это последовательность символов. В стандарте С считается, что текстовый поток организован в виде строк, каждая из которых заканчивается символом новой строки. Однако в конце последней строки этот символ не является обязательным. В текстовом потоке по требованию базовой среды могут происходить определенные преобразования символов. Например, символ новой строки может быть заменен парой символов – возврата каретки (например, \r ) и перевода строки (например, \n ), т.е. \r\n.
Двоичные потоки – это последовательность байтов, которая взаимно однозначно соответствует байтам на внешнем устройстве, причем никакого преобразования символов не происходит [12.2]. Кроме того, количество тех байтов, которые пишутся (читаются), и тех, которые хранятся на внешнем устройстве, одинаково. Однако в конце двоичного потока может добавляться определяемое приложением количество нулевых байтов. Такие нулевые байты, например, могут использоваться для заполнения свободного места в блоке памяти незначащей информацией, чтобы она в точности заполнила сектор на диске.
Файловая система языка С состоит из нескольких взаимосвязанных функций [12.2]. Самые распространенные из них показаны в табл. 12.1.
| Функции файловой системы языка С | ||
|---|---|---|
| № п/п | Имя функции | Что делает |
| 1. | fopen() |
Открывает файл |
| 2. | fclose() |
Закрывает файл |
| 3. | putc() |
Записывает символ в файл |
| 4. | fputc() |
То же, что и putc() |
| 5. | getc() |
Читает символ из файла |
| 6. | fgetc() |
То же, что и getc() |
| 7. | fgets() |
Читает строку из файла |
| 8. | fputs() |
Записывает строку в файл |
| 9. | fseek() |
Устанавливает |
| 10. | ftell() |
Возвращает текущее значение указателя текущей позиции в файле |
| 11. | fprintf() |
Для файла то же, что printf() для консоли |
| 12. | fscanf() |
Для файла то же, что scanf() для консоли |
| 13. | feof() |
Возвращает значение true (истина), если достигнут конец файла |
| 14. | ferror() |
Возвращает значение true (истина), если произошла ошибка |
| 15. | |
Устанавливает |
| 16. | remove() |
Стирает файл |
| 17. | fflush() |
Дозапись потока в файл |
Для приведенных функций требуется подключить заголовок <stdio.h>. Запись или чтение из файла осуществляются с помощью указателя файла. Указатель файла – это указатель на структуру типа FILE. Для объявления переменной–указателя файла, например, *fp, используется следующий оператор:
FILE *fp;
Ключевое слово FILE определяет собой своеобразный тип данных, а указатель *fp указывает на этот тип.
Указатель файла указывает на структуру, содержащую различные сведения о файле, его имя, статус и
Открытие файла осуществляется с помощью функции fopen(), которая открывает поток и связывает с этим потоком определенный файл. Прототип функции fopen() такой:
FILE *fopen(const char *file_name, const char *mode);
В прототипе функции fopen() формальные переменные имеют следующий смысл:
file_name – это имя файла с заданным расширением и возможным путем расположения, mode – режим работы файла: чтение, запись и т.д. [12.1].
В табл. 12.2, взятой из [12.2], приводятся допустимые значения режима для функции fopen().
Допустимые значения режима функции fopen() | ||
|---|---|---|
| № п/п | Режим | Что означает |
| 1. | r | Открыть текстовый файл для чтения |
| 2. | w | Создать текстовый файл для записи |
| 3. | a | Добавить в конец текстового файла |
| 4. | rb | Открыть двоичный файл для чтения |
| 5. | wb | Создать двоичный файл для записи |
| 6. | ab | Добавить в конец двоичного файла |
| 7. | r+ | Открыть текстовый файл для чтения/записи |
| 8. | w+ | Создать текстовый файл для чтения/записи |
| 9. | a+ | Добавить в конец текстового файла или создать текстовый файл для чтения/записи |
| 10. | r+b | Открыть двоичный файл для чтения/записи |
| 11. | w+b | Создать двоичный файл для чтения/записи |
| 12. | a+b | Добавить в конец двоичного файла или создать двоичный файл для чтения/записи |
Например, для записи в файл с именем (и расширением) data.txt на диск D следует использовать такие объявление и операции:
FILE *fp;
fp = fopen("D: \\data.txt", "w");
fprintf(fp, "\n\t hello, world\n");
fclose(fp);
В приведенном фрагменте С -кода функция fclose() закрывает поток, который был открыт с помощью вызова функции fopen(). Функция fprintf() осуществляет форматную запись (в данном случае строку hello, world ) в файл. Все манипуляции с файлом происходят между функциями fopen() и fclose(). Режим функции fopen() задается строкой "w", которая обеспечивает создание текстового файла для записи. Это означает, что файл data.txt создается на диске D и в него записывается строка hello, world с отступом от верхнего края и с отступом (табуляцией) от левого края.
Прототип функции fclose() следующий:
int fclose(FILE *fp);
В приведенной записи *fp – указатель файла, возвращенный в результате вызова функции fopen() [12.2]. Возвращение нуля означает успешную операцию закрытия. В случае же ошибки возвращается EOF. Обычно отказ при выполнении функции fclose() происходит только тогда, когда диск был преждевременно удален из дисковода или на диске не осталось свободного места.
Правомочность открытия файла с помощью функции fopen() обычно подтверждается после проверки какой-либо ошибки, например, когда на диске нет места для записи или неправильного имени диска, причем эти ошибки будут обнаружены до того, как программа попытается в этот файл что-либо записать. Поэтому приведенный фрагмент С -кода будет правильным, если производится проверка возможности открытия файла:
FILE *fp;
if ((fp = fopen("D:\\data.txt", "w")) == NULL) {
//exit(1);
printf("\n\t Error! Can not open file\n ");
printf("\n Press any key: ");
_getch(); return 0; }
fprintf(fp, "\n\t hello, world\n");
fclose(fp);
При выполнении условия проверки можно выходить при нажатии любой клавиши с заданным сообщением или немедленный выход сделать с помощью функции exit(), которая в данном фрагменте С -кода закомментирована.
Функции для работы с текстовыми файлами удобно использовать при создании текстовых файлов, ведении файлов-протоколов и т.п. Но при создании баз данных целесообразно использовать функции для работы с fwrite() и . Эти функции без каких-либо изменений копируют выделенный блок данных из оперативной памяти в файл и, соответственно, из файла – в память [12.1].
При записи или чтении суффикс "t" открывает файл в текстовом режиме. В этом режиме символ CTRL+Z (символ с кодом 26) обрабатывается как символ конца файла. Кроме того, комбинации символов перевода строки и возврата каретки преобразуются в единственный символ перевода строки ( '\n' ) при вводе, и символы перевода строки преобразуются в комбинации символов перевода строки и возврата каретки при выводе.
Суффикс "b" открывает файл в бинарном режиме, преобразования символов перевода строки и возврата каретки не производятся.
FILE *fp;
if ((fp = fopen("D:\\data.txt", "w")) == NULL) {
//exit(1);
printf("\n\t Error! Can not open file\n ");
printf("\n Press any key: ");
_getch(); return -1; }
fprintf(fp, "\n\t hello, world\n");
fclose(fp);
Пример 1. Напишите программу заполнения матрицы размера n $$\times$$ m нечетными целыми числами с выводом результата на консоль и в текстовый файл. Размеры матрицы и начальное нечетное число задаются пользователем с клавиатуры.
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int main(void) {
int i, j, x, xi, n, m, *matr;
FILE *fid;
char str[] = "D:\\data.txt"; // месторасположение файла
if ((fid = fopen(str, "w")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0; }
printf("\n\t Enter the number of lines: "); scanf_s("%d", n);
printf("\t Enter the number of columns: "); scanf_s("%d", m);
printf("\t Enter the odd number: "); scanf_s("%d", x);
xi = x;
matr = (int *)calloc(n*m, sizeof(int));
// Заполнение матрицы целыми числами
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
{matr[i*m + j] = x; x += 2; }
printf("\n\t Matrix (%d x %d), initial number: %d\n", n, m, xi);
fprintf(fid, "\r\n\t Matrix (%d x %d), initial number: %d\r\n", n, m, xi);
for (i = 0; i < n; ++i){
printf("\n "); fprintf(fid, "\r\n ");
for (j = 0; j < m; ++j){
printf("%5d", matr[i*m + j]);
fprintf(fid, "%5d", matr[i*m + j]); }
}
fclose(fid);
printf("\n\n Result of record look in file %s\n", str);
printf("\n Press any key: ");
_getch();
return 0;
}
В программу включена препроцессорная директива #define... для устранения предупреждения о ненадежной работе функции fopen() в Visual Studio 2008.
Возможный результат выполнения программы показан на рис 12.1.
(рис 12.1) Заполнение матрицы нечетными числамиТекстовый файл с заполненной матрицей показан на рис 12.2.
(рис 12.2) Матрица нечетных чисел в текстовом файлеПримечание. В текстовом файле следует использовать моноширинный (равноширинный) шрифт, например, Courier New.
Задание 1
calloc() примените функцию malloc().Пример 2. Напишите программу посимвольной записи в текстовый файл некоторой строки, набранной на консоли, и посимвольного чтения из текстового файла с перезаписью в другой текстовый файл.
В качестве строки возьмем "hello, world". Для посимвольной записи в файл используем функции putc() и fputc(), которые реализованы для сохранения совместимости со старыми версиями языка С. Для прекращения чтения символов с клавиатуры используем точку, т.е. '.'.
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
int main(void){
char ch; FILE *f_in, *f_out;
char str[] = "D:\\data.txt"; // Файл записи
char str2[] = "D:\\data2.txt";// Файл перезаписи
if ((f_in = fopen(str, "w")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0;}
printf("\n Enter the characters by pressing Enter and exit point:\n\n> ");
while ((ch = getchar()) != '.')
{ printf(" "); fputc(ch, f_in);}
fclose(f_in);
if ((f_in = fopen(str, "r")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0; }
if ((f_out = fopen(str2, "w")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0;}
while((ch = getc(f_in)) != EOF) putc(ch, f_out);
fclose(f_in);
fclose(f_out);
printf("\n\n Result of record look in file %s\n", str);
printf(" Result of rewriting look in file %s\n", str2);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе сначала открывается файл data.txt для записи в него символов, затем он закрывается. После этот же файл открывается для считывания записанных символов с целью записи их в другой файл, под именем data2.txt. Всякий раз производится проверка возможности открытия файлов. Запись символов в текстовый файл выполняется с помощью функций putc() и fputc(). Считывание символов из файла осуществляется с помощью функции getc().
В среде Visual Studio стандартная функция fopen() языка С вызывает предупреждение при компиляции программы. Для устранения предупреждений при компиляции в программу включена препроцессорная директива #define_CRT_SECURE_NO_WARNINGS.
Результат выполнения программы показан на рис 12.3.
(рис 12.3) Консольный ввод символов для записи в файл Задание 2
fgetc() для чтения символов из файла.Пример 3. Напишите программу чтения из текстового файла массива строк, вывода этих строк на консоль и записи их в другой файл.
Для решения примера используем функции fgets() – для чтения строк из текстового файла, fputs() – для записи строк в текстовый файл. Содержание текстового файла для считывания – это обложка книги [12.3]:
=============================================
THE
_____________________________________________
C
_____________________________________________
PROGRAMMING
LANGUAGE
=============================================
Second Edition
BRIAN W. KERIGHAN
DENNIS M. RITCHIE
AT T Bell Laboratories
Murray Hill, New Jersey
Prentice Hall PTR, Upper Saddle River, New Jersey 07458
_________________________________________________________
Файлу, из которого будет считываться информация, присвоим имя data3.txt. Файлу, куда будет записываться информация, присвоим имя data33.txt.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
int main(void){
char str[255+1];
char data3[] = "D:\\data3.txt";
char data33[] = "D:\\data33.txt";
FILE *fid, *fid2;
errno_t err;
if ((fopen_s(fid, "D:\\data3.txt", "r")) ||
(err = fopen_s(fid2, "D:\\data33.txt", "w")) != 0)
{ printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch();
return 0; }
while (fgets(str, 255, fid) != NULL) // Чтение из data3.txt
{fputs(str, stdout); // Вывод на консоль
fputs(str, fid2); // Запись в файл data33.txt
}
fclose(fid);
fclose(fid2);
printf(" Read the information was produced from a file %s\n", data3);
printf(" Recorded information has been made to the file %s\n", data33);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе с помощью логического условия ИЛИ ( || ) производится проверка корректности открытия файла data3.txt для чтения и проверка открытия файла data33.txt для записи. Вместо функции fopen() используется функция fopen_s(), которая применяется в MS Visual Studio.
Функция fgets() считывает строки из файла, на который имеется файловый указатель *fid, записывает их в str[256]. Одно поле функции fgets() используется для определения количества считываемых символов с учетом символа завершения строки.
Первая функция fputs() используется для вывода информации на консоль с помощью определения стандартного выходного потока stdout, который указывает на "обычное" средство вывода – дисплей. Вторая функция fputs() выводит str[] в файл data33.txt с помощью файлового указателя *fid2. Вывод на дисплей и запись в файл будет осуществляться до тех пор, пока при чтении из файла data3.txt не обнаружится NULL. Проверку можно выполнять также по числу считанных символов, а именно n –1, т.е. в данном случае 255 символов из 256.
Результат выполнения программы с выводом текстовой информации на консоль показан на рис 12.4.
(рис 12.4) Консольный вывод содержимого текстового файлаРезультат записи информации в текстовый файл показан на рис 12.5.
(рис 12.5) Результат записи текстовой информации в текстовый файлЗадание 3
while().printf(), а запись в файл – с помощью функции fprintf().Примечание. Для п.5 задания 3 примените массив указателей для считывания строк разной длины.
Пример 4. Напишите программу форматированной записи в текстовый файл трех строк различной длины и одномерного целочисленного массива. Произведите чтение из текстового файла с выводом его содержания на консоль и преобразования одномерного массива в двухмерный.
Для решения примера используем функции fprintf(), fgets(), atoi(), fscanf().
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define n 4 // Число строк матрицы
#define m 3 // Число столбцов матрицы
#define N 123 // Число считываемых строк из текстового файла
int main(void) {
int i, j = 0;
int A[n*m] = {1,2,3,4,5,6,7,8,9,10,11,12};
int B[n*m];
FILE *fid;
char *str[] = {"aza","baza","qwerty"};
char str2[N][80]; // Буферный массив
// Обнуление массива B[n*m]
for (i = 0; i < n*m; ++i) B[i] = 0;
if ((fid = fopen("D:\\data4.txt", "w")) == NULL)
{printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: "); _getch(); return 0; }
// Запись в файл data4.txt
fprintf(fid, "\n\t The lines are:\n");
for (i = 0; i < m; ++i) fprintf(fid,"\t %s\n", str[i]);
for (i = 0; i < n*m; ++i)
fprintf(fid, " %3d", A[i]);
fclose(fid);
printf("\n\t From file \"data4.txt\":\n");
if ((fid = fopen("D:\\data4.txt", "r")) == NULL)
{printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: "); _getch(); return 0; }
// Чтение из файла data4.txt
for (i = 0; (fgets(str2[i], 80, fid) != NULL) (i < N); ++i)
printf(" %s",str2[i]);
fclose(fid);
if ((fid = fopen("D:\\data4.txt", "r")) == NULL)
{printf("\n\t Error! You can not open the file \n ");
printf("\n Press any key: "); _getch(); return 0; }
// Повторное чтение из файла data4.txt
for (i = 0; fscanf (fid, "%s", str2[i]) != EOF; ++i)
if (atoi(str2[i]))
{ B[j] = atoi(str2[i]); ++j; }
fclose(fid);
printf("\n\n\t The reconfigured array:\n");
for (i = 0; i < n; ++i) {
printf("\n\t");
for (j = 0; j < m; ++j)
printf("%5d", B[i*m+j]); }
printf("\n\n Press any key: ");
_getch();
return 0;
}
Для форматированной записи в текстовый файл и чтения из файла применены массивы указателей *str[], str2[123][80]. Чтение из файла одномерного массива целых чисел выполняется с помощью функции atoi(), значения целых чисел заносятся сначала в одномерный массив B[n*m]. После закрытия файла data4.txt одномерный массив B[n*m] выводится на консоль в виде двухмерной матрицы размера 4 $$\times$$ 3. Форматированная запись строк и одномерного массива в файл data4.txt производится с помощью функции fprintf(). Первое чтение информации из текстового файла производится с помощью функции fgets(), что позволяет практически точно копировать расположение строк текстового файла на консоль (дисплей). Функция fscanf() используется для форматированного чтения информации из текста с посл
едующим выделением целых чисел с помощью функции atoi().
Возможный результат выполнения программы показан на рис 12.6.
(рис 12.6) Содержимое текстового файла и преобразованного массива Задание 4
fgets() и fscanf().Пример 5. Напишите программу добавления слов в текстовый файл с контролем на консоли [9].
В текстовый файл запишем название книги и авторов [3]. После будем добавлять слова, символы и т.д.
Для программного решения примера используем функции файлового ввода/вывода fprintf(), fgets() и . Кроме того, подключим библиотеку locale.h и объявим прототип функции, что позволит использовать шрифты русского алфавита:>
#include <locale.h>
setlocale( LC_ALL, "Russian");
или
setlocale( LC_ALL, ".1251");//кодовая страница Windows–1251
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <locale.h>
#define MAX 40
int main(void) {
FILE *fid;
char words[MAX+1];
char str_name[] = "D:\\data5.txt";
// Прототип функции поддержки русских шрифтов
setlocale( LC_ALL, "Russian");
// setlocale( LC_ALL, ".1251");
if ((fid = fopen(str_name, "a+")) == NULL)
{fprintf(stdout, "\n\t Файл не может быть открыт \"%s\".\n ", str_name);
printf("\n Нажмите любую клавишу: ");
_getch(); return -1; }
printf("\n\t Введите слова для включения их в файл \"%s\"\n\t\
и нажмите клавишу Enter в начале строки для завершения ввода\n\t: ", str_name);
// Запись в файл data5.txt
while (gets_s(words, MAX) != NULL words[0] != '\0')
{printf("\t: "); fprintf(fid," %s\n", words); }
puts("\t Содержимое файла:");
// Устанавливает указатель текущей позиции в начало файла
rewind(fid);
// Сканирование файла
while (fgets(words, MAX, fid) != '\0')
printf("\t%s", words);
if (fclose(fid) != 0)
fprintf(stderr, "\n\t Ошибка при закрытии файла \"%s\"\n", str_name);
printf("\n\n Нажмите любую клавишу (Press any key): ");
_getch();
return 0;
}
В программе введены две проверки: на открытие файла if (... == NULL) и на закрытие файла if (... != 0). Эти проверки позволяют исключить аварийный выход из программы. Использование в функции форматного вывода fprintf() ключевого слова stdout позволяет выводить сообщения на консоль – дисплей пользователя.
Вместо стандартной функции gets() использована функция gets_s(), которую поддерживает MS Visual Studio. При работе в MS Visual Studio с функцией gets() появляются предупреждения (которыми в общем случае можно пренебречь). Предупреждения возникают и при работе с функцией fopen(). Вместо нее можно использовать fopen_s() в следующем формате записи:
fopen_s(fid, "D:\\data5.txt","a+");
Тогда проверку на открытие файла следует изменить, например:
if (fopen_s(fid, "D:\\data5.txt","a+"))
{fprintf(stdout, "\n\t Ошибка! Не удается открыть файл \"data5.txt\".\n ");
printf("\n Нажмите любую клавишу: ");
_getch(); return -1; }
Если файл data5.txt сохранить, то при последующих выполнениях программы в этот файл будут дописывать данные. Это обеспечивает режим "a+" функции fopen().
Возможный результат выполнения программы показан на рис 12.7.
(рис 12.7) Пример записи в файл и чтения из файлаЗадание 5
fopen_s() вместо функции fopen(). Отметьте результат компиляции.fgets() включите функцию fscanf(). Отметьте результат записи и чтения нескольких строк, состоящих из нескольких слов.Примечание. Для данной программы формат записи функции fscanf():
fscanf(fid, "%s", words);
Пример 6. Напишите программу записи в файл нескольких строк и отображения содержимого файла в обратном порядке, как на консоли, так и в другом текстовом файле.
Для решения примера используем функции fseek() и ftell().
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#define MAX 79
#define file "D:\\data6.txt" // запись в прямом порядке
#define file2 "D:\\data66.txt" // запись в обратном порядке
int main(void) {
char ch, str[MAX+1];
long n, m;
FILE *fid, *fid2;
if ( fopen_s(fid, file, "w") ) {
fprintf(stdout, "\n\t The file could not be opened.\n ");
printf("\nPress any key: ");
_getch(); return 0; }
printf("\n\t Enter a few lines and press Enter to complete before the new line\n\t: ");
// Запись в файл data6.txt
while (gets_s(str, MAX) != NULL str[0] != '\0')
{ printf("\t: "); fprintf(fid," %s\n", str); }
fclose(fid);
if ( fopen_s(fid, file, "r") ) {
fprintf(stdout, "\n\t File could not be opened.\n");
printf("\n Press any key: ");
_getch(); return 0; }
if ( fopen_s(fid2, file2, "w") ) {
fprintf(stdout, "\n\t File could not be opened.\n");
printf("\n Press any key: ");
_getch(); return 0; }
//Переход в конец файла
fseek(fid, 0L, SEEK_END);
m = ftell(fid);
for (n = 1L; n <= m; n++) {
fseek(fid, -n, SEEK_END);
ch = getc(fid);
if (ch != '\n') {
printf(" "); putchar(ch);
fprintf(fid2, " "); putc(ch, fid2); }
} // End for
putchar('\n');
fclose(fid);
fprintf(fid2, "%c", '\n');
fclose(fid2);
printf("\n Result see the files, \"%s\" and \"%s\"\n", file, file2);
printf("\n Press any key: ");
_getch();
return 0;
}
Работу функций fseek() и ftell() опишем в соответствии с [9].
Функция fseek() имеет следующую форматную запись:
fseek(fid, 0L, SEEK_END);
Она определяет позицию со смещением в 0 байт от конца файла (SEEK_END ). Суффикс L означает тип long int.
Строка с функцией ftell() определяет количество байтов от начала до конца указанного файла. Это количество байтов записывается в переменную m:
m = ftell(fid);
Рассмотрим следующий программный цикл:
for (n = 1L; n <= m; n++) {
fseek(fid, -n, SEEK_END);
ch = getc(fid);
if (ch != '\n')
{ printf(" "); putchar(ch);
fprintf(fid2, " "); putc(ch, fid2); }
} // End for
Первое выполнение
Возможные результаты выполнения программы показаны на рис 12.8-рис 12.9–рис 12.10.

(рис 12.9) Результат обратного считывания информации из файла(рис 12.8) Результат записи информации в файл
(рис 12.10) Результат записи информации в файл в обратном порядке Задание 6
putchar() примените printf().putc() примените функцию с тем же действием.Пример 7. Создайте файл последовательного доступа и записать в него информацию, состоящую из целых чисел, строки символов и вещественных чисел. После произведенной записи выведите содержимое файла на консоль и перезапишите в другой файл.
Предположим, что имеются номера ячеек, их имена (например, по фамилии владельца) и определенное количество денег в условных единицах (у. е.).
Для форматированного считывания данных из файла применим библиотечную функцию fscanf().
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#define MAX 39 // Предполагаемое число символов в имени
#define file "D:\\data7.dat"
#define file2 "D:\\data77.dat"
int main(void)
{
int number, i = 1, j = 1; // номер ячейки
char name[MAX+1]; // имя ячейки (владельца)
long double sum; // сумма денег в у.е.
FILE *fid, *fid2;
if ( fopen_s(fid, file, "w") )
{fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
printf("\n Enter through blanks number of a cell,\n a name of the owner and the sum of money.\n \
Type Ctrl+Z to exit at the beginning of a new line: \n\n");
printf(" %3d) ", i);
scanf("%d%s%lf", number, name, sum);
// Запись в файл data7.dat
while ( !feof(stdin)) { // stdin - поток с клавиатуры
fprintf(fid, " %3d\t %-15s %7.2f\r\n", number, name, sum);
printf(" %3d) ", ++i);
scanf("%d%s%lf", number, name, sum);
}
fclose(fid);
if ( fopen_s(fid, file, "r") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
if ( fopen_s(fid2, file2, "w") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
// Вывод на консоль
printf("\n %s\t %s\t\t %5s", "The number of cell", "Name", "Sum");
// Чтение из файла data7.dat
fscanf(fid, "%d%s%Lf", number, name, sum);
fprintf(fid2, "\r\n %s\t\t %s\t\t %5s\r\n", "The number of cell", "Name", "Sum");
i = 1;
while ( !feof(fid)) { // пока не конец файла
// Вывод на консоль
printf("\n %3d\t\t\t %-17s %1.2f", number, name, sum);
// Запись в файл data77.dat
fprintf(fid2, " %3d) %3d\t\t\t %-17s %1.2f\r\n", i++, number, name, sum);
// Чтение из файла data7.dat
fscanf(fid, "%d%s%Lf", number, name, sum);
}
fclose(fid);
fclose(fid2);
printf("\n\n\n Result see the files, \"%s\" and \"%s\"\n", file, file2);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе использована функция feof(), которая проверяет, достигнут ли конец файла, связанного с потоком (указателем на файл) fid.
На рис 12.11 показан возможный результат выполнения программы.
(рис 12.11) Консольный вывод содержимого файлаСледует обратить внимание на прекращение ввода данных с клавиатуры с помощью комбинации клавиш Ctrl+Z.
Задание 7
while примените оператор цикла for.Пример 8. Напишите программу пакетной записи в файл произвольного доступа массива данных и вывода этого пакета на консоль.
Для решения примера применим функции fwrite() и для бинарной записи и считывания информации.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#define MAX 20
#define n 5
#define m 4
#define file "D:\\data8.txt"
int main(void) {
//Матрица 5х4
int mass[MAX][MAX] = {
{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}, {17,18,19,20} };
int mass2[MAX][MAX]; // Вспомогательная матрица
int i, j;
// Массив из 5 указателей
char *str[] = {
"Brian W. Kernighan",
"Dennis M. Ritchie",
"Stephen Prata",
"Herbert Shildt",
"The C Programming Language"
};
char *str2[n]; // Вспомогательный массив указателей
FILE *fid;
if ( fopen_s(fid, file, "wb") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Error! Press any key: ");
_getch(); return 0; }
fwrite(str, sizeof(char), sizeof(str)/sizeof(char), fid);
fwrite(mass, sizeof(int), sizeof(mass)/sizeof(int), fid);
fclose (fid);
if ( fopen_s(fid, file, "rb") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
fread(str2, sizeof(char), sizeof(str)/sizeof(char), fid);
fread(mass2, sizeof(int), sizeof(mass2)/sizeof(int), fid);
// Чтение элементов из файла
printf("\n\t From a file \"%s\": \n\n", file);
for (i = 0; i < n; ++i)
printf("\t %-15s\n", str2[i]);
printf("\n\t Matrix from a file \"%s\":\n", file);
for (i = 0; i < n; ++i) {
printf("\n\t");
for (j = 0; j < m; ++j)
printf(" %3d", mass2[i][j]);
}
fclose(fid);
printf("\n\n\n Press any key: ");
_getch();
return 0;
}
Функция fwrite() пересылает в файл заданное количество байт начиная с указанного адреса памяти. Данные записываются с того места в файле, которое обозначено указателем позиции файла. Функция пересылает заданное количество байт на места в файле, определенного указателем позиции файла, в массив в памяти, начинающийся с указанного адреса.
В программе пакетная запись информации – набора строк и матрицы целых чисел производится через двоичный поток с помощью функций fwrite(). Чтение информации из двоичного файла осуществляется функцией . Форматы записи обеих функций одинаковый, так как в них требуется определить количество объектов с заданным размером байт, которые определяются функцией sizeof().
Результат выполнения программы показан на рис 12.12 и на рис 12.13.

(рис 12.13) Результат чтения из файла бинарной информации(рис 12.12) Результат записи в текстовый файл бинарной информацииКак видно из рисунков, информация на консоли соответствует исходной информации, а в двоичном файле информация не подлежит непосредственному восприятию.
Примечание. Вид бинарной информации в текстовом файле зависит от установленных шрифтов.
Задание 8
Файл – это именованный объект, хранящий данные (программа или любая другая информация) на каком-либо носителе (дискета,
В языке С файлом может быть все что угодно, начиная с дискового файла и заканчивая терминалом или принтером [12.2]. Поток связывают с определенным файлом, выполняя операцию открытия. Как только файл открыт, можно проводить обмен информацией между ним и программой.
Не у всех файлов одинаковые возможности. Например, к дисковому файлу прямой доступ возможен, в то время как к некоторым принтерам – нет. В языке С все потоки одинаковы, а файлы – нет [12.2].
Если файл может поддерживать запросы на местоположение (
Файл отсоединяется от определенного потока (т.е. разрывается связь между файлом и потоком) с помощью операции закрытия. При закрытии файла, открытого с целью вывода, содержимое (если оно есть) связанного с ним потока записывается на внешнее устройство. Этот процесс, который обычно называют дозаписью потока, гарантирует, что никакая информация случайно не останется в буфере диска. Если программа завершает работу нормально, т.е. либо функция main() возвращает управление операционной системе, либо вызывается функция exit(), то все файлы закрываются автоматически. В случае аварийного завершения программы, например, в случае краха или завершения путем вызова функции abort(), файлы не закрываются [12.2].
Файловая системы языка С предназначена для работы с самыми разнообразными устройствами, в том числе терминалами, дисками и накопителями на магнитной ленте. Даже если какое-то устройство сильно отличается от других, буферизованная файловая система все равно представит его в виде логического устройства, которое называется потоком. Потоки бывают двух видов: текстовые и двоичные [12.2].
Текстовый поток – это последовательность символов. В стандарте С считается, что текстовый поток организован в виде строк, каждая из которых заканчивается символом новой строки. Однако в конце последней строки этот символ не является обязательным. В текстовом потоке по требованию базовой среды могут происходить определенные преобразования символов. Например, символ новой строки может быть заменен парой символов – возврата каретки (например, \r ) и перевода строки (например, \n ), т.е. \r\n.
Двоичные потоки – это последовательность байтов, которая взаимно однозначно соответствует байтам на внешнем устройстве, причем никакого преобразования символов не происходит [12.2]. Кроме того, количество тех байтов, которые пишутся (читаются), и тех, которые хранятся на внешнем устройстве, одинаково. Однако в конце двоичного потока может добавляться определяемое приложением количество нулевых байтов. Такие нулевые байты, например, могут использоваться для заполнения свободного места в блоке памяти незначащей информацией, чтобы она в точности заполнила сектор на диске.
Файловая система языка С состоит из нескольких взаимосвязанных функций [12.2]. Самые распространенные из них показаны в табл. 12.1.
| Функции файловой системы языка С | ||
|---|---|---|
| № п/п | Имя функции | Что делает |
| 1. | fopen() |
Открывает файл |
| 2. | fclose() |
Закрывает файл |
| 3. | putc() |
Записывает символ в файл |
| 4. | fputc() |
То же, что и putc() |
| 5. | getc() |
Читает символ из файла |
| 6. | fgetc() |
То же, что и getc() |
| 7. | fgets() |
Читает строку из файла |
| 8. | fputs() |
Записывает строку в файл |
| 9. | fseek() |
Устанавливает |
| 10. | ftell() |
Возвращает текущее значение указателя текущей позиции в файле |
| 11. | fprintf() |
Для файла то же, что printf() для консоли |
| 12. | fscanf() |
Для файла то же, что scanf() для консоли |
| 13. | feof() |
Возвращает значение true (истина), если достигнут конец файла |
| 14. | ferror() |
Возвращает значение true (истина), если произошла ошибка |
| 15. | |
Устанавливает |
| 16. | remove() |
Стирает файл |
| 17. | fflush() |
Дозапись потока в файл |
Для приведенных функций требуется подключить заголовок <stdio.h>. Запись или чтение из файла осуществляются с помощью указателя файла. Указатель файла – это указатель на структуру типа FILE. Для объявления переменной–указателя файла, например, *fp, используется следующий оператор:
FILE *fp;
Ключевое слово FILE определяет собой своеобразный тип данных, а указатель *fp указывает на этот тип.
Указатель файла указывает на структуру, содержащую различные сведения о файле, его имя, статус и
Открытие файла осуществляется с помощью функции fopen(), которая открывает поток и связывает с этим потоком определенный файл. Прототип функции fopen() такой:
FILE *fopen(const char *file_name, const char *mode);
В прототипе функции fopen() формальные переменные имеют следующий смысл:
file_name – это имя файла с заданным расширением и возможным путем расположения, mode – режим работы файла: чтение, запись и т.д. [12.1].
В табл. 12.2, взятой из [12.2], приводятся допустимые значения режима для функции fopen().
Допустимые значения режима функции fopen() | ||
|---|---|---|
| № п/п | Режим | Что означает |
| 1. | r | Открыть текстовый файл для чтения |
| 2. | w | Создать текстовый файл для записи |
| 3. | a | Добавить в конец текстового файла |
| 4. | rb | Открыть двоичный файл для чтения |
| 5. | wb | Создать двоичный файл для записи |
| 6. | ab | Добавить в конец двоичного файла |
| 7. | r+ | Открыть текстовый файл для чтения/записи |
| 8. | w+ | Создать текстовый файл для чтения/записи |
| 9. | a+ | Добавить в конец текстового файла или создать текстовый файл для чтения/записи |
| 10. | r+b | Открыть двоичный файл для чтения/записи |
| 11. | w+b | Создать двоичный файл для чтения/записи |
| 12. | a+b | Добавить в конец двоичного файла или создать двоичный файл для чтения/записи |
Например, для записи в файл с именем (и расширением) data.txt на диск D следует использовать такие объявление и операции:
FILE *fp;
fp = fopen("D: \\data.txt", "w");
fprintf(fp, "\n\t hello, world\n");
fclose(fp);
В приведенном фрагменте С -кода функция fclose() закрывает поток, который был открыт с помощью вызова функции fopen(). Функция fprintf() осуществляет форматную запись (в данном случае строку hello, world ) в файл. Все манипуляции с файлом происходят между функциями fopen() и fclose(). Режим функции fopen() задается строкой "w", которая обеспечивает создание текстового файла для записи. Это означает, что файл data.txt создается на диске D и в него записывается строка hello, world с отступом от верхнего края и с отступом (табуляцией) от левого края.
Прототип функции fclose() следующий:
int fclose(FILE *fp);
В приведенной записи *fp – указатель файла, возвращенный в результате вызова функции fopen() [12.2]. Возвращение нуля означает успешную операцию закрытия. В случае же ошибки возвращается EOF. Обычно отказ при выполнении функции fclose() происходит только тогда, когда диск был преждевременно удален из дисковода или на диске не осталось свободного места.
Правомочность открытия файла с помощью функции fopen() обычно подтверждается после проверки какой-либо ошибки, например, когда на диске нет места для записи или неправильного имени диска, причем эти ошибки будут обнаружены до того, как программа попытается в этот файл что-либо записать. Поэтому приведенный фрагмент С -кода будет правильным, если производится проверка возможности открытия файла:
FILE *fp;
if ((fp = fopen("D:\\data.txt", "w")) == NULL) {
//exit(1);
printf("\n\t Error! Can not open file\n ");
printf("\n Press any key: ");
_getch(); return 0; }
fprintf(fp, "\n\t hello, world\n");
fclose(fp);
При выполнении условия проверки можно выходить при нажатии любой клавиши с заданным сообщением или немедленный выход сделать с помощью функции exit(), которая в данном фрагменте С -кода закомментирована.
Функции для работы с текстовыми файлами удобно использовать при создании текстовых файлов, ведении файлов-протоколов и т.п. Но при создании баз данных целесообразно использовать функции для работы с fwrite() и . Эти функции без каких-либо изменений копируют выделенный блок данных из оперативной памяти в файл и, соответственно, из файла – в память [12.1].
При записи или чтении суффикс "t" открывает файл в текстовом режиме. В этом режиме символ CTRL+Z (символ с кодом 26) обрабатывается как символ конца файла. Кроме того, комбинации символов перевода строки и возврата каретки преобразуются в единственный символ перевода строки ( '\n' ) при вводе, и символы перевода строки преобразуются в комбинации символов перевода строки и возврата каретки при выводе.
Суффикс "b" открывает файл в бинарном режиме, преобразования символов перевода строки и возврата каретки не производятся.
FILE *fp;
if ((fp = fopen("D:\\data.txt", "w")) == NULL) {
//exit(1);
printf("\n\t Error! Can not open file\n ");
printf("\n Press any key: ");
_getch(); return -1; }
fprintf(fp, "\n\t hello, world\n");
fclose(fp);
Пример 1. Напишите программу заполнения матрицы размера n $$\times$$ m нечетными целыми числами с выводом результата на консоль и в текстовый файл. Размеры матрицы и начальное нечетное число задаются пользователем с клавиатуры.
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int main(void) {
int i, j, x, xi, n, m, *matr;
FILE *fid;
char str[] = "D:\\data.txt"; // месторасположение файла
if ((fid = fopen(str, "w")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0; }
printf("\n\t Enter the number of lines: "); scanf_s("%d", n);
printf("\t Enter the number of columns: "); scanf_s("%d", m);
printf("\t Enter the odd number: "); scanf_s("%d", x);
xi = x;
matr = (int *)calloc(n*m, sizeof(int));
// Заполнение матрицы целыми числами
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
{matr[i*m + j] = x; x += 2; }
printf("\n\t Matrix (%d x %d), initial number: %d\n", n, m, xi);
fprintf(fid, "\r\n\t Matrix (%d x %d), initial number: %d\r\n", n, m, xi);
for (i = 0; i < n; ++i){
printf("\n "); fprintf(fid, "\r\n ");
for (j = 0; j < m; ++j){
printf("%5d", matr[i*m + j]);
fprintf(fid, "%5d", matr[i*m + j]); }
}
fclose(fid);
printf("\n\n Result of record look in file %s\n", str);
printf("\n Press any key: ");
_getch();
return 0;
}
В программу включена препроцессорная директива #define... для устранения предупреждения о ненадежной работе функции fopen() в Visual Studio 2008.
Возможный результат выполнения программы показан на рис 12.1.
(рис 12.1) Заполнение матрицы нечетными числамиТекстовый файл с заполненной матрицей показан на рис 12.2.
(рис 12.2) Матрица нечетных чисел в текстовом файлеПримечание. В текстовом файле следует использовать моноширинный (равноширинный) шрифт, например, Courier New.
Задание 1
calloc() примените функцию malloc().Пример 2. Напишите программу посимвольной записи в текстовый файл некоторой строки, набранной на консоли, и посимвольного чтения из текстового файла с перезаписью в другой текстовый файл.
В качестве строки возьмем "hello, world". Для посимвольной записи в файл используем функции putc() и fputc(), которые реализованы для сохранения совместимости со старыми версиями языка С. Для прекращения чтения символов с клавиатуры используем точку, т.е. '.'.
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
int main(void){
char ch; FILE *f_in, *f_out;
char str[] = "D:\\data.txt"; // Файл записи
char str2[] = "D:\\data2.txt";// Файл перезаписи
if ((f_in = fopen(str, "w")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0;}
printf("\n Enter the characters by pressing Enter and exit point:\n\n> ");
while ((ch = getchar()) != '.')
{ printf(" "); fputc(ch, f_in);}
fclose(f_in);
if ((f_in = fopen(str, "r")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0; }
if ((f_out = fopen(str2, "w")) == NULL){
printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch(); return 0;}
while((ch = getc(f_in)) != EOF) putc(ch, f_out);
fclose(f_in);
fclose(f_out);
printf("\n\n Result of record look in file %s\n", str);
printf(" Result of rewriting look in file %s\n", str2);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе сначала открывается файл data.txt для записи в него символов, затем он закрывается. После этот же файл открывается для считывания записанных символов с целью записи их в другой файл, под именем data2.txt. Всякий раз производится проверка возможности открытия файлов. Запись символов в текстовый файл выполняется с помощью функций putc() и fputc(). Считывание символов из файла осуществляется с помощью функции getc().
В среде Visual Studio стандартная функция fopen() языка С вызывает предупреждение при компиляции программы. Для устранения предупреждений при компиляции в программу включена препроцессорная директива #define_CRT_SECURE_NO_WARNINGS.
Результат выполнения программы показан на рис 12.3.
(рис 12.3) Консольный ввод символов для записи в файлЗадание 2
fgetc() для чтения символов из файла.Пример 3. Напишите программу чтения из текстового файла массива строк, вывода этих строк на консоль и записи их в другой файл.
Для решения примера используем функции fgets() – для чтения строк из текстового файла, fputs() – для записи строк в текстовый файл. Содержание текстового файла для считывания – это обложка книги [12.3]:
=============================================
THE
_____________________________________________
C
_____________________________________________
PROGRAMMING
LANGUAGE
=============================================
Second Edition
BRIAN W. KERIGHAN
DENNIS M. RITCHIE
AT T Bell Laboratories
Murray Hill, New Jersey
Prentice Hall PTR, Upper Saddle River, New Jersey 07458
_________________________________________________________
Файлу, из которого будет считываться информация, присвоим имя data3.txt. Файлу, куда будет записываться информация, присвоим имя data33.txt.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
int main(void){
char str[255+1];
char data3[] = "D:\\data3.txt";
char data33[] = "D:\\data33.txt";
FILE *fid, *fid2;
errno_t err;
if ((fopen_s(fid, "D:\\data3.txt", "r")) ||
(err = fopen_s(fid2, "D:\\data33.txt", "w")) != 0)
{ printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: ");
_getch();
return 0; }
while (fgets(str, 255, fid) != NULL) // Чтение из data3.txt
{fputs(str, stdout); // Вывод на консоль
fputs(str, fid2); // Запись в файл data33.txt
}
fclose(fid);
fclose(fid2);
printf(" Read the information was produced from a file %s\n", data3);
printf(" Recorded information has been made to the file %s\n", data33);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе с помощью логического условия ИЛИ ( || ) производится проверка корректности открытия файла data3.txt для чтения и проверка открытия файла data33.txt для записи. Вместо функции fopen() используется функция fopen_s(), которая применяется в MS Visual Studio.
Функция fgets() считывает строки из файла, на который имеется файловый указатель *fid, записывает их в str[256]. Одно поле функции fgets() используется для определения количества считываемых символов с учетом символа завершения строки.
Первая функция fputs() используется для вывода информации на консоль с помощью определения стандартного выходного потока stdout, который указывает на "обычное" средство вывода – дисплей. Вторая функция fputs() выводит str[] в файл data33.txt с помощью файлового указателя *fid2. Вывод на дисплей и запись в файл будет осуществляться до тех пор, пока при чтении из файла data3.txt не обнаружится NULL. Проверку можно выполнять также по числу считанных символов, а именно n –1, т.е. в данном случае 255 символов из 256.
Результат выполнения программы с выводом текстовой информации на консоль показан на рис 12.4.
(рис 12.4) Консольный вывод содержимого текстового файлаРезультат записи информации в текстовый файл показан на рис 12.5.
(рис 12.5) Результат записи текстовой информации в текстовый файлЗадание 3
while().printf(), а запись в файл – с помощью функции fprintf().Примечание. Для п.5 задания 3 примените массив указателей для считывания строк разной длины.
Пример 4. Напишите программу форматированной записи в текстовый файл трех строк различной длины и одномерного целочисленного массива. Произведите чтение из текстового файла с выводом его содержания на консоль и преобразования одномерного массива в двухмерный.
Для решения примера используем функции fprintf(), fgets(), atoi(), fscanf().
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define n 4 // Число строк матрицы
#define m 3 // Число столбцов матрицы
#define N 123 // Число считываемых строк из текстового файла
int main(void) {
int i, j = 0;
int A[n*m] = {1,2,3,4,5,6,7,8,9,10,11,12};
int B[n*m];
FILE *fid;
char *str[] = {"aza","baza","qwerty"};
char str2[N][80]; // Буферный массив
// Обнуление массива B[n*m]
for (i = 0; i < n*m; ++i) B[i] = 0;
if ((fid = fopen("D:\\data4.txt", "w")) == NULL)
{printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: "); _getch(); return 0; }
// Запись в файл data4.txt
fprintf(fid, "\n\t The lines are:\n");
for (i = 0; i < m; ++i) fprintf(fid,"\t %s\n", str[i]);
for (i = 0; i < n*m; ++i)
fprintf(fid, " %3d", A[i]);
fclose(fid);
printf("\n\t From file \"data4.txt\":\n");
if ((fid = fopen("D:\\data4.txt", "r")) == NULL)
{printf("\n\t The file could not be opened.\n ");
printf("\n Press any key: "); _getch(); return 0; }
// Чтение из файла data4.txt
for (i = 0; (fgets(str2[i], 80, fid) != NULL) (i < N); ++i)
printf(" %s",str2[i]);
fclose(fid);
if ((fid = fopen("D:\\data4.txt", "r")) == NULL)
{printf("\n\t Error! You can not open the file \n ");
printf("\n Press any key: "); _getch(); return 0; }
// Повторное чтение из файла data4.txt
for (i = 0; fscanf (fid, "%s", str2[i]) != EOF; ++i)
if (atoi(str2[i]))
{ B[j] = atoi(str2[i]); ++j; }
fclose(fid);
printf("\n\n\t The reconfigured array:\n");
for (i = 0; i < n; ++i) {
printf("\n\t");
for (j = 0; j < m; ++j)
printf("%5d", B[i*m+j]); }
printf("\n\n Press any key: ");
_getch();
return 0;
}
Для форматированной записи в текстовый файл и чтения из файла применены массивы указателей *str[], str2[123][80]. Чтение из файла одномерного массива целых чисел выполняется с помощью функции atoi(), значения целых чисел заносятся сначала в одномерный массив B[n*m]. После закрытия файла data4.txt одномерный массив B[n*m] выводится на консоль в виде двухмерной матрицы размера 4 $$\times$$ 3. Форматированная запись строк и одномерного массива в файл data4.txt производится с помощью функции fprintf(). Первое чтение информации из текстового файла производится с помощью функции fgets(), что позволяет практически точно копировать расположение строк текстового файла на консоль (дисплей). Функция fscanf() используется для форматированного чтения информации из текста с посл
едующим выделением целых чисел с помощью функции atoi().
Возможный результат выполнения программы показан на рис 12.6.
(рис 12.6) Содержимое текстового файла и преобразованного массиваЗадание 4
fgets() и fscanf().Пример 5. Напишите программу добавления слов в текстовый файл с контролем на консоли [9].
В текстовый файл запишем название книги и авторов [3]. После будем добавлять слова, символы и т.д.
Для программного решения примера используем функции файлового ввода/вывода fprintf(), fgets() и . Кроме того, подключим библиотеку locale.h и объявим прототип функции, что позволит использовать шрифты русского алфавита:>
#include <locale.h>
setlocale( LC_ALL, "Russian");
или
setlocale( LC_ALL, ".1251");//кодовая страница Windows–1251
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <locale.h>
#define MAX 40
int main(void) {
FILE *fid;
char words[MAX+1];
char str_name[] = "D:\\data5.txt";
// Прототип функции поддержки русских шрифтов
setlocale( LC_ALL, "Russian");
// setlocale( LC_ALL, ".1251");
if ((fid = fopen(str_name, "a+")) == NULL)
{fprintf(stdout, "\n\t Файл не может быть открыт \"%s\".\n ", str_name);
printf("\n Нажмите любую клавишу: ");
_getch(); return -1; }
printf("\n\t Введите слова для включения их в файл \"%s\"\n\t\
и нажмите клавишу Enter в начале строки для завершения ввода\n\t: ", str_name);
// Запись в файл data5.txt
while (gets_s(words, MAX) != NULL words[0] != '\0')
{printf("\t: "); fprintf(fid," %s\n", words); }
puts("\t Содержимое файла:");
// Устанавливает указатель текущей позиции в начало файла
rewind(fid);
// Сканирование файла
while (fgets(words, MAX, fid) != '\0')
printf("\t%s", words);
if (fclose(fid) != 0)
fprintf(stderr, "\n\t Ошибка при закрытии файла \"%s\"\n", str_name);
printf("\n\n Нажмите любую клавишу (Press any key): ");
_getch();
return 0;
}
В программе введены две проверки: на открытие файла if (... == NULL) и на закрытие файла if (... != 0). Эти проверки позволяют исключить аварийный выход из программы. Использование в функции форматного вывода fprintf() ключевого слова stdout позволяет выводить сообщения на консоль – дисплей пользователя.
Вместо стандартной функции gets() использована функция gets_s(), которую поддерживает MS Visual Studio. При работе в MS Visual Studio с функцией gets() появляются предупреждения (которыми в общем случае можно пренебречь). Предупреждения возникают и при работе с функцией fopen(). Вместо нее можно использовать fopen_s() в следующем формате записи:
fopen_s(fid, "D:\\data5.txt","a+");
Тогда проверку на открытие файла следует изменить, например:
if (fopen_s(fid, "D:\\data5.txt","a+"))
{fprintf(stdout, "\n\t Ошибка! Не удается открыть файл \"data5.txt\".\n ");
printf("\n Нажмите любую клавишу: ");
_getch(); return -1; }
Если файл data5.txt сохранить, то при последующих выполнениях программы в этот файл будут дописывать данные. Это обеспечивает режим "a+" функции fopen().
Возможный результат выполнения программы показан на рис 12.7.
(рис 12.7) Пример записи в файл и чтения из файлаЗадание 5
fopen_s() вместо функции fopen(). Отметьте результат компиляции.fgets() включите функцию fscanf(). Отметьте результат записи и чтения нескольких строк, состоящих из нескольких слов.Примечание. Для данной программы формат записи функции fscanf():
fscanf(fid, "%s", words);
Пример 6. Напишите программу записи в файл нескольких строк и отображения содержимого файла в обратном порядке, как на консоли, так и в другом текстовом файле.
Для решения примера используем функции fseek() и ftell().
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#define MAX 79
#define file "D:\\data6.txt" // запись в прямом порядке
#define file2 "D:\\data66.txt" // запись в обратном порядке
int main(void) {
char ch, str[MAX+1];
long n, m;
FILE *fid, *fid2;
if ( fopen_s(fid, file, "w") ) {
fprintf(stdout, "\n\t The file could not be opened.\n ");
printf("\nPress any key: ");
_getch(); return 0; }
printf("\n\t Enter a few lines and press Enter to complete before the new line\n\t: ");
// Запись в файл data6.txt
while (gets_s(str, MAX) != NULL str[0] != '\0')
{ printf("\t: "); fprintf(fid," %s\n", str); }
fclose(fid);
if ( fopen_s(fid, file, "r") ) {
fprintf(stdout, "\n\t File could not be opened.\n");
printf("\n Press any key: ");
_getch(); return 0; }
if ( fopen_s(fid2, file2, "w") ) {
fprintf(stdout, "\n\t File could not be opened.\n");
printf("\n Press any key: ");
_getch(); return 0; }
//Переход в конец файла
fseek(fid, 0L, SEEK_END);
m = ftell(fid);
for (n = 1L; n <= m; n++) {
fseek(fid, -n, SEEK_END);
ch = getc(fid);
if (ch != '\n') {
printf(" "); putchar(ch);
fprintf(fid2, " "); putc(ch, fid2); }
} // End for
putchar('\n');
fclose(fid);
fprintf(fid2, "%c", '\n');
fclose(fid2);
printf("\n Result see the files, \"%s\" and \"%s\"\n", file, file2);
printf("\n Press any key: ");
_getch();
return 0;
}
Работу функций fseek() и ftell() опишем в соответствии с [9].
Функция fseek() имеет следующую форматную запись:
fseek(fid, 0L, SEEK_END);
Она определяет позицию со смещением в 0 байт от конца файла (SEEK_END ). Суффикс L означает тип long int.
Строка с функцией ftell() определяет количество байтов от начала до конца указанного файла. Это количество байтов записывается в переменную m:
m = ftell(fid);
Рассмотрим следующий программный цикл:
for (n = 1L; n <= m; n++) {
fseek(fid, -n, SEEK_END);
ch = getc(fid);
if (ch != '\n')
{ printf(" "); putchar(ch);
fprintf(fid2, " "); putc(ch, fid2); }
} // End for
Первое выполнение
Возможные результаты выполнения программы показаны на рис 12.8-рис 12.9–рис 12.10.

(рис 12.9) Результат обратного считывания информации из файла(рис 12.8) Результат записи информации в файл
(рис 12.10) Результат записи информации в файл в обратном порядкеЗадание 6
putchar() примените printf().putc() примените функцию с тем же действием.Пример 7. Создайте файл последовательного доступа и записать в него информацию, состоящую из целых чисел, строки символов и вещественных чисел. После произведенной записи выведите содержимое файла на консоль и перезапишите в другой файл.
Предположим, что имеются номера ячеек, их имена (например, по фамилии владельца) и определенное количество денег в условных единицах (у. е.).
Для форматированного считывания данных из файла применим библиотечную функцию fscanf().
Программный код решения примера:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#define MAX 39 // Предполагаемое число символов в имени
#define file "D:\\data7.dat"
#define file2 "D:\\data77.dat"
int main(void)
{
int number, i = 1, j = 1; // номер ячейки
char name[MAX+1]; // имя ячейки (владельца)
long double sum; // сумма денег в у.е.
FILE *fid, *fid2;
if ( fopen_s(fid, file, "w") )
{fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
printf("\n Enter through blanks number of a cell,\n a name of the owner and the sum of money.\n \
Type Ctrl+Z to exit at the beginning of a new line: \n\n");
printf(" %3d) ", i);
scanf("%d%s%lf", number, name, sum);
// Запись в файл data7.dat
while ( !feof(stdin)) { // stdin - поток с клавиатуры
fprintf(fid, " %3d\t %-15s %7.2f\r\n", number, name, sum);
printf(" %3d) ", ++i);
scanf("%d%s%lf", number, name, sum);
}
fclose(fid);
if ( fopen_s(fid, file, "r") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
if ( fopen_s(fid2, file2, "w") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
// Вывод на консоль
printf("\n %s\t %s\t\t %5s", "The number of cell", "Name", "Sum");
// Чтение из файла data7.dat
fscanf(fid, "%d%s%Lf", number, name, sum);
fprintf(fid2, "\r\n %s\t\t %s\t\t %5s\r\n", "The number of cell", "Name", "Sum");
i = 1;
while ( !feof(fid)) { // пока не конец файла
// Вывод на консоль
printf("\n %3d\t\t\t %-17s %1.2f", number, name, sum);
// Запись в файл data77.dat
fprintf(fid2, " %3d) %3d\t\t\t %-17s %1.2f\r\n", i++, number, name, sum);
// Чтение из файла data7.dat
fscanf(fid, "%d%s%Lf", number, name, sum);
}
fclose(fid);
fclose(fid2);
printf("\n\n\n Result see the files, \"%s\" and \"%s\"\n", file, file2);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе использована функция feof(), которая проверяет, достигнут ли конец файла, связанного с потоком (указателем на файл) fid.
На рис 12.11 показан возможный результат выполнения программы.
(рис 12.11) Консольный вывод содержимого файлаСледует обратить внимание на прекращение ввода данных с клавиатуры с помощью комбинации клавиш Ctrl+Z.
Задание 7
while примените оператор цикла for.Пример 8. Напишите программу пакетной записи в файл произвольного доступа массива данных и вывода этого пакета на консоль.
Для решения примера применим функции fwrite() и для бинарной записи и считывания информации.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#define MAX 20
#define n 5
#define m 4
#define file "D:\\data8.txt"
int main(void) {
//Матрица 5х4
int mass[MAX][MAX] = {
{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}, {17,18,19,20} };
int mass2[MAX][MAX]; // Вспомогательная матрица
int i, j;
// Массив из 5 указателей
char *str[] = {
"Brian W. Kernighan",
"Dennis M. Ritchie",
"Stephen Prata",
"Herbert Shildt",
"The C Programming Language"
};
char *str2[n]; // Вспомогательный массив указателей
FILE *fid;
if ( fopen_s(fid, file, "wb") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Error! Press any key: ");
_getch(); return 0; }
fwrite(str, sizeof(char), sizeof(str)/sizeof(char), fid);
fwrite(mass, sizeof(int), sizeof(mass)/sizeof(int), fid);
fclose (fid);
if ( fopen_s(fid, file, "rb") ) {
fprintf(stdout, "\n\t File could not be opened\n");
printf("\n Press any key: ");
_getch(); return 0; }
fread(str2, sizeof(char), sizeof(str)/sizeof(char), fid);
fread(mass2, sizeof(int), sizeof(mass2)/sizeof(int), fid);
// Чтение элементов из файла
printf("\n\t From a file \"%s\": \n\n", file);
for (i = 0; i < n; ++i)
printf("\t %-15s\n", str2[i]);
printf("\n\t Matrix from a file \"%s\":\n", file);
for (i = 0; i < n; ++i) {
printf("\n\t");
for (j = 0; j < m; ++j)
printf(" %3d", mass2[i][j]);
}
fclose(fid);
printf("\n\n\n Press any key: ");
_getch();
return 0;
}
Функция fwrite() пересылает в файл заданное количество байт начиная с указанного адреса памяти. Данные записываются с того места в файле, которое обозначено указателем позиции файла. Функция пересылает заданное количество байт на места в файле, определенного указателем позиции файла, в массив в памяти, начинающийся с указанного адреса.
В программе пакетная запись информации – набора строк и матрицы целых чисел производится через двоичный поток с помощью функций fwrite(). Чтение информации из двоичного файла осуществляется функцией . Форматы записи обеих функций одинаковый, так как в них требуется определить количество объектов с заданным размером байт, которые определяются функцией sizeof().
Результат выполнения программы показан на рис 12.12 и на рис 12.13.

(рис 12.13) Результат чтения из файла бинарной информации(рис 12.12) Результат записи в текстовый файл бинарной информацииКак видно из рисунков, информация на консоли соответствует исходной информации, а в двоичном файле информация не подлежит непосредственному восприятию.
Примечание. Вид бинарной информации в текстовом файле зависит от установленных шрифтов.
Задание 8
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.