Простейший ввод-вывод. Функции посимвольного и построчного ввода-вывода

Автор работы: Пользователь скрыл имя, 06 Апреля 2013 в 15:24, лабораторная работа

Краткое описание

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

Содержимое работы - 1 файл

Простейший ввод-вывод.Ф-ии посимвольного и построчного ввода-вывода.doc

— 61.50 Кб (Скачать файл)

Простейший ввод-вывод. Функции посимвольного и построчного ввода-вывода.

 

 

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

 

Функции посимвольного ввода-вывода.

Функции этой группы осуществляют ввод-вывод отдельных символов. Обычно символы вводятся с клавиатуры, а выводятся на экран монитора.

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

Следует отметить, что символ, генерируемый при нажатии на клавишу Enter, также заносится в буфер ввода как символ перехода на новую строку (’\n’). Функция getchar передает его в программу, как и любой другой символ. При необходимости впоследствии его можно обработать требуемым образом.

Функция getchar возвращает целое число, представляющее собой код очередного символа, взятого из буфера ввода. Это значение для дальнейшей обработки следует обязательно записывать в переменную целого типа (int), не смотря на то, что существуют специальные данные символьного типа (char). Это объясняется необходимостью хранения и обработки кода символа, вырабатываемого функцией getchar при достижении конца входного потока. Очевидно, этот код не должен совпадать с кодом какого-либо реального символа, и поэтому по размеру он больше размера данных типа char. Реальная числовая величина этого коду в разных системах программирования на Си может быть разной. Согласно стандарту языка Си, эта величина задается в виде именованной константы EOF, которая определяется с помощью команды препроцессора #define в заголовочном файле stdio.h. Следует обратить внимание на ошибку, которую иногда делают, пытаясь занести во входной поток с клавиатуры признак его конца путем последовательного ввода букв E, O и F. В этом случае во входной поток так и попадут коды указанных букв. Способ ввода признака конца входного потока зависит от системы программирования на Си. Например, в системе ВС3.1 для этого достаточно последовательно нажать клавиши F6 и Enter. Более универсальный способ – использование комбинации клавиш Ctrl^Z и Enter.

Пример вызова функции getchar:

int c;   // Описание используемой переменной.

   c= getchar(); // Собственно вызов функции getchar.

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

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

putchar(’a’)  -  выводится на экран монитора символ а,

putchar(a)   -  выводится на экран монитора символ, код которого записан в             переменной а,

putchar(67)  -  выводится на экран монитора символ, код которого равен 67.

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

 

# include <stdio.h>

 

int main(void)

{

int c;

 

c=getchar();

putchar(c);

putchar(getchar());

putchar(getchar());

return 0;

}

 

Данная программа берет  из входного потока первые три символа  и выводит их на экран монитора. На первый взгляд, странными кажутся операторы вида: putchar(getchar()), хотя для языка Си такие конструкции вполне обычны. Здесь сначала вызывается функция getchar, которая возвращает в точку вызова код очередного символа входного потока. Т.к. вызов этой функции записан в качестве параметра функции putchar, то это возвращаемое значение напрямую будет передано в функцию putchar. Т.о., один оператор выполнит сразу два действия: ввод и вывод символа входного потока. Однако, так можно поступать только тогда, когда введенный символ в дальнейшем будет не нужен. Если это не так, то подходит первая пара операторов, где введенный символ сохраняется в переменной с и может быть использован в дальнейшем. (В нашем случае эту пару операторов вполне можно было бы заменить конструкцией putchar(getchar()), т.к. после вывода переменная с нигде не используется).

Приведенная программа, хоть и вполне рабочая, показывает, как не надо писать программы. Здесь видно, что писавший её, совсем не думал о будущем пользователе своей программы, которым в начале, скорее всего, окажется он сам. Если после компиляции и компоновки такую программу запустить на выполнение, то появится черный экран и мигающий внизу слева курсор. Что при этом должен делать сидящий перед компьютером человек, совершенно не понятно. Опыт показывает, что в такой ситуации начинают хаотично нажимать на любые клавиши и чаще всего на клавишу Enter. Не трудно убедиться, что трех нажатий на эту клавишу окажется достаточно, чтобы программа завершилась, хотя мало кто с первого раза правильно может объяснить полученный при этом результат. Всё окажется ещё хуже, если подобным образом написать программу, предлагаемую Б. Керниганом и Д. Ритчи (см. стр. 30-32). Тут пользователя может ожидать лёгкая паника: на первый взгляд, кажется, что эту программу вообще никак не завершить! Всё станет намного проще, если приведенную выше программу переписать, используя знания, полученные при рассмотрении простейшей программы, следующим образом:

# include <stdio.h>

 

int main(void)

{

int c;

 

puts(”\n Введите несколько символов:”);

c=getchar();

putchar(c);

putchar(getchar());

putchar(getchar());

return 0;

}

 

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

В языке Си есть ещё  две полезные функции посимвольного ввода. Хотя они и не входят в стандарт языка Си, их можно встретить практически во всех системах программирования на Си. Речь идет о функциях getch и getche. Это функции прямого ввода, не использующие при работе буфер ввода. Они также возвращают в программу код, соответствующий нажатой клавише. (Нажатие на некоторые клавиши или их комбинации типа Shift+, Ctrl+, Alt+, приводит к выработке и передачу в программу кода, состоящего из двух чисел). Этот код передается в программу немедленно после нажатия на клавишу. При работе функции getch символ, соответствующий нажатой клавише, на экране не отображается. Если необходимо отобразить на экране символ, соответствующий нажатой клавише, используют функцию getchе (е на конце - от англ. слова echo). Использование функции getch позволяет обработать реакцию на нажатие на любые клавиши и их комбинации, что широко используется в программировании.

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

Прототипы функций getch и getchе находятся в заголовочном файле conio.h.

 

Упражнение 1.

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

Упражнение 2.

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

 

Функции построчного ввода-вывода.

Функции этой группы осуществляют ввод-вывод символьных строк. Как и раньше данные обычно вводятся с клавиатуры, а выводятся на экран монитора.

Для ввода символьных строк служит функция gets. Данная функция является функцией буферизованного ввода. При вызове функции gets всё содержимое буфера ввода, включая пробелы и символы горизонтальной табуляции, передается в программу, и тем самым буфер ввода полностью очищается. Максимальная длина строки, которую можно ввести за один вызов функции gets, определяется размером буфера ввода, который, в свою очередь, зависит от системы программирования. Так в ВС 3.1 это 128 символов. В функцию gets передаётся только один параметр - символьный массив, в который и записывается вводимая символьная строка. Разговор о массивах ещё впереди. Здесь же следует заметить, что размер массива, передаваемого в функцию gets, должен быть достаточным, чтобы вместить самую длинную строку, которую только можно ввести. Выполнение данного требования компилятор не контролирует, однако ввод строки длиннее, чем размер массива, предназначенного для её хранения, есть ошибка, которая может привести к непредсказуемому поведению программы во время её выполнения. Самое неприятное здесь то, что простые программы обычно при такой ошибке выполняются совершенно нормально, что создаёт иллюзию корректности программы.

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

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

Если функция gets ввела хотя бы один символ, то она возвращает указатель на первый символ результирующей символьной строки. При записи символьной строки в символьный массив это адрес этого массива. Если функция gets обрабатывала только признак конца входного потока, то она возвращает именованную константу NULL. Эта константа, как  и константа EOF, определяется в заголовочном файле stdio.h.

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

Функция puts имеет возвращаемое значение, которое обычно не используется.

В заключение, приведём пример программы, иллюстрирующей работу функций построчного ввода-вывода.

# include <stdio.h>

# define MAX_DL_STR  128

 

int main(void)

{

char str[MAX_DL_STR];        // Так описывается символьный массив

 

puts(”\n Введите несколько символов:”);

gets(str);

puts(”\n Введённая символьная строка:”);

puts(str);

return 0;

}


Информация о работе Простейший ввод-вывод. Функции посимвольного и построчного ввода-вывода