Как открыть файл в бинарном виде в си

Обновлено: 05.07.2024

 Файл – это именованная область данных на каком-либо носителе информации. Типы файлов (относительно языка «СИ»):
  текстовые;
  бинарные.

 Основные операции производимые над файлами:
  Открытие файлов.
  Чтение и запись данных.
  Закрытие файлов.
 Дополнительные операции:
  Навигация по файлу.
  Обработка ошибок работы с файлами.
  Удаление и переименование файлов.
  Описание переменной

  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] . );

Функция возвращает:
 >0 – число успешно прочитанных переменных,
 0 – ни одна из переменных не была успешно прочитана,
 EOF – ошибка или достигнут конец файла.
Чтение строки
 char * fgets(char * buffer, int maxlen, FILE *stream);

Функция возвращает:
 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 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 – в противном случае.

БлогNot. Лекции по C/C++: работа с файлами (fstream)

Лекции по C/C++: работа с файлами (fstream)

Механизм ввода-вывода, разработанный для обычного языка С, не соответствует общепринятому сегодня стилю объектно-ориентированного программирования, кроме того, он активно использует операции с указателями, считающиеся потенциально небезопасными в современных защищённых средах выполнения кода. Альтернативой при разработке прикладных приложений является механизм стандартных классов ввода-вывода, предоставляемый стандартом языка C++.

Открытие файлов

Наиболее часто применяются классы ifstream для чтения, ofstream для записи и fstream для модификации файлов.

Все поточные классы ввода-вывода являются косвенными производными от общего предка ios , полностью наследуя его функциональность. Так, режим открытия файлов задает член данных перечисляемого типа open_mode, который определяется следующим образом:

Ниже приведены возможные значения флагов и их назначение.

Режим Назначение
in Открыть для ввода (выбирается по умолчанию для ifstream)
out Открыть для вывода (выбирается по умолчанию для ofstream)
binary Открыть файл в бинарном виде
aрр Присоединять данные; запись в конец файла
ate Установить файловый указатель на конец файла
trunc Уничтожить содержимое, если файл существует (выбирается по умолчанию, если флаг out указан, а флаги ate и арр — нет)

Например, чтобы открыть файл с именем test.txt для чтения данных в бинарном виде, следует написать:

Оператор логического ИЛИ ( | ) позволяет составить режим с любым сочетанием флагов. Так, чтобы, открывая файл по записи, случайно не затереть существующий файл с тем же именем, надо использовать следующую форму:

Предполагается, что к проекту подключён соответствующий заголовочный файл:

Для проверки того удалось ли открыть файл, можно применять конструкцию

Операторы включения и извлечения

Переопределённый в классах работы с файлами оператор включения ( << ) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

Можно также записывать текстовую строку по частям:

Оператор endl завершает ввод строки символом "возврат каретки":

С помощью оператора включения несложно записывать в файл значения переменных или элементов массива:

В результате выполнения кода образуется три строки текстового файла Temp.txt :

Обратите внимание, что числовые значения записываются в файл в виде текстовых строк, а не двоичных значений.

Оператор извлечения ( >> )производит обратные действия. Казалось бы, чтобы извлечь символы из файла Temp.txt , записанного ранее, нужно написать код наподобие следующего:

Однако оператор извлечения остановится на первом попавшемся разделителе (символе пробела, табуляции или новой строки). Таким образом, при разборе предложения "Текстовый массив содержит переменные" только слово "Текстовый" запишется в массив buff , пробел игнорируется, а слово "массив" станет значением целой переменной vx и исполнение кода "пойдет вразнос" с неминуемым нарушением структуры данных. Далее, при обсуждении класса ifstream , будет показано, как правильно организовать чтение файла из предыдущего примера.

Класс ifstream: чтение файлов

Как следует из расшифровки названия, класс ifstream предназначен для ввода файлового потока. Далее перечислены основные методы класса. Большая часть из них унаследована от класса istream и перегружена с расширением родительской функциональности. К примеру, функция get , в зависимости от параметра вызова, способна считывать не только одиночный символ, но и символьный блок.

Метод Описание
open Открывает файл для чтения
get Читает один или более символов из файла
getline Читает символьную строку из текстового файла или данные из бинарного файла до определенного ограничителя
read Считывает заданное число байт из файла в память
eof Возвращает ненулевое значение (true), когда указатель потока достигает конца файла
peek Выдает очередной символ потока, но не выбирает его
seekg Перемещает указатель позиционирования файла в заданное положение
tellg Возвращает текущее значение указателя позиционирования файла
close Закрывает файл

Теперь понятно, как нужно модифицировать предыдущий пример, чтобы использование оператора извлечения данных давало ожидаемый результат:

Метод getline прочитает первую строку файла до конца, а оператор >> присвоит значения переменным.

Следующий пример показывает добавление данных в текстовый файл с последующим чтением всего файла. Цикл while (1) используется вместо while(!file2.eof()) по причинам, которые обсуждались в предыдущей лекции.

Этот код под ОС Windows также зависит от наличия в последней строке файла символа перевода строки, надежнее было бы сделать так:

Явные вызовы методов open и close не обязательны. Действительно, вызов конструктора с аргументом позволяет сразу же, в момент создания поточного объекта file , открыть файл:

Вместо метода close можно использовать оператор delete , который автоматически вызовет деструктор объекта file и закроет файл. Код цикла while обеспечивает надлежащую проверку признака конца файла.

Класс ofstream: запись файлов

Класс ofstream предназначен для вывода данных из файлового потока. Далее перечислены основные методы данного класса.

Метод Описание
open Открывает файл для записи
put Записывает одиночный символ в файл
write Записывает заданное число байт из памяти в файл
seekp Перемещает указатель позиционирования в указанное положение
tellp Возвращает текущее значение указателя позиционирования файла
close Закрывает файл

Описанный ранее оператор включения удобен для организации записи в текстовый файл:

Бинарные файлы

В принципе, бинарные данные обслуживаются наподобие текстовых. Отличие состоит в том, что если бинарные данные записываются в определенной логической структуре, то они должны считываться из файла в переменную того же структурного типа.

Первый параметр методов write и read (адрес блока записи/чтения) должен иметь тип символьного указателя char * , поэтому необходимо произвести явное преобразование типа адреса структуры void * . Второй параметр указывает, что бинарные блоки файла имеют постоянный размер байтов независимо от фактической длины записи. Следующее приложение дает пример создания и отображения данных простейшей записной книжки. Затем записи файла последовательно считываются и отображаются на консоли.

P.S. При выполнении этого и других листингов в Visual Studio последних версий может дополнительно понадобиться подключение директивы _CRT_SECURE_NO_WARNINGS.

В результате выполнения этого кода образуется бинарный файл Notebook.dat из трех блоков размером по 80 байт каждый (при условии, что символы - однобайтовые). Естественно, вы можете использовать другие поточные методы и проделывать любые операции над полями определенной структуры данных.

Класс fstream: произвольный доступ к файлу

Предположим что в нашей записной книжке накопилось 100 записей, а мы хотим считать 50-ю. Конечно, можно организовать цикл и прочитать все записи с первой по заданную. Очевидно, что более целенаправленное решение - установить указатель позиционирования файла pos прямо на запись 50 и считать ее:

Подобные операции поиска эффективны, если файл состоит из записей известного и постоянного размера. Чтобы заменить содержимое произвольной записи, надо открыть поток вывода в режиме модификации:

Если не указать флаг ios::ate (или ios::app ), то при открытии бинарного файла Notebook.dat его предыдущее содержимое будет стерто!

Дополнительно может понадобиться указать, откуда отсчитывается смещение.

Наконец, можно открыть файл одновременно для чтения/записи, используя методы, унаследованные поточным классом fstream от своих предшественников. Поскольку класс fstream произведен от istream и ostream (родителей ifstream и ofstream соответственно), все упомянутые ранее методы становятся доступными в приложении.

Стандартная библиотека Си содержит набор функций для работы с файлами. Эти функции описаны в стандарте ANSI . Отметим, что файловый ввод-вывод не является частью языка Си , и ANSI -функции - не единственное средство ввода-вывода. Так, в операционной системе Unix более популярен другой набор функций ввода-вывода, который можно использовать не только для работы с файлами, но и для обмена по сети. В C++ часто используются библиотеки классов для ввода-вывода. Тем не менее, функции ANSI -библиотеки поддерживаются всеми Си -компиляторами, и потому программы, применяющие их, легко переносятся с одной платформы на другую. Прототипы функций ввода-вывода и используемые для этого типы данных описаны в стандартном заголовочном файле "stdio.h.

Открытие файла: функция fopen

Для доступа к файлу применяется тип данных FILE . Это структурный тип, имя которого задано с помощью оператора typedef в стандартном заголовочном файле "stdio.h". Программисту не нужно знать, как устроена структура типа файл: ее устройство может быть системно зависимым, поэтому в целях переносимости программ обращаться явно к полям струтуры FILE запрещено. Тип данных "указатель на структуру FILE используется в программах как черный ящик: функция открытия файла возвращает этот указатель в случае успеха, и в дальнейшем все файловые функции применяют его для доступа к файлу.

Прототип функции открытия файла выглядит следующим образом:

Здесь path - путь к файлу (например, имя файла или абсолютный путь к файлу), mode - режим открытия файла. Строка mode может содержать несколько букв. Буква " r " (от слова read) означает, что файл открывается для чтения (файл должен существовать). Буква " w " (от слова write) означает запись в файл, при этом старое содержимое файла теряется, а в случае отсутствия файла он создается. Буква " a " (от слова append) означает запись в конец существующего файла или создание нового файла, если файл не существует.

В некоторых операционных системах имеются различия в работе с текстовыми и бинарными файлами (к таким системам относятся MS DOS и MS Windows; в системе Unix различий между текстовыми и бинарными файлами нет). В таких системах при открытии бинарного файла к строке mode следует добавлять букву " b " (от слова binary), а при открытии текстового файла -- букву " t " (от слова text). Кроме того, при открытии можно разрешить выполнять как операции чтения, так и записи; для этого используется символ + (плюс). Порядок букв в строке mode следующий: сначала идет одна из букв " r ", " w ", " a ", затем в произвольном порядке могут идти символы " b ", " t ", " + ". Буквы " b " и " t " можно использовать, даже если в операционной системе нет различий между бинарными и текстовыми файлами, в этом случае они просто игнорируются.

Значения символов в строке mode сведены в следующую таблицу:

Несколько примеров открытия файлов:

Обратите внимание, что во втором случае мы используем обычную косую черту / для разделения директорий, хотя в системах MS DOS и MS Windows для этого принято использовать обратную косую черту \ . Дело в том, что в операционной системе Unix и в языке Си, который является для нее родным, символ \ используется в качестве экранирующего символа, т.е. для защиты следующего за ним символа от интерпретации как специального. Поэтому во всех строковых константах Си обратную косую черту надо повторять дважды, как это и сделано в третьем примере. Впрочем, стандартная библиотека Си позволяет в именах файлов использовать нормальную косую черту вместо обратной; эта возможность была использована во втором примере.

В случае удачи функция fopen открытия файла возвращает ненулевой указатель на структуру типа FILE , описывающую параметры открытого файла. Этот указатель надо затем использовать во всех файловых операциях. В случае неудачи (например, при попытке открыть на чтение несуществующий файл) возвращается нулевой указатель. При этом глобальная системная переменная errno, описанная в стандартном заголовочном файле "errno.h, содержит численный код ошибки. В случае неудачи при открытии файла этот код можно распечатать, чтобы получить дополнительную информацию:

Константа NULL

В приведенном выше примере при открытии файла функция fopen в случае ошибки возвращает нулевой указатель на структуру FILE . Чтобы проверить, произошла ли ошибка, следует сравнить возвращенное значение с нулевым указателем. Для наглядности стандартный заголовочный файл "stdio.h" определяет символическую константу NULL как нулевой указатель на тип void :

Сделано это вроде бы с благой целью: чтобы отличить число ноль от нулевого указателя. При этом язык Си, в котором контроль ошибок осуществляется недостаточно строго, позволяет сравнивать указатель общего типа void * с любым другим указателем. Между тем,в Си вместо константы NULL всегда можно использовать просто 0 , и вряд ли от этого программа становится менее понятной. Более строгий язык C++ запрещает сравнение разных указателей, поэтому в случае C++ стандартный заголовочный файл определяет константу NULL как обычный ноль:

Автор языка C++ Б. Страуструп советует использовать обычный ноль 0 вместо символического обозначения NULL . Тем не менее, по традиции большинство программистов любят константу NULL .

Константа NULL не является частью языка Си или C++, и без подключения одного из стандартных заголовочных файлов, в котором она определяется, использовать ее нельзя. (По этой причине авторы языка Java добавили в язык ключевое слово null , записываемое строчными буквами.) Так что в случае Си или C++ безопаснее следовать совету Б. Страуструпа и использовать обычный ноль 0 вместо символической константы NULL .

Диагностика ошибок: функция perror

Функции бинарного чтения и записи fread и fwrite

После того как файл открыт, можно читать информацию из файла или записывать информацию в файл. Рассмотрим сначала функции бинарного чтения и записи fread и fwrite . Они называются бинарными потому, что не выполняют никакого преобразования информации при вводе или выводе (с одним небольшим исключением при работе с текстовыми файлами, которое будет рассмотрено ниже): информация хранится в файле как последовательность байтов ровно в том виде, в котором она хранится в памяти компьютера.

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

Здесь size_t определен как беззнаковый целый тип в системных заголовочных файлах. Функция пытается прочесть numElems элементов из файла, который задается указателем f на структуру FILE , размер каждого элемента равен elemSize . Функция возвращает реальное число прочитанных элементов, которое может быть меньше, чем numElems , в случае конца файла или ошибки чтения. Указатель f должен быть возвращен функцией fopen в результате успешного открытия файла. Пример использования функции fread :

В этом примере файл " tmp.dat " открывается на чтение как бинарный, из него читается 100 вещественных чисел размером 8 байт каждое. Функция fread возвращает реальное количество прочитанных чисел, которое меньше или равно, чем 100.

Функция fread читает информацию в виде потока байтов и в неизменном виде помещает ее в память. Следует различать текстовое представление чисел и их бинарное представление! В приведенном выше примере числа в файле должны быть записаны в бинарном виде, а не в виде текста. Для текстового ввода чисел надо использовать функции ввода по формату, которые будут рассмотрены ниже.

Внимание! Открытие файла как текстового с помощью функции fopen , например,

вовсе не означает, что числа при вводе с помощью функции fopen будут преобразовываться из текстовой формы в бинарную! Из этого следует только то, что в операционных системах, в которых строки текстовых файлов разделяются парами символами " \r\n " (они имеют названия CR и LF - возврат каретки и продергивание бумаги, Carriage Return и Line Feed ), при вводе такие пары символов заменяются на один символ " \n " (продергивание бумаги). Обратно, при выводе символ " \n " заменяется на пару " \r\n ". Такими операционными системами являются MS DOS и MS Windows. В системе Unix строки разделяются одним символом " \n " (отсюда проистекает обозначение " \n ", которое расшифровывается как new line). Таким образом, внутреннее представление текста всегда соответствует системе Unix, а внешнее - реально используемой операционной системе. Отметим также, что создатели операционной системы компьютеров Apple Macintosh выбрали, чтобы жизнь не казалась скучной, третий, отличный от двух предыдущих, вариант: текстовые строки разделяются одним символом " \r " возврат каретки!

Такое представление текстовых файлов восходит к тем уже далеким временам, когда еще не было компьютерных мониторов и для просмотра текста использовались электрифицированные пишущие машинки или посимвольные принтеры. Текстовый файл фактически представлял собой программу печати на пишущей машинке и, таким образом, содержал команды возврата каретки и продергивания бумаги в конце каждой строки.

Функция бинарной записи в файл fwrite аналогична функции чтения fread . Она имеет следующий прототип:

Функция возвращает число реально записанных элементов, которое может быть меньше, чем numElems , если при записи произошла ошибка - например, не хватило свободного пространства на диске. Пример использования функции fwrite :

Закрытие файла: функция fclose

По окончании работы с файлом его надо обязательно закрыть. Система обычно запрещает полный доступ к файлу до тех пор, пока он не закрыт. (Например, в нормальном режиме система запрещает одновременную запись в файл для двух разных программ.) Кроме того, информация реально записывается полностью в файл лишь в момент его закрытия. До этого она может содержаться в оперативной памяти (в так называемой файловой кеш -памяти), что при выполнении многочисленных операций записи и чтения значительно ускоряет работу программы.

Для закрытия файла используется функция fclose с прототипом

В случае успеха функция fclose возвращает ноль, при ошибке -- отрицательное значение (точнее, константу конец файла EOF, определенную в системных заголовочных файлах как минус единица). При ошибке можно воспользоваться функцией perror , чтобы напечатать причину ошибки. Отметим, что ошибка при закрытии файла - явление очень редкое (чего не скажешь в отношении открытия файла), так что анализировать значение, возвращаемое функцией fclose , в общем-то, не обязательно. Пример использования функции fclose :

Пример: подсчет числа символов и строк в текстовом файле

В качестве содержательного примера использования рассмотренных выше функций файлового ввода приведем программу, которая подсчитывает число символов и строк в текстовом файле. Программа сначала вводит имя файла с клавиатуры. Для этого используется функция scanf ввода по формату из входного потока, для ввода строки применяется формат " %s . Затем файл открывается на чтение как бинарный (это означает, что при чтении не будет происходить никакого преобразования разделителей строк). Используя в цикле функцию чтения fread , мы считываем содержимое файла порциями по 512 байтов, каждый раз увеличивая суммарное число прочитанных символов. После чтения очередной порции сканируется массив прочитанных символов и подсчитывается число символов " \n " продергивания бумаги, которые записаны в концах строк текстовых файлов как в системе Unix, так и в MS DOS или MS Windows. В конце закрывается файл и печатается результат.

Пример выполнения программы: она применяется к собственному тексту, записанному в файле "wc.cpp.

Форматный ввод-вывод: функции fscanf и fprintf

В отличие от функции бинарного ввода fread , которая вводит байты из файла без всякого преобразования непосредственно в память компьютера, функция форматного ввода fscanf предназначена для ввода информации с преобразованием ее из текстового представления в бинарное. Пусть информация записана в текстовом файле в привычном для человека виде (т.е. так, что ее можно прочитать или ввести в файл, используя текстовый редактор). Функция fscanf читает информацию из текстового файла и преобразует ее во внутреннее представление данных в памяти компьютера. Информация о количестве читаемых элементов, их типах и особенностях представления задается с помощью формата. В случае функции ввода формат - это строка, содержащая описания одного или нескольких вводимых элементов. Форматы, используемые функцией fscanf , аналогичны применяемым функцией scanf , они уже неоднократно рассматривались (см. раздел 3.5.4). Каждый элемент формата начинается с символа процента " % ". Наиболее часто используемые при вводе форматы приведены в таблице:

Прототип функции fscanf выглядит следующим образом:

Многоточие здесь означает, что функция имеет переменное число аргументов, большее двух, и что количество и типы аргументов, начиная с третьего, произвольны. На самом деле, фактические аргументы, начиная с третьего, должны быть указателями на вводимые переменные. Несколько примеров использования функции fscanf :

Функция fscanf возвращает число успешно введенных элементов. Таким образом, возвращаемое значение всегда меньше или равно количеству процентов внутри форматной строки (которое равно числу фактических аргументов минус 2).

Функция fprintf используется для форматного вывода в файл. Данные при выводе преобразуются в их текстовое представление в соответствии с форматной строкой. Ее отличие от форматной строки, используемой в функции ввода fscanf , заключается в том, что она может содержать не только форматы для преобразования данных, но и обычные символы, которые записываются без преобразования в файл. Форматы, как и в случае функции fscanf , начинаются с символа процента " % ". Они аналогичны форматам, используемым функцией fscanf . Небольшое отличие заключается в том, что форматы функции fprintf позволяют также управлять представлением данных, например, указывать количество позиций, отводимых под запись числа, или количество цифр после десятичной точки при выводе вещественного числа. Некоторые типичные примеры форматов для вывода приведены в следующей таблице:

Прототип функции fprintf выглядит следующим образом:

int fprintf(FILE *f, const char *format, . );

Многоточие, как и в случае функции fscanf , означает, что функция имеет переменное число аргументов. Количество и типы аргументов, начиная с третьего, должны соответствовать форматной строке. В отличие от функции fscanf , фактические аргументы, начиная с третьего, представляют собой выводимые значения, а не указатели на переменные. Для примера рассмотрим небольшую программу, выводящую данные в файл "tmp.dat":

В результате выполнения этой программы в файл "tmp.dat" будет записан следующий текст:

В последнем примере форматная строка содержит внутри себя двойные апострофы. Это специальные символы, выполняющие роль ограничителей строки, поэтому внутри строки их надо экранировать (т.е. защищать от интерпретации как специальных символов) с помощью обратной косой черты \ , которая, напомним, в системе Unix и в языке Си выполняет роль защитного символа. Отметим также, что мы воспользовались стандартной функцией sqrt , вычисляющей квадратный корень числа, и стандартной функцией strlen , вычисляющей длину строки.

Понятие потока ввода или вывода

В операционной системе Unix и в других системах, использующих идеи системы Unix (например, MS DOS и MS Windows), применяется понятие потока ввода или вывода. Поток представляет собой последовательность байтов. Различают потоки ввода и вывода. Программа может читать данные из потока ввода и выводить данные в поток вывода. Программы можно запускать в конвейере, когда поток вывода первой программы является потоком ввода второй программы и т.д. Для запуска двух программ в конвейере используется символ вертикальной черты | между именами программ в командной строке. Например, командная строка

означает, что поток вывода программы ab направляется на вход программе cd , а поток вывода программы cd - на вход программе ef . По умолчанию, потоком ввода для программы является клавиатура, поток вывода назначен на терминал (или, как говорят программисты, на консоль). Потоки можно перенаправлять в файл или из файла, используя символы больше > и меньше < , которые можно представлять как воронки. Например, командная строка

перенаправляет выходной поток программы abcd в файл "tmp.res", т.е. данные будут выводиться в файл вместо печати на экране терминала. Соответственно, командная строка

заставляет программу abcd читать исходные данные из файла "tmp.dat" вместо ввода с клавиатуры. Командная строка

перенаправляет как входной, так и выходной потоки: входной назначается на файл "tmp.dat", выходной -- на файл "tmp.res".

В Си работа с потоком не отличается от работы с файлом. Доступ к потоку осуществляется с помощью переменной типа FILE * . В момент начала работы Си-программы открыты три потока:

  • stdin -- стандартный входной поток. По умолчанию он назначен на клавиатуру;
  • stdout -- стандартный выходной поток. По умолчанию он назначен на экран терминала;
  • stderr -- выходной поток для печати информации об ошибках. Он также назначен по умолчанию на экран терминала.

Переменные stdin , stdout , stderr являются глобальными, они описаны в стандартном заголовочном файле "stdio.h. Операции файлового ввода-вывода могут использовать эти потоки, например, строка

вводит значение целочисленной переменной n из входного потока. Строка

выводит значение переменой n в выходной поток. Строка

По умолчанию, стандартный выходной поток и выходной поток для печати ошибок назначены на экран терминала. Однако операция перенаправления вывода в файл > действует только на стандартный выходной поток. Например, в результате выполнения командной строки

Функции scanf и printf ввода и вывода в стандартные потоки

Поскольку ввод из стандартного входного потока, по умолчанию назначенного на клавиатуру, и вывод в стандартный выходной поток, по умолчанию назначенный на экран терминала, используются особенно часто, библиотека функций ввода-вывода Си предоставляет для работы с этими потоками функции scanf и printf . Они отличаются от функций fscanf и fprintf только тем, что у них отсутствует первый аргумент, означающий поток ввода или вывода. Строка

Описание работы с файлами в языке Си: открытие, закрытие и переименование файлов, функции бинарного чтения и текстового преобразования, диагностика ошибок. Определение текущей рабочей директории, текущего каталога диска и размера дискового пространства.

Рубрика Программирование, компьютеры и кибернетика
Вид лабораторная работа
Язык русский
Дата добавления 06.07.2009
Размер файла 38,2 K

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Кафедра: Автоматика и Информационные Технологии

РАБОТА С ФАЙЛАМИ, ДИРЕКТОРИЯМИ И ДИСКОВЫМ ПРОСТРАНСТВОМ

СОДЕРЖАНИЕ

1. Работа с файлами

1.1 Открытие файла: функция fopen

1.2 Диагностика ошибок: функция perror

1.3 Функции бинарного чтения и записи fread и fwrite

1.4 Закрытие файла: функция fclose

1.5 Пример: подсчет числа символов и строк в текстовом файле

1.6 Функции текстового преобразования sscanf и sprintf

1.7 Переименование файла

1.8 Определение текущей рабочей директории

1.9 Определение текущего каталога диска

1.10 Определение размера свободного дискового пространства

1.11 Определение/установка текущего диска

1.12 Создание, удаление, смена директорий

1.13 Поиск файла

1.14 Просмотр каталога диска

1.15 Создание уникального имени файла

1.16 Редактирование имени файла

2. Лабораторные задания

2.1 Переменное число параметров.

2.2 Многострочный ввод с клавиатуры

2.3 Объединение файлов

2.4 Замена в текстовом файле.

2.5 Ввод массивов.

2.6 Просмотр дисков

2.7 Структура каталога

3. Дополнительные задания

3.2 Комментарии в программе

1. Работа с файлами

Стандартная библиотека Си содержит набор функций для работы с файлами. Эти функции описаны в стандарте ANSI. Отметим, что файловый ввод-вывод не является частью языка Си, и ANSI-функции - не единственное средство ввода-вывода. Так, в операционной системе Unix более популярен другой набор функций ввода-вывода, который можно использовать не только для работы с файлами, но и для обмена по сети. В C++ часто используются библиотеки классов для ввода-вывода. Тем не менее, функции ANSI-библиотеки поддерживаются всеми Си-компиляторами, и потому программы, применяющие их, легко переносятся с одной платформы на другую. Прототипы функций ввода-вывода и используемые для этого типы данных описаны в стандартном заголовочном файле "stdio.h.

1.1 Открытие файла: функция fopen

Для доступа к файлу применяется тип данных FILE. Это структурный тип, имя которого задано с помощью оператора typedef в стандартном заголовочном файле <stdio.h>. Программисту не нужно знать, как устроена структура типа файл: ее устройство может быть системно зависимым, поэтому в целях переносимости программ обращаться явно к полям структуры FILE запрещено. Тип данных "указатель на структуру FILE” используется в программах как черный ящик: функция открытия файла возвращает этот указатель в случае успеха, и в дальнейшем все файловые функции применяют его для доступа к файлу.

Прототип функции открытия файла выглядит следующим образом:

FILE *fopen(const char *path, const char *mode);

Здесь path - путь к файлу (например, имя файла или абсолютный путь к файлу), mode - режим открытия файла. Строка mode может содержать несколько букв. Буква "r" (read) означает, что файл открывается для чтения (файл должен существовать). Буква "w" (write) означает запись в файл, при этом старое содержимое файла теряется, а в случае отсутствия файла он создается. Буква "a" (от слова append) означает запись в конец существующего файла или создание нового файла, если файл не существует.

В некоторых операционных системах имеются различия в работе с текстовыми и бинарными файлами (к таким системам относятся MS DOS и MS Windows; в системе Unix различий между текстовыми и бинарными файлами нет). В таких системах при открытии бинарного файла к строке mode следует добавлять букву "b" (от слова binary), а при открытии текстового файла -- букву "t" (от слова text). Кроме того, при открытии можно разрешить выполнять как операции чтения, так и записи; для этого используется символ + (плюс). Порядок букв в строке mode следующий: сначала идет одна из букв "r", "w", "a", затем в произвольном порядке могут идти символы "b", "t", "+". Буквы "b" и "t" можно использовать, даже если в операционной системе нет различий между бинарными и текстовыми файлами, в этом случае они просто игнорируются.

Значения символов в строке mode сведены в следующую таблицу:

Режимы открытия файла

Открыть существующий файл на чтение

Открыть файл на запись. Старое содержимое файла теряется, в случае отсутствия файла он создаётся.

Открыть файл на запись. Если файл существует, то запись производится в его конец.

Читайте также: