bmstu_iu6_Cpp1 (823967), страница 18
Текст из файла (страница 18)
При достижении конца файлафункция возвращает 0, а при обнаружении ошибок – -1.Функция вывода в двоичный файл:size_t fwrite(void *ptr,size_t size,size_t n,FILE *stream);Функция выводит информацию из буфера по адресу ptr объемом size*n.Указанные функции в основном используются в двух вариантах:а) при работе со структурами:fread(&myrec,sizeof(myrec),1,f1);fwrite (&myrec,sizeof(myrec),1,f1);где myrec – переменная типа структура;б) при работе с файлом в целом, когда обрабатываемая информация не детализируется, например, при копировании файла:size_t bufSize=0x200;char *buffer = new char[bufSize];fread (buffer,1,bufSize,f2);fwrite(buffer,1,bufSize,f2);...delete[] buffer;Оглавление120Размер буфера при этом, как правило, задается кратным 512 байт.Пример 5.6.
Программа создания файла, содержащего ассортимент игрушек в магазине с указанием цены.#include <locale.h>#include <stdio.h>#include <conio.h>#include <string.h>#include <stdlib.h>struct toys{char name[20];float cost;} toy;int main(int argc,char *argv[ ]){setlocale(0,"russian");FILE *f;char s_cost[20];f=fopen("test.dat","w+b");if(f){while(puts("Введите название и стоимость:"),strcmp(gets(toy.name),"end")!=0){toy.cost=atof(gets(s_cost));fwrite(&toy,sizeof(toy),1,f);}fclose(f);}puts("Нажмите любую клавишу для завершения...");_getch();return 0;}Результаты работы программы (вводимые данные выделены полужирным):Введите название и стоимость:Кукла307,67Оглавление121Введите название и стоимость:Зайка476,89Введите название и стоимость:endНажмите любую клавишу для завершения...Пример 5.7.
Чтение двоичного файла (компонент - структура).#include <locale.h>#include <stdio.h>#include <conio.h>struct toys{char name[20];float cost;} toy;int main(int argc,char *argv[ ]){setlocale(0,"russian");FILE *f;f=fopen("test.dat","r+b");while(fread(&toy,sizeof(toy),1,f)>0)printf("Игрушка %s - цена %f\n",toy.name,toy.cost);fclose(f);puts("Нажмите любую клавишу для завершения...");_getch();return 0;}Пример 5.8. Программе создания текстового файл, который затем читается какдвоичный, состоящий из компонентов размером байт.#include <locale.h>#include <stdio.h>#include <conio.h>int main(int argc,char *argv[ ]){setlocale(0,"russian");char c;FILE *f;Оглавление122f=fopen("ddd.dat","w"); // открытие файла как текстовогоfputs("ABCDEF\n",f);// запись строки в текстовый файлfclose(f);// закрытие текстового файлаf=fopen("ddd.dat","rb"); // открытие файла как двоичногоwhile (fread(&c,1,1,f)!=0) printf("%x ",c); // побайтное чтениеprintf("\n");fclose(f);puts("Нажмите любую клавишу для завершения...");_getch(); return 0;}Результаты программа выводит в шестнадцатеричной системе счисления:41 42 43 44 45 46 d aНажмите любую клавишу для завершения...Последние две буквы – шестнадцатеричный маркер конца строки (13, 10).5.6 Удаление и переименование файловДля удаления файлов можно использовать одну из двух функций, названия которыхявляются синонимами:int unlink(const char *filename); // функция удаляет указанный файл;int remove(const char *filename); // функция удаляет указанный файл.Переименование файлов осуществляется с помощью функции:int remove(const char *oldname, const char *newname); .Пример 5.9.
Вставка фрагмента в середину текстового файла. Для осуществлениявставки программа использует копирование в другой файл, который после удаления исходного файла получает его имя.#include <locale.h>#include <stdio.h>#include <conio.h>int main(int argc,char *argv[]){setlocale(0,"russian");int n,m;FILE *f,*g;f=fopen("rand.dat","r");// открытие исходного файлаg=fopen("$$$$xxx.tmp","w"); // открытие рабочего файлаОглавление123// цикл копирования начала файлаfor (n=0;n<5;n++) {fscanf(f,"%d",&m);fprintf(g,"%d\n",m);}for (n=0;n<4;n++) fprintf(g,"%d\n",n); // вставка фрагментаwhile ((n=fgetc(f))!=EOF) fputc(n,g);// копирование остаткаfcloseall();// закрытие обоих файловunlink("rand.dat");// удаление исходного файлаrename("$$$$xxx.tmp","rand.dat");// переименование файлаputs("Нажмите любую клавишу для завершения...");_getch();return 0;}Контрольные вопросы к главе 51.
Что такое файл, и какие типы файлов вы знаете?Ответ.2. Что такое файловая переменная и как ее объявит в программе на С++?Ответ.3. Как открыть файл на чтение или запись с контролем наличия файла на диске?Приведите пример.Ответ.4. Что такое файловый указатель? Каково его назначение?Ответ.5. Какие Вы знаете функции работы с файловым указателем?Ответ.6.
Что такое стандартные текстовые файлы? Где они используются?Ответ.7. Каковы особенности работы с текстовыми файлами?Ответ.8. Что такое форматный ввод-вывод? Приведите основные функции работы с ним?Ответ.9. Что такое двоичные файлы и чем они отличаются от текстовых?Ответ.10. Какие Вы знаете функции работы с двоичными файлами?Ответ.Оглавление1246ПРЕПРОЦЕССОР ЯЗЫКА СПрепроцессор используется для обработки текста программы до ее компиляции и вызывается автоматически при обращении к компилятору. Обработка заключается в выполнении специальных команд. Рассмотрим наиболее часто используемые команды препроцессора.6.1 Команда #includeКоманда #include используется для включения в исходный текст программыфайлов, содержащих прототипы стандартных функций и части исходных текстов программы.
Данное средство языка позволяет хранить в отдельных файлах описания констант, типов и функций и затем использовать их в разных программах.Команда встречается в двух вариантах:#include <Имя файла> – в этом случае файл ищется в каталогах среды – этаформа используется при подключении стандартных файлов Си и С++;#include ″Имя файла″ – в этом случае файл сначала ищется в текущем каталогепроекта, а потом уже в каталогах среды – такая форма используется при подключениифайлов конкретного проекта.6.2 Команды #define и #undefКоманда #define используется для описания макроопределений – текстовых строк,вставляемых препроцессором вместо указанных имен (макрокоманд). Вставляемые фрагменты можно настраивать с использованием специально задаваемых параметров. Компиляция строк, как уже упоминалось ранее, выполняется после настройки и подстановкифрагментов.Команда записывается в следующем виде:#define <Идентификатор>[(<Список параметров>)] <Строка>где <Идентификатор> – имя, используемое для идентификации строки (макрокоманда);<Список параметров> – список идентификаторов, обозначающих заменяемые элементы строки – может отсутствовать;<Строка> – строка-макроопределение, заменяющая имя в тексте программы.Примеры:Оглавление125а) #define nil 0 // определяет замену идентификатора nil нулемб) #define N 5// определяет замену идентификатора N числом 5int main(){int A[N][N];⇒A[5][5]…в) #define MSG ″Это строка - пример″ // определяет замену// идентификатора MSG заданной строкойг) #define P(X) printf(″X равен %d.\n″,X) // определяет замену// идентификатора с параметром X на строку вывода данного параметра,// например, вместо P(alf) будет вставлено printf(″alf равно %d.\n″,alf)Следует осторожнее использовать форму с параметрами, так как в отличии от inlineфункций, препроцессор осуществляет формальную подстановку параметров как символьных строк без проверки типов.
Например, рассмотрим два варианта определения функциипоиска максимального значения:а) inline int MAX(int X, int Y){return X>Y?X:Y;}б) #define MAX(X,Y) (X>Y?X:Y)Вариант а не способен работать с типами, отличными от int, в то время как вариант бможет принимать аргументы любых типов.Примечание. Следует заметить, что подобное использование Си-команды #define дляC++ не рекомендуется, поскольку С++ имеет другие механизмы, например шаблоны (template), позволяющие выполнять контроль типов:template <typename T> T MAX(T x, T y){ return x>y?x:y;}Вызов функции при использовании шаблона можно осуществлять либо с неявнымуказанием типа, например MAX(1,4), либо если аргументы имеют разный тип, с явнымуказанием типа MAX<float>(1.03, 4).Формальные подстановки, выполняемые посредством #define, могут привести кнеожиданным ошибкам, например:#define ABS(X) (X>0?X:-X)void main(){int i,j; … i= ABS(j++); // Ошибка! j++ будет выполнено дважды}Оглавление126Если подстрока в команде #define не указана, то она получает значение «пусто» ипри обработке описанное таким образом имя макроса из текста удаляется.