#9 — Работа с файлами через язык Си
За счёт языка Си вы можете с легкостью манипулировать файлами и помещать в них различную информацию и позже считывать её. За урок мы научимся работать с файлами через язык Си.
Видеоурок
Многие языки программирования предоставляют классы для работы с файлами и директориями проекта. Язык Си обладает множеством возможностей для записи и чтения данных из файлов.
Работа с файлами
При работе с файлами всегда необходимо помнить две вещи:
- Перед началом работы с файлом его необходимо открыть;
- После завершения работы с файлом его необходимо закрыть.
Если файл не открыт или же неверно открыт, то вы не можете полноценно работать с его содержимым.
С закрытием все проще, но и коварнее. Если вы не закроете файл, то программа будет работать верно, тем не менее, чем больше будет открытых файлов, тем больше программа будет перегружена и в какой-то момент она просто зависнет или выключиться.
Запись данных в файл
При записи данных в файл его изначально необходимо открыть. Для этого в языке Си используется функция fopen :
// Создание/открытие файла "examples.txt" // Можно было использовать метод fopen FILE *file = fopen("examples.txt", "w"); // Помещение данных fprintf(file, "Hello George"); // Закрываем файл fclose(file);
Таким образом мы можем открыть файл и поместить в него любую информацию.
Режим необходимо прописывать в качестве второго параметра при открытии файла:
Чтение данных из файла
Для чтения данных файл необходимо также изначально открыть и в конце закрыть. Чтобы прочесть содержимое файла используется функция fgets :
FILE *file = fopen("test.txt", "r"); fgets(line, 255, file); printf("%s", line); fclose(file);
Программа обучения
Также хотим отметить, что если вас интересует более углубленное изучение языка и его фреймворков, то предлагаем вашему внимаю наш полный курс по изучению C++ . За курс вы изучите язык C++, научитесь работать с библиотекой STL, базами данных, многопоточностью и научитесь строить приложения при помощи WinForms и QT.
Весь код будет доступен после подписки на проект!
Работа с файлами
Для удобства обращения информация в запоминающих устройствах хранится в виде файлов.
Файл – именованная область внешней памяти, выделенная для хранения массива данных. Данные, содержащиеся в файлах, имеют самый разнообразный характер: программы на алгоритмическом или машинном языке; исходные данные для работы программ или результаты выполнения программ; произвольные тексты; графические изображения и т. п.
Каталог ( папка , директория ) – именованная совокупность байтов на носителе информации, содержащая название подкаталогов и файлов, используется в файловой системе для упрощения организации файлов.
Файловой системой называется функциональная часть операционной системы, обеспечивающая выполнение операций над файлами. Примерами файловых систем являются FAT (FAT – File Allocation Table, таблица размещения файлов), NTFS, UDF (используется на компакт-дисках).
Существуют три основные версии FAT: FAT12, FAT16 и FAT32. Они отличаются разрядностью записей в дисковой структуре, т.е. количеством бит, отведённых для хранения номера кластера. FAT12 применяется в основном для дискет (до 4 кбайт), FAT16 – для дисков малого объёма, FAT32 – для FLASH-накопителей большой емкости (до 32 Гбайт).
Рассмотрим структуру файловой системы на примере FAT32.
Файловая структура FAT32
Устройства внешней памяти в системе FAT32 имеют не байтовую, а блочную адресацию. Запись информации в устройство внешней памяти осуществляется блоками или секторами.
Сектор – минимальная адресуемая единица хранения информации на внешних запоминающих устройствах. Как правило, размер сектора фиксирован и составляет 512 байт. Для увеличения адресного пространства устройств внешней памяти сектора объединяют в группы, называемые кластерами.
Кластер – объединение нескольких секторов, которое может рассматриваться как самостоятельная единица, обладающая определёнными свойствами. Основным свойством кластера является его размер, измеряемый в количестве секторов или количестве байт.

Файловая система FAT32 имеет следующую структуру.
Нумерация кластеров, используемых для записи файлов, ведется с 2. Как правило, кластер №2 используется корневым каталогом, а начиная с кластера №3 хранится массив данных. Сектора, используемые для хранения информации, представленной выше корневого каталога, в кластеры не объединяются.
Минимальный размер файла, занимаемый на диске, соответствует 1 кластеру.
Загрузочный сектор начинается следующей информацией:
- EB 58 90 – безусловный переход и сигнатура;
- 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
- 00 02 – количество байт в секторе (обычно 512);
- 1 байт – количество секторов в кластере;
- 2 байта – количество резервных секторов.
Кроме того, загрузочный сектор содержит следующую важную информацию:
- 0x10 (1 байт) – количество таблиц FAT (обычно 2);
- 0x20 (4 байта) – количество секторов на диске;
- 0x2С (4 байта) – номер кластера корневого каталога;
- 0x47 (11 байт) – метка тома;
- 0x1FE (2 байта) – сигнатура загрузочного сектора ( 55 AA ).
Сектор информации файловой системы содержит:
- 0x00 (4 байта) – сигнатура ( 52 52 61 41 );
- 0x1E4 (4 байта) – сигнатура ( 72 72 41 61 );
- 0x1E8 (4 байта) – количество свободных кластеров, -1 если не известно;
- 0x1EС (4 байта) – номер последнего записанного кластера;
- 0x1FE (2 байта) – сигнатура ( 55 AA ).
Таблица FAT содержит информацию о состоянии каждого кластера на диске. Младшие 2 байт таблицы FAT хранят F8 FF FF 0F FF FF FF FF (что соответствует состоянию кластеров 0 и 1, физически отсутствующих). Далее состояние каждого кластера содержит номер кластера, в котором продолжается текущий файл или следующую информацию:
- 00 00 00 00 – кластер свободен;
- FF FF FF 0F – конец текущего файла.
Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:
- 8 байт – имя файла;
- 3 байта – расширение файла;
Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:
- 8 байт – имя файла;
- 3 байта – расширение файла;
- 1 байт – атрибут файла:

- 1 байт – зарезервирован;
- 1 байт – время создания (миллисекунды) (число от 0 до 199);
- 2 байта – время создания (с точностью до 2с):

- 2 байта – дата создания:

- 2 байта – дата последнего доступа;
- 2 байта – старшие 2 байта начального кластера;
- 2 байта – время последней модификации;
- 2 байта – дата последней модификации;
- 2 байта – младшие 2 байта начального кластера;
- 4 байта – размер файла (в байтах).
В случае работы с длинными именами файлов (включая русские имена) кодировка имени файла производится в системе кодировки UTF-16. При этого для кодирования каждого символа отводится 2 байта. При этом имя файла записывается в виде следующей структуры:
- 1 байт последовательности;
- 10 байт содержат младшие 5 символов имени файла;
- 1 байт атрибут;
- 1 байт резервный;
- 1 байт – контрольная сумма имени DOS;
- 12 байт содержат младшие 3 символа имени файла;
- 2 байта – номер первого кластера;
- остальные символы длинного имени.
Далее следует запись, включающая имя файла в формате 8.3 в обычном формате.
Работа с файлами в языке Си
Для программиста открытый файл представляется как последовательность считываемых или записываемых данных. При открытии файла с ним связывается поток ввода-вывода . Выводимая информация записывается в поток, вводимая информация считывается из потока.
Когда поток открывается для ввода-вывода, он связывается со стандартной структурой типа FILE , которая определена в stdio.h . Структура FILE содержит необходимую информацию о файле.
Открытие файла осуществляется с помощью функции fopen() , которая возвращает указатель на структуру типа FILE , который можно использовать для последующих операций с файлом.
FILE *fopen(name, type);
name – имя открываемого файла (включая путь),
type — указатель на строку символов, определяющих способ доступа к файлу:
- «r» — открыть файл для чтения (файл должен существовать);
- «w» — открыть пустой файл для записи; если файл существует, то его содержимое теряется;
- «a» — открыть файл для записи в конец (для добавления); файл создается, если он не существует;
- «r+» — открыть файл для чтения и записи (файл должен существовать);
- «w+» — открыть пустой файл для чтения и записи; если файл существует, то его содержимое теряется;
- «a+» — открыть файл для чтения и дополнения, если файл не существует, то он создаётся.
Возвращаемое значение — указатель на открытый поток. Если обнаружена ошибка, то возвращается значение NULL .
Функция fclose() закрывает поток или потоки, связанные с открытыми при помощи функции fopen() файлами. Закрываемый поток определяется аргументом функции fclose() .
Возвращаемое значение: значение 0, если поток успешно закрыт; константа EOF , если произошла ошибка.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include
int main() FILE *fp;
char name[] = «my.txt» ;
if ((fp = fopen(name, «r» )) == NULL )
printf( «Не удалось открыть файл» );
getchar();
return 0;
>
// открыть файл удалось
. // требуемые действия над данными
fclose(fp);
getchar();
return 0;
>
Чтение символа из файла:
char fgetc(поток);
Аргументом функции является указатель на поток типа FILE . Функция возвращает код считанного символа. Если достигнут конец файла или возникла ошибка, возвращается константа EOF .
Запись символа в файл:
fputc(символ,поток);
Аргументами функции являются символ и указатель на поток типа FILE . Функция возвращает код считанного символа.
Функции fscanf() и fprintf() аналогичны функциям scanf() и printf() , но работают с файлами данных, и имеют первый аргумент — указатель на файл.
fscanf(поток, «ФорматВвода» , аргументы);
fprintf(поток, «ФорматВывода» , аргументы);
Функции fgets() и fputs() предназначены для ввода-вывода строк, они являются аналогами функций gets() и puts() для работы с файлами.
fgets(УказательНаСтроку, КоличествоСимволов, поток);
Символы читаются из потока до тех пор, пока не будет прочитан символ новой строки ‘\n’ , который включается в строку, или пока не наступит конец потока EOF или не будет прочитано максимальное количество символов. Результат помещается в указатель на строку и заканчивается нуль- символом ‘\0’ . Функция возвращает адрес строки.
fputs(УказательНаСтроку,поток);
Копирует строку в поток с текущей позиции. Завершающий нуль- символ не копируется.
Пример Ввести число и сохранить его в файле s1.txt. Считать число из файла s1.txt, увеличить его на 3 и сохранить в файле s2.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include
#include
int main()
FILE *S1, *S2;
int x, y;
system( «chcp 1251» );
system( «cls» );
printf( «Введите число : » );
scanf( «%d» , &x);
S1 = fopen( «S1.txt», «w» );
fprintf(S1, «%d» , x);
fclose(S1);
S1 = fopen( «S1.txt», «r» );
S2 = fopen( «S2.txt», «w» );
fscanf(S1, «%d» , &y);
y += 3;
fclose(S1);
fprintf(S2, «%d\n» , y);
fclose(S2);
return 0;
>

Результат выполнения — 2 файла
Работа с файлами в C++ описана здесь.
Работа с файлами в СИ
Файл – это именованная область данных на каком-либо носителе информации. Типы файлов (относительно языка «СИ»):
текстовые;
бинарные.
Основные операции производимые над файлами:
Открытие файлов.
Чтение и запись данных.
Закрытие файлов.
Дополнительные операции:
Навигация по файлу.
Обработка ошибок работы с файлами.
Удаление и переименование файлов.
Описание переменной
Библиотека stdio.h
FILE *имя = NULL;
Открытие файла
FILE *fopen(const char *filename, const char *mode);
filename – название файла.
mode – режим открытия.
Функция возвращает указатель на файл, если тот был успешно открыт. В противном случае – NULL. Только имя, если файл находится в текущем каталоге. Иначе необходимо указать абсолютный или относительный путь к файлу.
Примеры:
«data.txt”
«..\\files\\data.txt»
«d:\\temp\\data.txt»
Режимы открытия файлов с СИ
| r | только чтение |
| w | Только запись. Если файл существовал, то он переписывается. |
| a | Добавление: открытие файла для записи в конец, или создание файла. |
| r+ | Открывает файл для обновления (чтение и запись). |
| w+ | Открывает файл для обновления (чтение и запись), переписывая файл, если он существует. |
| a+ | Открывает файл для записи в конец файла или для чтения. |
Перенаправление потоков
FILE * freopen(const char *filename, const char *mode, FILE *stream);
Функция возвращает:
Указатель на файл – все нормально,
NULL – ошибка переопределения.
Закрытие файла
int fclose(FILE *stream);
stream — указатель на открытый файл.
Функция возвращает:
0 – файл успешно закрыт.
1 – произошла ошибка закрытия файла.
Проверка на достижение конца файла
int feof(FILE *stream);
stream — указатель на открытый файл.
Функция возвращает:
0 – если конец файла еще не достигнут.
!0 – достигнут конец файла.
Открытие текстовых файлов
Во втором параметре дополнительно указывается символ t (необязательно):
rt, wt, at, rt+, wt+, at+
Чтение из текстового файла
Форматированное чтение
int fscanf(FILE *stream, const char * format, [arg] . );
Функция возвращает:
buffer – все нормально,
NULL – ошибка или достигнут конец файла.
Чтение строки
char * fgets(char * buffer, int maxlen, FILE *stream);
Функция возвращает:
buffer – все нормально,
NULL – ошибка или достигнут конец файла.
Чтение символа
int fgetc(FILE *stream);
Функция возвращает:
код символа – если все нормально,
EOF – если ошибка или достигнут конец файла.
Помещение символа обратно в поток
int ungetc(int c, FILE *stream);
Функция возвращает:
код символа – если все успешно,
EOF – произошла ошибка.
Запись в текстовый файл в СИ
Форматированный вывод
int fprintf(FILE *stream, const char *format, [arg] . );
Функция возвращает:
число записанных символов – если все нормально,
отрицательное значение – если ошибка.
Запись строки
int fputs(const char *string, FILE *stream);
Функция возвращает:
число записанных символов – все нормально,
EOF – произошла ошибка.
Запись символа
int fputc(int c, FILE *stream);
Функция возвращает:
код записанного символа – все нормально,
EOF – произошла ошибка.
Открытие бинарных файлов
Во втором параметре дополнительно указывается символ b (обязательно):rb, wb, ab, rb+, wb+, ab+
Чтение из бинарных файлов
size_t fread(void *buffer, size_t size, size_t num,FILE *stream);
Функция возвращает количество прочитанных блоков. Если оно меньше num, то произошла ошибка или достигнут
конец файла.
Запись в бинарный файл
size_t fwrite(const void *buffer, size_t size, size_t num, FILE *stream);
Функция возвращает количество записанных блоков. Если оно меньше num, то произошла ошибка.
Навигация по файлу
Чтение текущего смещения в файле:
long int ftell(FILE *stream);
Изменение текущего смещения в файле:
int fseek(FILE *stream, long int offset, int origin);
SEEK_SET (0) – от начала файла.
SEEK_CUR (1) – от текущей позиции.
SEEK_END (2) – от конца файла.
Функция возвращает:
0 – все нормально,
!0 – произошла ошибка.
Перемещение к началу файла:
void rewind(FILE *stream);
Чтение текущей позиции в файле:
int fgetpos(FILE *stream, fpos_t *pos);
Установка текущей позиции в файле:
int fsetpos(FILE *stream, const fpos_t *pos);
Функции возвращают:
0 – все успешно,
!0 – произошла ошибка.
Структура fpos_t:
typedef struct fpos_t long off;
mbstate_t wstate;
> fpos_t;
Получение признака ошибки:
int ferror(FILE *stream);
Функция возвращает ненулевое значение, если возникла ошибка.
Функция сброса ошибки:
void clearerr(FILE *stream);
Функция вывода сообщения об ошибке:
void perror(const char *string);
Буферизация
Функция очистки буфера:
int fflush(FILE *stream);
Функция возвращает:
0 – все нормально.
EOF – произошла ошибка.
Функция управления буфером:
void setbuf(FILE *stream, char * buffer);
Создает буфер размером BUFSIZ. Используется до ввода или вывода в поток.
Временные файлы
Функция создания временного файла:
FILE * tmpfile(void);
Создает временный файл в режиме wb+. После закрытия файла, последний автоматически удаляется.
Функция генерации имени временного файла:
char * tmpnam(char *buffer);
Удаление и переименование
Функция удаления файла:
int remove(const char *filename);
Функция переименования файла:
int rename(const char *fname, const char *nname);
Функции возвращают:
0 – в случае успеха,
!0 – в противном случае.
Работа с файлами в С++
Большинство компьютерных программ работают с файлами, и поэтому возникает необходимость создавать, удалять, записывать читать, открывать файлы. Что же такое файл? Файл – именованный набор байтов, который может быть сохранен на некотором накопителе. Ну, теперь ясно, что под файлом понимается некоторая последовательность байтов, которая имеет своё, уникальное имя, например файл.txt . В одной директории не могут находиться файлы с одинаковыми именами. Под именем файла понимается не только его название, но и расширение, например: file.txt и file.dat — разные файлы, хоть и имеют одинаковые названия. Существует такое понятие, как полное имя файлов – это полный адрес к директории файла с указанием имени файла, например: D:\docs\file.txt . Важно понимать эти базовые понятия, иначе сложно будет работать с файлами.
Для работы с файлами необходимо подключить заголовочный файл . В определены несколько классов и подключены заголовочные файлы — файловый ввод и — файловый вывод.
Файловый ввод/вывод аналогичен стандартному вводу/выводу, единственное отличие – это то, что ввод/вывод выполнятся не на экран, а в файл. Если ввод/вывод на стандартные устройства выполняется с помощью объектов cin и cout , то для организации файлового ввода/вывода достаточно создать собственные объекты, которые можно использовать аналогично операторам cin и cout .
Например, необходимо создать текстовый файл и записать в него строку Работа с файлами в С++ . Для этого необходимо проделать следующие шаги:
- создать объект класса ofstream ;
- связать объект класса с файлом, в который будет производиться запись;
- записать строку в файл;
- закрыть файл.
Почему необходимо создавать объект класса ofstream , а не класса ifstream ? Потому, что нужно сделать запись в файл, а если бы нужно было считать данные из файла, то создавался бы объект класса ifstream .
// создаём объект для записи в файл ofstream /*имя объекта*/; // объект класса ofstream
Назовём объект – fout , Вот что получится:
ofstream fout;
Для чего нам объект? Объект необходим, чтобы можно было выполнять запись в файл. Уже объект создан, но не связан с файлом, в который нужно записать строку.
fout.open("cppstudio.txt"); // связываем объект с файлом
Через операцию точка получаем доступ к методу класса open(), в круглых скобочках которого указываем имя файла. Указанный файл будет создан в текущей директории с программой. Если файл с таким именем существует, то существующий файл будет заменен новым. Итак, файл открыт, осталось записать в него нужную строку. Делается это так:
foutИспользуя операцию передачи в поток совместно с объектом fout строка Работа с файлами в С++ записывается в файл. Так как больше нет необходимости изменять содержимое файла, его нужно закрыть, то есть отделить объект от файла.
fout.close(); // закрываем файлИтог – создан файл со строкой Работа с файлами в С++ .
Шаги 1 и 2 можно объединить, то есть в одной строке создать объект и связать его с файлом. Делается это так:
ofstream fout("cppstudio.txt"); // создаём объект класса ofstream и связываем его с файлом cppstudio.txtОбъединим весь код и получим следующую программу.
// file.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include using namespace std; int main(int argc, char* argv[]) < ofstream fout("cppstudio.txt"); // создаём объект класса ofstream для записи и связываем его с файлом cppstudio.txt foutОсталось проверить правильность работы программы, а для этого открываем файл cppstudio.txt и смотрим его содержимое, должно быть — Работа с файлами в С++ .
Для того чтобы прочитать файл понадобится выполнить те же шаги, что и при записи в файл с небольшими изменениями:
- создать объект класса ifstream и связать его с файлом, из которого будет производиться считывание;
- прочитать файл;
- закрыть файл.
// file_read.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, "rus"); // корректное отображение Кириллицы char buff[50]; // буфер промежуточного хранения считываемого из файла текста ifstream fin("cppstudio.txt"); // открыли файл для чтения fin >> buff; // считали первое слово из файла coutВ программе показаны два способа чтения из файла, первый – используя операцию передачи в поток, второй – используя функцию getline() . В первом случае считывается только первое слово, а во втором случае считывается строка, длинной 50 символов. Но так как в файле осталось меньше 50 символов, то считываются символы включительно до последнего. Обратите внимание на то, что считывание во второй раз ( строка 17 ) продолжилось, после первого слова, а не с начала, так как первое слово было прочитано в строке 14 . Результат работы программы показан на рисунке 1.
CppStudio.com
Работа с файлами в С++ Для продолжения нажмите любую клавишу . . .Рисунок 1 — Работа с файлами в С++
Программа сработала правильно, но не всегда так бывает, даже в том случае, если с кодом всё впорядке. Например, в программу передано имя несуществующего файла или в имени допущена ошибка. Что тогда? В этом случае ничего не произойдёт вообще. Файл не будет найден, а значит и прочитать его не возможно. Поэтому компилятор проигнорирует строки, где выполняется работа с файлом. В результате корректно завершится работа программы, но ничего, на экране показано не будет. Казалось бы это вполне нормальная реакции на такую ситуацию. Но простому пользователю не будет понятно, в чём дело и почему на экране не появилась строка из файла. Так вот, чтобы всё было предельно понятно в С++ предусмотрена такая функция — is_open() , которая возвращает целые значения: 1 — если файл был успешно открыт, 0 — если файл открыт не был. Доработаем программу с открытием файла, таким образом, что если файл не открыт выводилось соответствующее сообщение.
// file_read.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, "rus"); // корректное отображение Кириллицы char buff[50]; // буфер промежуточного хранения считываемого из файла текста ifstream fin("cppstudio.doc"); // (ВВЕЛИ НЕ КОРРЕКТНОЕ ИМЯ ФАЙЛА) if (!fin.is_open()) // если файл не открыт cout > buff; // считали первое слово из файла cout system("pause"); return 0; >Результат работы программы показан на рисунке 2.
CppStudio.com
Файл не может быть открыт! Для продолжения нажмите любую клавишу . . .Рисунок 2 — Работа с файлами в С++
Как видно из рисунка 2 программа сообщила о невозможности открыть файл. Поэтому, если программа работает с файлами, рекомендуется использовать эту функцию, is_open() , даже, если уверены, что файл существует.
Режимы открытия файлов
Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе ios_base предусмотрены константы, которые определяют режим открытия файлов (см. Таблица 1).
| Константа | Описание |
|---|---|
| ios_base::in | открыть файл для чтения |
| ios_base::out | открыть файл для записи |
| ios_base::ate | при открытии переместить указатель в конец файла |
| ios_base::app | открыть файл для записи в конец файла |
| ios_base::trunc | удалить содержимое файла, если он существует |
| ios_base::binary | открытие файла в двоичном режиме |
Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове функции open() .
ofstream fout("cppstudio.txt", ios_base::app); // открываем файл для добавления информации к концу файла fout.open("cppstudio.txt", ios_base::app); // открываем файл для добавления информации к концу файла
Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции или | , например: ios_base::out | ios_base::trunc — открытие файла для записи, предварительно очистив его.
Объекты класса ofstream , при связке с файлами по умолчанию содержат режимы открытия файлов ios_base::out | ios_base::trunc . То есть файл будет создан, если не существует. Если же файл существует, то его содержимое будет удалено, а сам файл будет готов к записи. Объекты класса ifstream связываясь с файлом, имеют по умолчанию режим открытия файла ios_base::in — файл открыт только для чтения. Режим открытия файла ещё называют — флаг, для удобочитаемости в дальнейшем будем использовать именно этот термин. В таблице 1 перечислены далеко не все флаги, но для начала этих должно хватить.
Обратите внимание на то, что флаги ate и app по описанию очень похожи, они оба перемещают указатель в конец файла, но флаг app позволяет производить запись, только в конец файла, а флаг ate просто переставляет флаг в конец файла и не ограничивает места записи.
Разработаем программу, которая, используя операцию sizeof() , будет вычислять характеристики основных типов данных в С++ и записывать их в файл. Характеристики:
- число байт, отводимое под тип данных
- максимальное значение, которое может хранить определённый тип данных.
Запись в файл должна выполняться в таком формате:
/* data type byte max value bool = 1 255.00 char = 1 255.00 short int = 2 32767.00 unsigned short int = 2 65535.00 int = 4 2147483647.00 unsigned int = 4 4294967295.00 long int = 4 2147483647.00 unsigned long int = 4 4294967295.00 float = 4 2147483647.00 long float = 8 9223372036854775800.00 double = 8 9223372036854775800.00 */
Такая программа уже разрабатывалась ранее в разделе Типы данных С++ , но там вся информация о типах данных выводилась на стандартное устройство вывода, а нам необходимо программу переделать так, чтобы информация записывалась в файл. Для этого необходимо открыть файл в режиме записи, с предварительным усечением текущей информации файла (строка 14). Как только файл создан и успешно открыт (строки 16 — 20), вместо оператора cout , в строке 22 используем объект fout . таким образом, вместо экрана информация о типах данных запишется в файл.
// write_file.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include // работа с файлами #include // манипуляторы ввода/вывода using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, "rus"); // связываем объект с файлом, при этом файл открываем в режиме записи, предварительно удаляя все данные из него ofstream fout("data_types.txt", ios_base::out | ios_base::trunc); if (!fout.is_open()) // если файл небыл открыт < cout fout << " data type " << "byte" << " " << " max value " << endl // заголовки столбцов << "bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout
Нельзя не заметить, что изменения в программе минимальны, а всё благодаря тому, что стандартный ввод/вывод и файловый ввод/вывод используются абсолютно аналогично. В конце программы, в строке 45 мы явно закрыли файл, хотя это и не обязательно, но считается хорошим тоном программирования. Стоит отметить, что все функции и манипуляторы используемые для форматирования стандартного ввода/вывода актуальны и для файлового ввода/вывода. Поэтому не возникло никаких ошибок, когда оператор cout был заменён объектом fout .