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

ЛЕКЦИЯ: ВВОД-ВЫВОД

Ввод-вывод в языке с

Большинство популярных языков программирования высокого уровня имеет довольно ограниченные средства ввода-вывода. В результате программистам часто приходится разрабатывать изощренные алгоритмы, чтобы добиться необходимых результатов при вводе или выводе данных. К счастью, это не относится к языку С, который снабжен мощной подсистемой ввода-вывода, представленной обширной библиотекой соответствующих функций, хотя исторически эта подсистема не была частью языка. Как бы то ни было, те программисты, которые привыкли в языке Pascal использовать только два оператора — readln и writeln, — будут поражены обилием функций ввода-вывода в языке С.

Стандартные библиотечные функции ввода-вывода языка С позволяют считывать и записывать данные, связанные с файлами и различными устройствами. В то же время в самом языке С не предусмотрены какие-то предопределенные структуры файлов. Любые данные рассматриваются как цепочка байтов. В целом же все функции ввода-вывода можно разделить на три основные категории: потоковые, консольные и низкоуровневые.

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

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

Потоковые функции обеспечивают возможность буферного, форматного и неформатного ввода-вывода. Буферные потоки позволяют временно сохранять данные в буфере как при записи данных в поток, так и при чтении их из потока. Поскольку прямая запись на диск и считывание с диска требуют много времени, использование в этих целях буферной области памяти значительно ускоряет процесс. Обмен данными потоковые функции всегда осуществляют не символ за символом, а целыми блоками. Если приложению необходимо прочесть блок информации, оно обращается прежде всего к буферу как к наиболее доступной области памяти. Если буфер оказывается пустым, то запрашивается очередной блок данных с диска. Обратный процесс происходит во время буферизованного вывода данных. Вместо того чтобы посылать устройству вывода всю информацию сразу, выводимые данные сначала записываются в буфер. Когда буфер оказывается заполненным, данные "выталкиваются" из него.

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

Решение проблемы состоит в использовании специальных функций, которые "выталкивают" данные из буфера. В отличие от других языков высокого уровня, в С предусмотрена автоматическая выгрузка данных из буфера при завершении работы программы. Хотя, конечно, профессионально написанное приложение не должно полагаться на автоматическое решение этой проблемы: всегда следует явно указывать всю последовательность действий, которую должна выполнить программа для предотвращения потери данных. Еще одно замечание: если используются потоковые функции, то в случае аварийного завершения программы вся информация, хранящаяся в выходном буфере, может быть утеряна.

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

Последняя категория функций — низкоуровневые. Ни одна из них нe осуществляет промежуточной записи данных в буфер и какого бы то ни было форматирования. Все они напрямую используют системные средства ввода-вывода, открывая доступ к файлам и периферийным устройствам на более низком уровне, чем потоковые функции. При открытии файла с помощью низкоуровневых функций возвращается его дескриптор, который представляет собой целое число, употребляемое в дальнейших операциях в качестве идентификатора файла.

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

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