Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lek13_14.doc
Скачиваний:
9
Добавлен:
13.07.2019
Размер:
695.3 Кб
Скачать

Поиск в файлах с помощью функций fseek( ), ftell( ) и rewind()

Функции fseek(),ftell() и rewind() предназначены для определения и изменения положения маркера текущей позиции файла. Первая из них, fseek(), перемещает маркер в файле, заданном указателем pf, на требуемое число байтов, определенное аргументом ibytes. Перемещение осуществляется от начала файла (аргумент ifrom равен 0), от текущего положения маркера (аргумент ifrom равен 1) или от конца файла (аргумент ifrom равен 2). В языке С предусмотрены три константы, которые можно указывать в качестве аргумента ifrom: seek_set (сдвиг от начала файла), seek_cur(сдвиг от текущей позиции) и seek_end(сдвиг от конца файла). Функция fseek ( ) возвращает ноль при успешном завершении и EOF в противном случае. Синтаксис функции таков:

fseek(pf,  ibytes, ifrom) ;

Функция ftell() возвращает текущую позицию маркера в файле, которая определяется величиной смещения в байтах от начала файла. Возвращаемое значение имеет тип long.

Функция rewind( ) просто перемещает маркер в начало файла.

В следующей программе на языке С продемонстрировано использование всех трех функций: fseek(),ftell() и rewind().

/* *   fseek.с *  Эта программа на языке С демонстрирует использование *  функций fseek(), ftell() и rewind() . */

#include <stdio.h>

void main ( ) {

FILE *pf;

char c;

long llocation;

pf = fopen("test.dat","r+t");

с = fgetc(pf ) ;    putchar (c) ;  

с = fgetc(pf ) ; putchar (c);

llocation = ftell (pf ) ;

с = fgetc (pf) ;

putchar (c); 

fseek(pf,llocation, 0) ;

с = fgetc(pf) ;

putchar(с);    

fseek(pf, llocation, 0);  fputc.(E1, pf) ;

fseek(pf,llooation, 0) ;

с = fgetc(pf); putchar(c);

rewind (pf);   

с = fgetc (pf) ;    putchar(c);

}   

Переменная llocation имеет тип long. Это связано с тем, что язык С поддерживает работу с файлами, размер которых превышает 64 Кб. Файл TEST.DAT содержит строку "ABCD". Первая из функций fgetc() возвращает букву 'А', после чего программа выводит ее на экран. В следующих двух строках выводится буква 'В'.

Далее функция ftell() записывает в переменную llocation значение маркера текущей позиции в файле. Поскольку буква 'В' уже прочитана, переменная llocationбудет содержать 2. Это означает, что в данный момент маркер указывает на третий символ, который смещен на 2 байта от первого символа 'А'.

В следующей паре строк считывается и отображается буква 'С'. После выполнения данной операции маркер сдвинется на четвертый символ — 'D'.

В этом месте программа вызывает функцию fseek (), которая перемещает маркер на 2 байта от начала файла (отсчет идет от начала файла, поскольку третий аргумент функции равен 0). После выполнения функции маркер вновь "указывает на третий символ в файле. Поэтому в результате работы следующих двух строк на экран будет выведена буква 'С'.

При втором вызове функции fseek() устанавливаются те же параметры, что и в первом случае. Но на этот раз с помощью функции fputc() в файл записывается буква 'Е' на место буквы 'С'. Чтобы убедиться, что новая буква действительно была вставлена в файл, программа в очередной раз обращается к функции fseek()для перемещения к третьей позиции, считывает символ в этой позиции и отображает его. Этим символом будет 'Е'.

3атем вызывается функция rewind(),которая перемещает маркер в начало файла. При следующем вызове функции fgetc() из файла считывается буква 'А', которая и выводится на экран. В результате работы программы на экране будет получена следующая последовательность букв: АВССЕА 

Форматный ввод

Форматирование вводимых данных в языке С можно осуществлять с помощью достаточно мощных функций scanf() и fscanf (), Различие между ними заключается в том, что последняя требует указания файла, из которого читаются данные. Функция scanf() принимает данные из стандартного входного потока stdin.

Функции scanfC ), fscanf( ) и sscanf( )

Функция scanf (), как и ее "родственники" fscanf() и sscanf (), в качестве аргумента принимает такого же рода строку форматирования, что и функция printf(), осуществляющая вывод данных, хотя имеются и некоторые отличия. Для примера рассмотрим следующее выражение:

scanf("%2d%5s%4f",   sivalue,   psz,   &fvalue);

Данная функция считывает целое число, состоящее из двух цифр, строку из пяти символов и число с плавающей запятой, образованное не более чем четырьмя символами (2,97, 12,5 и т.п.). Все аргументы, перечисленные после строки форматирования, должны быть указателями, т.е. содержать адреса переменных. А теперь попробуем разобрать более сложное выражение:

scanf ("  \"%[^А-Zа-z-] %*[-] %[^\"]",   ps1,  ps2);

Первым в строке форматирования стоит пробел. Он служит указанием пропустить все ведущие пробелы, символы табуляции и новой строки, пока не встретится двойная кавычка ("). В строке форматирования этот символ защищен обратной косой чертой (\"), так как в противном случае он означал бы завершение самой строки! Таким образом, обратная косая черта является своего рода командой отмены специального назначения следующего за ней символа.

Управляющая последовательность %[^A-Za-z-] говорит о том, что в строку рs1 нужно вводить все, кроме букв и символа дефиса (-). Квадратные скобки, в которых на первом месте стоит знак крышки (^), определяют диапазон символов, из которых не должна состоять вводимая строка. В данном случае в диапазон входят буквы от 'А' до 'Z' (дефис между ними означает "от и до") и от 'а' до 'z', а также сам дефис. Если убрать знак ^, то, наоборот, будут ожидаться только буквы и символы дефиса. В конец прочитанной строки добавляется символ \0. Если во входном потоке вслед за открывающей кавычкой первыми встретятся буква или дефис, выполнение функции scanf() завершится ошибкой и в переменные ps1 и рs2 ничего не будет записано, а сама строка останется в буфере потока. Чтение строки ps1 продолжается до тех пор, пока не встретится один из символов, указанных после знака ^.

Вторая управляющая последовательность % * [ - ] говорит о том, что после чтения строки ps1 должна быть обнаружена группа из одного или нескольких дефисов, которые необходимо пропустить. Символ звездочки (*) указывает на то, что данные должны быть прочитаны, но не сохранены. Отметим два важных момента.

  • Если после строки ps1 первой встретится буква, а не дефис, выполнение функции scanf() завершится ошибкой, в переменную ps2 ничего не будет записано, а сама строка останется в буфере потока.

  • Если бы в первой управляющей последовательности символ дефиса не был отмечен как пропускаемый, функция scanf() работала бы неправильно, так как символ дефиса, являющийся "ограничителем" строки ps1, воспринимался бы как часть этой строки! В этом случае чтение было бы прекращено только после обнаружения буквы, а это, в свою очередь, привело бы к возникновению ошибки, описанной в первом пункте.

Последняя управляющая последовательность %[^\"] указывает на то, что в строку ps2 нужно считывать все символы, кроме двойных кавычек, которые являются признаком завершения ввода.

Для полной ясности приведем пример входной строки:

"65---ААА"

Вот что будет получено в результате: *psl= 65, *ps2 = ааа.

Все вышесказанное справедливо и в отношении функций fscanf () и sscanf (). Функция sscanf() работает точно так же, как и scanf(),но читает данные из указанного символьного массива, а не из потока stdin. В следующем примере показано, как с помощью функции sscanf() преобразовать строку цифр в целое число:

sscanf(psz,"%d",&ivalue);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]