Выбрать главу

Третий аргумент является кодом, определяющим начальную точку:

Код Положение в файле
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) прописной буквой

Ваша система может иметь дополнительные функции, такие как

ФУНКЦИЯ ПРОВEРЯEТ, ЯВЛЯЕТСЯ ЛИ С
isalnum(c) алфавитноцифровым (буква или цифра)
isascii(c) кодом ASCII (0-127)
iscntrl(c) управляющим символом
ispunct(c) знаком пунктуации

Еще две функции выполняют преобразования

toupper(c) преобразует с в прописную букву
tolower(c) преобразует с в строчную букву

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

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

/* преобразование строчных букв в прописные и обратно */

#include <stdio.h>

#include <ctype.h>  /* включает файл макроопределений */

#define  UPPER 1