Язык Си - руководство для начинающих - M. УЭИТ
Шрифт:
Интервал:
Закладка:
/* считывает файл строка за строкой */
#include <stdio.h>
#define MAXLIN 80
main( )
{
FILE *f1;
char *string [MAXLIN];
f1 = fopen("story", "r");
while(fgets(string, MAXLIN, f1) != NULL)
puts(string);
}
Первый из трех аргументов функции fgets( ) является указателем на местоположение считываемой строки. Мы располагаем вводимую информацию в символьный массив string.
Второй аргумент содержит предельную длину считываемой строки. Функция прекращает работу после считывания символа новой строки или после считывания символов общим числом MAXLIN - 1 (в зависимости от того, что произойдет раньше). В любом случае нуль-символ (' ') добавляется в самый конец строки.
Третий аргумент указывает, конечно, на файл, который будет читаться.
Разница между gets( ) и fgets( ) заключается в том, что gets( ) заменяет символ новой строки на ' ', в то время как fgets( ) сохраняет символ новой строки.
Подобно gets( ) функция fgets( ) возвращает значение NULL, если встречает символ EOF. Это позволяет вам проверить, как мы и сделали, достигли ли вы конца файла.
Функция fputs( )
Эта функция очень похожа на puts( ). Оператор
fputs(" Вы были правы.", fileptr);
передает строку "Вы были правы." В файл, на который ссылается указатель fileptr типа FILE. Конечно, сначала нужно открыть файл при помощи функции fopen( ). В самом общем виде это выглядит так
status = fputs(yказатель строки, указатель файла);
где status является целым числом, которое устанавливается в EOF, если fputs( ) встречает EOF или ошибку.
Подобно puts( ) эта функция не ставит завершающий символ ' ' в конец копируемой строки. В отличие от puts() функция fputs( ) не добавляет символ новой строки в ее вывод.
Шесть функций ввода-вывода которые мы только что обсудили, должны дать вам инструмент, для чтения и записи текстовых файлов. Есть еще одно средство, которое может оказаться полезным, и мы его сейчас обсудим.
ПРОИЗВОЛЬНЫЙ ДОСТУП: fseek( )
Функция fseek( ) позволяет нам обрабатывать файл подобно массиву и непосредственно достигать любого определенного байта в файле, открытом функцией fopen( ). Вот простой пример, показывающий, как она работает. Как и в наших предыдущих примерах, функция использует аргумент командной строки для получения имени файла, с которым она работает. Заметим, что fseek() имеет три аргумента и возвращает значение типа int.
/*использование fscek( ) для печати содержимого файла */
#include <stdio.h&
main(number, names) /* не следует использовать argc и argv */
int number;
char *namеs[ ];
{
FILE *fp;
long offset = OL; /*обратите внимание, что это тип long */
if(number < 2)
puts("Мне нужно имя файла в качестве аргумента.");
else {
if((fp = fopen(names[1], "r")) == 0)
printf(" Я не могу открыть %s.n", names[1]);
else {
while(fseek(fp, offset++, 0) == 0)
putchar(getc(fp));
fclose(fp); }
}
}
Первый из трех аргументов функции fseek( ) является указателем типа FILE на файл, в котором ведется поиск. Файл следует открыть, используя функцию fopen( ).
Второй аргумент назван "offset" (вот почему мы выбрали данное имя для переменной). Этот аргумент сообщает, как далеко следует передвинуться от начальной точки (см. ниже); он должен иметь значение типа long, которое может быть положительным (движение вперед) или отрицательным (движение назад).
Третий аргумент является кодом, определяющим начальную точку:
Код Положение в файле 0 начало файла 1 текущая позиция 2 конец файлаФункция fseek( ) возвращает 0, если все хорошо, и -1, если есть ошибка, например попытка перемещаться за границы файла. Теперь мы можем разъяснить наш маленький цикл:
while(fseek(fp, offset++, 0)==0)
putchar(getc(fp));
Поскольку переменная offset инициализирована нулем, при первом прохождении через цикл мы имеем выражение
fseek(fp, OL, 0)
означающее, что мы идем в файл, на который ссылается указатель fp, и находим байт, отстоящий на 0 байт от начала, т.е. первый байт. Затем функция putchar( ) печатает содержимое этого байта. При следующем прохождении через цикл переменная offset увеличивается до 1L, и печатается следующий байт. Посуществу, переменная offset действует подобно индексу для элементов файла. Процесс продолжается до тех пор, пока offset нe попытается попасть в fseek( ) после конца файла. В этом случае fseek( ) возвращает значение - 1 и цикл прекращается.
Этот последний пример чисто учебный. Нам нe нужно использовать fseek( ), потому что getc( ) так или иначе проходит через файл байт за байтом; fseek( ) приказала getc( ) "посмотреть" туда, куда она сама уже собиралась посмотреть.
Вот пример (рис. 15.2), в котором выполняется что-то несколько более необычное (Мы благодарим Вильяма Шекспира за этот пример в пьесе "Двенадцатая ночь").
/* чередование печати в прямом и обратном направлениях */
#include <stdio.h>
main(number, names) /* вам не нужно применять argc и argv */
int number;
char *names[ ];
{
FILE *fp;
long offset = 0L;
if(number < 2)
puts(" Мне нужно имя файла в качестве аргумента.");
else {
if(fp = fopen(names[l], "r")) == 0)
printf(" Я не могу открыть %s.n", names[l]);
else {
while(fseek(fp, offset++, 0) == 0)
{ putchar(getc(fp));
if(fseek(fp, -(offset + 3), 2) == 0)
putchar(getc(fp)); }
fclose(fp); }
} }
РИС. 15.2. Программа, чередующая печать в прямом и обратном направлениях.
Применение этой программы к файлу, содержащему имя "Мальволио", дает такой приятный результат:
МоаилльоввоьллиаоМ
Наша программа печатает первый символ файла, затем последний, затем второй, затем предшествующий последнему и т.д. Мы только добавили вот эти строки в последнюю программу:
if(fseek(fp, -(offset + 3), 2) == 0)
putchar(getc(fp));
Код 2 в операторе предполагает, что мы будем считать позиции от конца файла. Знак минус означает счет в обратном направлении. +3 стоит здесь потому, что мы начинаем с последнего регулярного символа файла и пропускаем несколько символов "новая строка" и EOF в самом конце файла. (Точное значение этой корректировки зависит от типа системы. Наши файлы имеют в конце по два символа новой строки, за которыми следуют два EOF, поэтому мы как раз их и обходим.)
Таким образом, эта часть программы чередует печать в обратном направлении и печать в прямом направлении. Следует заметить, что в некоторых системах может не предусматриваться код 2 для fseek( ).
Теперь оставим на некоторое время файлы и перейдем к другому разделу библиотеки.
ПРОВЕРКА И ПРЕОБРАЗОВАНИЕ СИМВОЛОВ
Заголовочный файл ctype.h содержит несколько функций макроопределений, которые проверяют, к какому классу принадлежат символы. Функция isalpha(c), например, возвращает ненулевое значение (истина), если с является символом буквы, и нуль (ложь), если символ не является буквой. Таким образом,
isalpha('S') != 0, но isalpha('#') ==0
Ниже перечислены функции, чаще всего находящиеся в этом файле. В каждом случае функция возвращает ненулевое значение, если с принадлежит к опрашиваемому классу, и нуль в противном случае.
ФУНКЦИЯ ПРОВЕРЯЕТ, ЯВЛЯЕТСЯ ЛИ С isalpha(c) буквой isdigit(c) цифрой islower(c) строчной буквой isspace(c) пустым символом (пробел, табуляция или новая строка) isupper(c) прописной буквойВаша система может иметь дополнительные функции, такие как