Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Посимвольное чтение из файла



Для посимвольного чтения из файла используется функция getc() или fgetc(). Синтаксис записи следующий:

char_variable = getc(file_pointer);

Например, для того чтобы получить символ из файла, связанного с указателем на файл fp, надо написать инструкцию:

letter = getc(fp);

Ниже приведена программа, которая читает файл, созданный в предыдущем примере:

/*fgets.c*/#include main() { FILE *fp; int letter; if((fp = fopen(" MYFILE", " r" ))==NULL) { puts(" Невозможно открыть файл" ); exit(); } while((letter = fgetc(fp))! = EOF) printf(" %c", letter); fclose(fp); }

Здесь файл открывается с режимом доступа " r", после чего в цикле while осуществляется посимвольное чтение. Большая часть работы программы выполняется внутри условия цикла while. Выражение

letter = fgetc(fp)

присваивает символ, полученный из файла, переменной letter. Цикл выполняется до тех пор, пока указатель не достигнет конца файла и значение переменной не станет равно значению специальной константы EOF (она определена в файле заголовков STDIO.H), что, собственно, и является признаком достижения конца файла.

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

Работа со строками

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

Функция fputs() имеет следующий синтаксис:

fputs(string_variable, file_pointer);

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

 

/*fputc.c*/#include main() { FILE *fp; char flag; char name[20]; if((fp = fopen(" MYFILE", " w" ))==NULL) { puts(" Невозможно открыть файл" ); exit(); } flag = 'y'; while(flag! = 'n') { puts(" Введите имя" ); gets(name); fputs(name, fp); fputs(" \n", fp); printf(" Желаете ввести другое имя? " ); flag=getchar(); putchar('\n'); } fclose(fp); }

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

Если ваш компилятор может использовать функцию strlen(), можно несколько упростить процедуру ввода, используя следующие инструкции:

printf(" Пожалуйста, введите имя: " ); gets(name); while(strlen(name) > 0) { fputs(name, fp); fputs(" \n", fp); printf(" Пожалуйста, введите имя: " ); gets(name); }

Символы, которые вы набираете на клавиатуре, присваиваются строковой переменной name, а затем проверяется, не оказалась ли длина строки равной 0. Если на запрос сразу же нажать клавишу Enter, строка будет иметь нулевую длину и выполнение цикла прекратится. Если до нажатия Enter ввести хотя бы один символ, строка и код «новая строка» будут записаны на диск.

Некоторые компиляторы позволяют еще более упростить алгоритм ввода строки, например, так:

printf(" Пожалуйста, введите имя: " ); while(strlen(gets(name)) > 0) { fputs(name, fp); fputs(" \n", fp); printf(" Пожалуйста, введите имя: " ); }

где ввод строки выполняется внутри условия while.

Для того чтобы напечатать строку на принтере, вместо записи ее на диск используется имя файла " prn". Чтобы открыть файл, требуется указать:

if ((fp = fopen(" prn", " w" )) == NULL)

Для создания программы печати длина строки определяется равной 81 символу, чтобы строка могла уместиться во всю ширину экрана, прежде чем будет нажата клавиша Enter. В Листинге 2 приводится текст программы, которая демонстрирует, как можно написать простой текстовый процессор. Строка не посылается на принтер до тех пор, пока не нажата клавиша Enter, что позволяет с помощью клавиши Backspace корректировать ошибки ввода строки.

Листинг 2. Программа вывода строки на печатающее устройство.

/*wp.c*/#include " stdio.h" main() { FILE *fp; char line[81]; if ((fp = fopen(" prn", " w" )) == NULL) { puts(" Принтер не готов к работе" ); exit(); } puts(" Введите текст, после ввода каждой строки нажимайте Enter\n" ); puts(" Для прекращения ввода нажмите Enter в начале новой строки\n" ); gets(line); while (strlen(line) > 0) { fputs(line, fp); fputs(" \n", fp); gets(line); } fclose(fp); }

Чтение строк

Чтение строк из файла осуществляется с помощью функции fgets(). Синтаксис функции:

fgets(string_variable, lenght, file_pointer);

Функция вводит строку целиком до символа новой строки, если ее длина не превышает значения, указанного в параметре lenght минус один символ. Параметр lenght является целым числом либо целочисленной константой или переменной, указывающей максимально возможное количество символов в строке.

Ниже приведена программа, в которой осуществляется чтение имен из файла, созданного в предыдущем примере:

/*fgets.c" /#include " stdio.h" main() { FILE *fp; char name[12]; if ((fp = fopen(" MYFILE", " r" )) == NULL) { puts(" Невозможно открыть файл" ); exit(); } while(fgets(name, 12, fp)! = NULL) { printf(name); } fclose(fp); }

Ввод выполняется внутри цикла while до тех пор, пока значение читаемого символа не равно NULL. Как только указатель достигнет конца файла, строковой переменной присваивается значение NULL. При построчном чтении из файла для указания конца файла всегда используется NULL, а EOF используют при посимвольном чтении.

Если вы пишете программу, предназначенную для чтения любого текстового файла, указывайте значение аргумента lenght равным 80.

Кстати, обратите внимание, что функция printf() используется в этом примере для вывода содержимого строковой переменной без указателей формата. Каждая строка, читаемая из файла, включает код «новая строка», который был записан в файл в инструкции fputs(" \n", fp);, и никаких дополнительных кодов «новая строка» в параметры функции printf() включать не требуется.

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

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

fprintf(file_pointer, control_string, data_list); fscanf(file_pointer, control_string, data_list);

Программа, приведенная в Листинге 3, предназначена для ввода и записи в файл данных инвентарной описи. Первый ввод осуществляется с помощью функции gets() перед началом цикла while. Цикл повторяется, пока длина каждого вводимого имени составляет как минимум один символ. Выполнение цикла прекращается, когда вместо ввода значения имени происходит нажатие клавиши Enter.

Листинг 3. Форматированный вывод.

/*fprintf.c*/#include " stdio.h" main() { FILE *fp; char name[20]; int quantity; float cost; if ((fp = fopen(" MYFILE", " w" )) == NULL) { puts(" Невозможно открыть файл" ); exit(); } printf(" Введите наименование товара: " ); gets(name); while (strlen(name) > 0) { printf(" Введите цену товара: " ); scanf(" %f", & cost); printf(" Введите количество единиц товара: " ); scanf(" %d", & quantity); fprintf(fp, " %s %f %d\n", name, cost, quantity); printf(" Введите наименование товара: " ); gets(name); } fclose(fp); }

Обратите внимание, что в последней строке цикла происходит ввод следующего имени. Это позволяет прекратить повторение цикла простым нажатием клавиши Enter. Некоторые начинающие программисты, вероятно, написали бы этот цикл таким образом:

do { printf(" Введите наименование товара: " ); gets(name); printf(" Введите цену: " ); scanf(" %f", & cost); printf(" Введите количество единиц товара: " ); scanf(" %d", & quantity); fprintf(fp, " %s %f %d\n", name, cost, quantity); }while (strlen(name) > 0);

и эта программа работала бы столь же успешно, не считая того, что для окончания цикла требовалось бы нажать клавишу Enter трижды: первый раз при вводе названия и еще два раза в ответ на просьбу ввести цену и количество товара.

Внутри цикла while данные о цене и количестве каждого наименования товара вводятся с использованием функции scanf(), а затем записываются на диск с помощью инструкции

fprintf(fp, " %s %f %d\n", name, cost, quantity);

Обратите внимание, что код «новая строка» записывается в файл в конце каждой строки. Если просмотреть содержимое файла с помощью команды TYPE операционной системы MS-DOS, то каждая строка инвентарной описи и на экране будет начинаться с новой строки:

дискеты 1.120000 100лента 7.340000 150картридж 75.000000 3

Если бы код «новая строка» не был записан на диск, текст выводился бы подряд, в одну строку на экране, и выглядел примерно так:

дискеты 1.120000 100лента 7.340000 150картридж 75.000000 3

Заметьте, что при этом отсутствует пробел между числом, показывающим количество единиц одного товара, и наименованием следующего. Даже при таком способе записи можно без проблем осуществлять чтение из этого файла, так как компилятор в состоянии различить конец числового значения и начало строки, но что произойдет, если последним значением для каждого наименования товара окажется строка с названием фирмы-производителя? Информация в файле будет выглядеть примерно таким образом:

дискеты 1.120000 Memoryexлента 7.340000 Okaydataкартридж 75.000000 HP

и тогда при чтении данных из файла программа присоединит начало данных о следующем товаре к концу описания предыдущего. Например, данные о первом наименовании товара при этом выглядели бы так:

дискеты 1.120000 Memoryexлента

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


Поделиться:



Популярное:

Последнее изменение этой страницы: 2017-03-08; Просмотров: 1168; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.022 с.)
Главная | Случайная страница | Обратная связь