Функции и переключение ввода-вывода

Функции и переключение ввода-вывода

В данном разделе мы рассмотрим функции, применяемые при вводе и выводе. Кроме того, мы коснемся других аспектов этого понятия. Под функциями ввода-вывода подразумеваются функции, которые выполняют транспортировку данных в программу и из нее. Мы уже использовали две такие функции: printf( ) и scanf( ) . Теперь рассмотрим несколько других возможностей, предоставляемых языком Си .

Функции ввода-вывода не входят в определение языка Си . Их разработка возложена на программистов, реализующих компилятор с языка Си . С другой стороны, выгода использования стандартного набора функций ввода-вывода на всех системах очевидна. Это дает возможность писать переносимые программы, которые легко можно применять на разных машинах. В языке Си имеется много функций ввода-вывода такого типа, например printf( ) и scanf( ) . Ниже мы рассмотрим функции getchar( ) и putchar( ) .

Эти две функции осуществляют ввод и вывод одного символа при каждом обращении к ним. Этот способ ввода данных лучше соответствует возможностям машины. Более того, такой подход служит основой построения большинства программ обработки текстов, являющихся последовательностями обычных слов. Мы увидим, как можно применять эти функции в программах, занимающихся подсчетом символов, чтением и копированием файлов . Узнаем про буферы , эхо-печать и переключение ввода-вывода.

Функция getchar( ) получает один символ, поступающий с пульта терминала, и передает его выполняющейся в данный момент программе. Функция putchar( ) получает один символ, поступающий из программы, и пересылает его для вывода на экран. Рассмотрим пример программы, которая принимает один символ с клавиатуры, и выводит его на экран:

Для большинства систем спецификации функции getchar и putchar содержатся в файле stdio.h , поэтому мы указали данный файл в программе. Функция getchar( ) аргументов не имеет, т.е. при ее вызове в круглые скобки не помещается никакая величина. Она просто получает очередной поступающий символ, и сама возвращает его значение выполняемой программе. Оператор, приведенный в строке 1, присваивает значение функции getchar( ) переменной ch . Функция putchar( ) имеет один аргумент . При ее вызове необходимо в скобках указать символ, который требуется вывести на печать . Аргументом может быть одиночный символ (включая знаки, представляемые управляющими последовательностями), переменная или функция , значением которой является одиночный символ. Правильным обращением к функции putchar( ) является указание любого из этих аргументов при ее вызове:

Модифицируем нашу программу:

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

Буферы

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

Зачем нужны буферы ? Во-первых, оказывается, что передачу нескольких символов в виде одного блока можно осуществить гораздо быстрее, чем передавать их последовательно по одному. Во-вторых, если при вводе символов допущена ошибка, мы сможем воспользоваться корректирующими средствами терминала, чтобы ее исправить. И когда мы нажмем клавишу Enter , будет произведена передача откорректированной строки. Однако, для некоторых диалоговых программ небуферизованный ввод может оказаться приемлемым. Например, в программах обработки текстов было бы желательно, чтобы каждая команда вводилась, как только мы нажимаем соответствующую клавишу. Поэтому как буферизованный , так и небуферизованный ввод имеет свои достоинства.

Рассмотрим вывод на печать групп символов. Желательно, чтобы в любой момент можно было остановить работу программы. Для этого напишем программу так, чтобы она прекращала работу при получении какого-нибудь специального символа, например "!":

В данном примере при первом прохождении тела цикла функция putchar( ) получает значение своего аргумента в результате выполнения оператора, расположенного в строке 9. В дальнейшем, вплоть до завершения работы цикла , значением этого аргумента является символ, передаваемый программе функцией getchar , расположенной в строке 12. Цикл while будет осуществлять чтение и печать символов до тех пор, пока не поступит признак STOP .

Одна строка 8 этой программы заменяет строки 9, 10, 12 предыдущей программы.

📎📎📎📎📎📎📎📎📎📎