Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Fseek() и произвольный доступ

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

int fseek(FILE *fp, long число_байт, int начало);

где fp - это указатель на файл, возвращенный fopen(), число_байт - это длинное целое, содер­жащее число байт от начала до позиции маркера, а начало - это одно из следующих макроопре­делений (определенных в stdio.h):

Макроопределение Смысл
SEEK_SET SEEK_CUR SEEK_END Начало файла Текущая позиция Конец файла

Макроопределения определены как целочисленные значения, причем SEEK_SET соответствует 0, SEEK_CUR - 1, a SEEK_END - 2. Следовательно, для перехода на число_байт от начала файла следует установить начало в SEEK_SET. Для перехода от текущей позиции надо использо­вать SEEK_CUR, а для перехода от конца файла - SEEK_END. Функция fseek() возвращает 0 в случае удачи или ненулевое значение в случае ошибки.
Например, можно использовать следующий код для чтения 23-го байта файла 5.txt:

#include <stdio.h>

#include <conio.h>

int func1(void)

{

FILE *fp;

if((fp=fopen("5.txt", "rb")) == NULL)

{

printf("Cannot open file.");

}

fseek(fp, 23, 0);

return getc(fp); /* чтение одного символа в 234-й позиции */

}

 

void main()

{

char a;

a=func1();

printf("%c",a);

_getch();

}

 

Другим примером, использующим функцию fseek(), является следующая программа dump, по­зволяющая просмотреть содержимое, как в ASCII, так и в шестнадцатиричных форматах. Можно смотреть на файл 128-байтными «секторами», причем двигаться можно в произвольном направле­нии. Для выхода из программы следует набрать -1, когда будет предложено ввести номер сектора. Обратим внимание на использование fread() для чтения файла. Если остается прочитать меньше чем SIZE байт, то число, передаваемое в display(), как раз и определяет, сколько символов необхо­димо вывести. (Надо помнить, что fread() возвращает число прочитанных элементов.) Введем про­грамму в компьютер и основательно с ней разберемся:

/* dump: простая дисковая утилита для просмотра, использующая fseek. */
#include <stdio.h>
#include <ctype.h>
#define SIZE 128
void display(int numread);
char buf[SIZE];
void display();
int main(int argc, char *argv[])
{
FILE *fp;
int sector, numread;
if(argc!=2) {
printf("Usage: dump filename");
return 1;
}
if((fp=fopen(argv[1], "rb"))==NULL) {
printf("Cannot open file.");
return 1;
}
do {
printf("Enter sector: ");
scanf("%d", &sector);
if(sector >= 0) {
if(fseek(fp, sector*SIZE, SEEK_SET)) {
printf("seek error");
}
if((numread=fread(buf, 1, SIZE, fp))!= SIZE)
printf("EOF reached.");
display(numread);
}
} while(sector>=0);
return 0;
}

/* вывод содержимого файла */
void display(int numread)
{
int i, j;
for(i=0; i<numread/16; i++) {
for (j=0; j<16; j++) printf("%3X", buf[i*16+j]);
printf(" ");
for(j=0; j<16; j++) {
if(isprint(buf[i*16+j])) printf("%c", buf[i*16+j]);
else printf(".");
}
printf("\n");
}
}

Надо обратить внимание, что библиотечная функция isprint() используется для определения вы­водимых символов. Функция isprint() возвращает истину, если символ можно вывести, и ложь - если нельзя. Для ее использования необходимо подключить заголовочный файл ctype.h.

fprintf() и fscanf()

Помимо основных функций ввода/вывода, система буферизированного ввода/вывода содержит fprintf() и fscanf(). Данные функции ведут себя так же, как и printf() и scanf(), за тем исключением, что работают с дисковыми файлами. Они имеют следующие прототипы:

int fprintf(FILE *fp, const char *форматная_строка,...);

int fscanf(FILE *fp, const char * форматная_строка,...);

где fp - это указатель на файл, возвращаемый fopen(). Если не принимать во внимание, что они перенаправляют вывод в файл, то можно считать, что работа данных функций полностью иден­тична printf() и scanf() соответственно.

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

/* простой телефонный справочник */
#include <conio.h>

#include <stdlib.h>

#include <stdio.h>

#include <ctype.h>

#include <string.h>

 

void add_num(void), lookup(void);

char menu(void);

 

int main(void)

{

char choice;

do {

choice = menu();

switch(choice)

{

case 'a': add_num();break;

case 'l': lookup();break;

}

} while (choice!='q');

return 0;

}

/* вывод меню и получение запроса */

char menu(void)

{

char ch;

do {

printf("(A)dd, (L)ookup, or (Q)uit: ");

ch = tolower(getche());

printf("\n");

} while(ch!= 'q' && ch!= 'a' && ch!= 'l');

return ch;

}

/* добавление имени и номера в справочник */

void add_num(void)

{

FILE *fp;

char name[80];

int a_code, exchg, num;

/* открытие для присоединения */

if((fp=fopen("phone.txt", "a")) == NULL) {

printf("Cannot open directory file.");

}

printf("Enter name and number: ");

fscanf(stdin, "%s%d%d%d", name, &a_code, &exchg, &num);

fscanf(stdin, "%*c"); /* удаление возврата каретки из потока ввода */

/* запись в файл */

fprintf(fp,"%s %d %d %d\n", name, a_code, exchg, num);

fclose(fp);

}

/* поиск числа по имени */

void lookup(void)

{

FILE *fp;

char name[80], name2[80];

int a_code, exchg, num;

/* открытие для чтения */

if((fp=fopen ("phone.txt","r")) == NULL)

{

printf("Cannot open directory file.");

}

printf("name? ");

gets(name);

/* поиск числа */

while(!feof(fp)) {

fscanf(fp,"%s%d%d%d", name2, &a_code, &exchg, &num);

if (!strcmp(name, name2)) {

printf("%s: (%d) %d-%d\n",name, a_code, exchg, num);

break;

}

}

fclose(fp);

}

 

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

ЗАМЕТКА: Хотя fprintf() u fscanf() часто являются наиболее простым способом записи и чтения данных из файла, они далеко не всегда являются наиболее эф­фективным решением. Поскольку отформатированные ASCII-данные сохраняются так же, как они выглядят на экране (а не в двоичном представлении), появляются дополнительные расходы при каждом вызове. Если скорость работы программы или размер создаваемых файлов играют важную роль, то, возможно, лучше ис­пользовать fread() и fwrite()
<== предыдущая лекция | следующая лекция ==>
Чтение символа | Работа с консолью
Поделиться с друзьями:


Дата добавления: 2013-12-14; Просмотров: 431; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.029 сек.