Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Внимание!
Если вы используете любой режим "w" без буквы х для существующего файла, содержимое файла усекается так, что программа может начать работу с чистого листа. Однако попытка открыть существующий файл с применением одного из режимов С11, содержащий букву х, завершится отказом.
538 Глава 13
После успешного открытия файла функция fopen() возвращает указатель файла, который затем другие функции ввода-вывода могут использовать для указания этого файла. Указатель файла (в примере это fp) имеет тип указателя на FILE; здесь FILE - производный тип, определенный в stdio.h. Указатель fp не ссылается на действительный файл. Вместо этого он указывает на объект данных, содержащий инфор мацию о файле, включая сведения о буфере, который применяется для файлового ввода-вывода. Гак как функции ввода-вывода из стандартной библиотеки используют буфер, им необходимо знать, где этот буфер находится. Им также должно быть известно, насколько заполнен буфер и с каким файлом осуществляется работа. Это позволяет функциям по мере необходимости заполнять или опустошать буфер. Вся эта информация содержится в объекте данных, указываемом fp. (Такой объект данных является примером структуры С, которые обсуждаются в главе 14.)
Функция fopen() возвращает нулевой указатель (также определенный в stdio.h), если ей не удается открыть файл. Когда указатель fp равен NULL, программа прекращает выполнение. Функция fopen() может отказать из-за переполнения диска, от сутствия файла в искомом каталоге, недопустимого имени, ограничений доступа или аппаратной проблемы. Это лишь небольшая часть причин отказа, так что ищите неполадку; даже минимальные меры по отлавливанию ошибок могут иметь большое значение.
ФУНКЦИИ getc() и putc()
Функции getc() и putc() работают очень похоже на getchar() и putchar(). Отличие заключается в том, что этим новым функциям потребуется указать, с каким файлом работать. Таким образом, приведенный ниже многократно использованный нами оператор означает “получить символ из стандартного ввода”:
ch = getchar();
Тем не менее, следующий оператор означает “получить символ из файла, идентифицируемого fp”:
ch = getc(fp);
Аналогично, показанный далее оператор означает “поместить символ ch в файл, идентифицируемый указателем fpout на FILE”:
putc(ch, fpout);
В списке аргументов putc() сначала задается символ, а затем указатель файла.
В листинге 13.1 во втором аргументе putc() применяется stdout. Он определен в stdio.h как указатель файла, ассоциированный со стандартным выводом, поэтому putc (ch, stdout) эквивалентно putchar (ch). На самом деле вторая функция обычно определена как первая. Аналогично, getchar() определена как функция getc(), использующая стандартный ввод.
Возможно, вас интересует, почему в этом примере применяется putc(), а не putchar(). Одна причина связана с необходимостью ознакомления с функцией putc(). Другая причина заключается в том, что вы легко можете преобразовать программу так, чтобы она могла генерировать файловый за счет использования аргумента, отличного от stdout.
конец файла
Программа, читающая данные из файла, должна останавливаться, когда она достигает конца файла. Как можно сообщить программе о том, что встретился конец файла?
Файловый ввод-вывод 539
Функция getc() возвращает специальное значение EOF, если она пытается прочитать символ и обнаруживает, что достигнут конец файла. Таким образом, программа С выясняет, что она достигла конца файла, только после попытки чтения за концом файла. (Это не похоже на поведение в ряде других языков, в которых предусмотрена специальная функция для проверки на предмет конца файла перед попыткой чтения.)
Чтобы избежать проблем с попыткой чтения пустого файла, при файловом вводе должен применяться цикл с входным условием (не цикл do while). Из-за конструктивных особенностей getc() (и других функций ввода С) программа должна выполнять чтение до входа в тело цикла. Тогда показанное ниже проектное решение вполне по дойдет:
// правильное проектное решение #1
int ch; // переменная int для хранения EOF
FILE * fp;
fp = fopen("wacky.txt", "r");
ch = getc(fp); // получить первоначальный ввод
while (ch ! = EOF)
{
putchar(ch); // обработать ввод
ch = getc(fp); // получить следующий ввод
}
Это решение можно ужать следующим образом:
// правильное проектное решение #2 int ch;
FILE * fp;
fp = fopen("wacky.txt", "r"); while ((ch = getc(fp)) ! = EOF)
{
putchar(ch); // обработать ввод
}
Поскольку оператор ввода является частью проверочного условия while, он выполняется до того, как поток управления войдет в тело цикла.
Проектных решений вроде приведенного ниже вы должны избегать:
// неудачное проектное решение (две проблемы) int ch;
FILE * fp;
fp = fopen("wacky.txt", "r");
while (ch != EOF) // первым используется неопределенное значение ch {
ch = getc(fp); // получить ввод
putchar(ch); // обработать ввод
}
Первая проблема связана с тем, что когда переменная ch в первый раз сравнивается с EOF, ей еще не было присвоено значение. Вторая проблема в том, что если getc() возвращает EOF, то цикл пытается обработать EOF, как если бы это был допустимый символ. Указанные дефекты поддаются исправлению. К примеру, вы могли бы инициализировать ch каким-то фиктивным значением и поместить внутрь цикла оператор if, но зачем об этом беспокоиться, если доступны правильные проектные решения?
Указанные меры предосторожности касаются и других функций ввода. Они также возвращают сигнал об ошибке (EOF или пустой указатель), столкнувшись с концом файла.
540 Глава 13
ФУНКЦИЯ fclose()
Функция fclose(fp) закрывает файл, идентифицируемый fp, при необходимости сбрасывая буферы. В более ответственной программе вы должны удостовериться, что файл закрыт успешно. Функция fclose() возвращает значение 0, если файл был закрыт успешно, и EOF, если нет:
if (fclose(fp) != 0)
printf("Ошибка при закрытии файла %s\n", argv[1]);
Функция fclose() может завершиться неудачно, если, например, жесткий диск заполнен, съемное устройство храпения извлечено или произошла ошибка ввода-вывода.
Указатели на стандартные файлы
В stdio.h три указателя файлов ассоциированы с тремя стандартными файлами, которые автоматически открываются программами на С.
Стандартный файл Указатель файла Обычное устройство
Стандартный ввод stdin Клавиатура
Стандартный вывод stdout Экран
Стандартный вывод ошибок stderr Экран
Все они имеют тип указателя на FILE, поэтому могут использоваться в качестве аргументов для стандартных функций ввода-вывода подобно fp в приведенном ранее примере. Давайте теперь перейдем к рассмотрению примера, в котором создается новый файл и в него производится запись.
Бесхитростная программа уплотнения файла
Следующая программа копирует избранные данные из одного файла в другой. Она открывает два файла одновременно с применением режима "г" для одного и режима "w" для второго. Программа (показанная в листинге 13.2) уплотняет содержимое первого файла, грубо оставляя только каждый третий символ. В итоге она помещает уплотненный текст во второй файл. Имя второго файла образуется путем дополнения старого имени расширением . red. Использование аргументов командной строки, открытие одновременно более одного файла и добавление расширения к имени файла в общем случае являются довольно практичными приемами. Эта конкретная форма уплотнения файла имеет ограниченное применение, по, как вы увидите, такие случаи возникают. (Программу несложно модифицировать, чтобы для предоставления имен файлов вместо аргументов командной строки использовались стандартные методы ввода-вывода.)
Читать дальшеИнтервал:
Закладка: