|
Программирование >> Процедурные приложения
Потоки stdin, stdout и stdprn буферизуются по умолчанию: данные из них извлекаются, как только буфер переполняется. Потоки stderr и stdaux не буферизуются, если только они не используются в функциях семейств printf() и scanf(): в этих случаях им назначается временный буфер. Буферизацию потоков stderr и stdaux также можно осуществлять с помощью функций setbuf() и setvbuf(). Следует отметить, что системные буферы недоступны для пользователей, но буферы, создаваемые функциями setbuf() и setvbuf(), являются именованными и могут модифицироваться наподобие переменных. Именованные буферы удобно использовать для того, чтобы проконтролировать вводимые или выводимые данные, прежде чем они будут переданы системным функциям и смогут вызвать появление сообщений об ошибках. Размер создаваемого буфера может быть произвольным. При использовании функции setbuf() размер буфера неявно задается константой BUFSIZ, объявленной в файле STDIO.H. Синтаксис функции выглядит следующим образом: void setbuf(FILE *имя потока, char *имя буфера) ; В следующей программе с помощью данной функции потоку stderr назначается буфер. * setbuf. с * Эта программа на языке С демонстрирует, как назначить * буфер небуферизованному потоку stderr. #include <stdio.h> char cmyoutputbuffer[BUFSIZ]; void main(void) /* Назначение буфера небуферизованному потоку stderr*/ setbuf(stderr, cmyoutputbuffer); /* попробуйте превратить эту строку в комментарий*/ /* Вставка данных в выходной поток */ fputs( Строка данных\n , stderr); fputs( вставляется в выходной буфер.\n ,stderr); /* Выталкивание буфера потока на экран */ fflush(stderr); } Запустите программу в режиме отладки, и вы увидите, что выводимые строки появятся на экране только после выполнения последней строки, когда содержимое буфера принудительно выталкивается . Если заключить строку с вызовом функции setbuf() в символы комментария и снова запустить программу в отладчике, то данные, записываемые в поток stderr, не будут буферизоваться, и тогда результат выполнения каждой функции fputs() будет появляться на экране немедленно. В приводимой ниже программе используется функция setvbuf(),синтаксис которой таков: int setvbuf(FILE *имя потока, char *имя буфера, int тип буфера, size t размер буфера) ; С помощью этой функции размер буфера задается явно, что демонстрируется в следующей программе. * setvbuf. с * Эта программа на языке С демонстрирует использование функции Setvbuf() . */ #include <stdio.h> #define MYBUFSIZE 512 void main(void) { char ichar, cmybuffer[MYBUFSIZE]; FILE *pfinfile, <<pfoutfile; pfinfile = fopen( sample.in , r ); pfoutfile = fopen( sample.out , w ); if(setvbuf(pfinfile, cmybuffer, IOFBF, MYBUFSIZE) != 0) printf( Ошибка выделения буфера для потока pfinfile.\n ); else printf( Буфер потока pfinfile создан.\n ); if(setvbuf(pfoutfile, NULL, IONBF, 0) != 0) printf( Ошибка выделения буфера для потока pfoutfile.\n ) ; else printf( Поток pfoutfileне имеет буфера.\n ); while (fscanf (pfinfile, %c , &ichar,) != EOF) fprintf(pfoutfile, %c ,ichar); fclose(pfinfile); f close (pfoutfile); Программа создает именованный буфер для потока pfinfile и запрещает буферизацию потока pfoutfile. В первом случае указан тип буфера 10РВр(полная буферизация). Если при этом не задать имя буфера, он будет создан автоматически в динамической памяти и так же автоматически удален по завершении работы программы. Во втором случае указан тип ionbf(нет буфера). В такой ситуации имя буфера и его размер, даже если они заданы, игнорируются. Закрытие файлов и потоков Функция fclose () закрывает указанный файл, тогда как функция fcloseall() закрывает сразу все открытые потоки, кроме стандартных: stdin, stdout, stderr, stdprn и stdaux. Если в программе явно не закрыть поток, он все равно будет автоматически закрыт по завершении программы. Поскольку одновременно можно открыть только ограниченное число потоков, следует своевременно закрывать те из них, которые больше не нужны. Низкоуровневый ввод-вывод При низкоуровневом вводе-выводе не происходит ни буферизации, ни форматирования данных. Файлы, открытые на низком уровне, представляются в программе дескрипторами - целочисленными значениями, которые операционная система использует в качестве ссылок на файлы. Для открытия файла предназначена функция ореn (). Чтобы открыть файл в режиме совместного доступа, следует воспользоваться функцией sopen(). В табл. 10.1 перечислены наиболее часто употребляемые в приложениях функции ввода-вывода низкого уровня. Все они объявлены в файле I0.H. Данная подсистема ввода-вывода, ориентированная на работу с дисковыми файлами, изначально была создана для операционной системы UNIX. Поскольку комитет ANSI С отказался стандартизировать ее, мы не рекомендуем применять эти функции. В новых проектах предпочтительнее работать со стандартными потоковыми функциями, которые детально рассматриваются в этой главе.
Ввод-вывод символов В стандарте ANSI С описан ряд функций, предназначенных для ввода-вывода символов и входящих в стандартный комплект поставки всех компиляторов языка С. Таков общий принцип С: реализовывать ввод-вывод посредством внешних библиотечных функций, а не ключевых слов, являющихся частью языка. Функции getc( ), putc( ), fgetc( ) и fputc( ) Функция getc() читает один символ из указанного файлового потока: int ic; ic = getc(stdin); Вас может удивить, почему переменная ic не объявлена как char. Дело в том, что в прототипе функции getc() указано, что она возвращает значения типа int. Это связано с необходимостью обрабатывать также признак конца файла, который не может быть сохранен в обычной переменной типа char. Функция getc() преобразовывает читаемый символ из типа char в тип unsigned char и только затем - в int. Такой способ обработки данных гарантирует, что символы с ASCII-кодами больше 127 не будут представлены отрицательными числами. Это позволяет зарезервировать отрицательные значения для нестандартных ситуаций - признаков ошибок или конца файла. Так, например, признаком конца файла традиционно служит значение -1. Правда, стандарт ANSI С гарантирует лишь то, что константа EOF содержит некое отрицательное значение. Хотя может показаться странным, что функция, предназначенная для ввода символов, возвращает целые числа, в действительности язык С не делает больших различий между типами charи int. Существует четкий алгоритм преобразования целых чисел в символы и наоборот. Функция getc() читает данные из буфера. Это означает, что управление не будет обратно передано программе до тех пор, пока в указанном потоке не встретится символ новой строки. Функция возвращает только самый первый из обнаруженных ею в буфере символов, другие остаются невостребованными. Таким образом, функцию getc() нельзя использовать для последовательного ввода символов с клавиатур ры, не нажимая при этом каждый раз клавишу [Enter]. Функция putc(} записывает символ в файловый поток, представленный указателем файла. Например, чтобы отобразить тот символ, который был введен в предыдущем примере, задайте такую строку: putc(ic, stdout); Особенность функций семейства putc() состоит в том, что они возвращают константу eof(обычно она обозначает конец файла) всякий раз при возникновении ошибочных ситуаций. Это может вызвать некоторые недоразумения, хотя, с технической точки зрения, следующий фрагмент совершенно корректен: if(putc (ic,stdout) == EOF) printf( Обнаружена ошибка записи в stdout ); И последнее замечание: функции getc() и putc() реализованы и как макросы, и как функции. Макроверсии имеют более высокий приоритет и выполняются в первую очередь. Чтобы изменить такой порядок, следует с помощью директивы препроцессора #undef отменить определение макроса: #undef getc Существуют чистые функции fgetc () и fputc (), которые выполняют аналогичные действия, но не имеют макросов- двойников . Функции getchar( ), putchar( ), fgetchar( ) n fputchar() Функции getchar() и putchar() являются модификациями рассмотренных выше функций getc() и putc(), работающими только cо стандартными потоками ввода (stdin) и вывода (stdout). Рассмотренные в предыдущем параграфе примеры могут быть переписаны с использованием функций getchar() и putchar() следующим образом: int ic;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |