![](/user_photo/_userpic.png)
книги / Программирование на языке Си
..pdf332 |
Программирование на языке Си |
Функция getchar( ) осуществляет ввод одного символа. При обращении она возвращает в вызвавшую ее функцию один вве денный символ.
Функция putchar() выводит в стандартный поток один сим вол, при этом также возвращает в вызвавшую ее функцию толь ко что выведенный символ.
Обратите внимание на то, что функция getchar() вводит оче редной байт информации (символ) в виде значения типа int. Это сделано для того, чтобы гарантировать успешность распознава ния ситуации "достигнут конец файла". Дело в том, что при чтении из файла с помощью функции getchar() может быть достигнут конец файла. В этом случае операционная система в ответ на попытку чтения символа передает функции getchar() значение EOF (End of File). Константа EOF определена в заго ловочном файле stdio.h и в разных операционных системах имеет значение 0 или -1. Таким образом, функция getchar() должна иметь возможность прочитать из входного потока не только символ, но и целое значение. Именно с этой целью функция getchar() всегда возвращает значение типа int.
Применение в программах константы EOF вместо конкрет ных целых значений, возвращаемых при достижении конца файла, делает программу мобильной (не зависимой от конкрет ной операционной системы).
В случае ошибки при вводе функция getchar() также воз вращает EOF.
Строго говоря, функции getchar() и putchar() функциями не являются, а представляют собой макросы, определенные в заго ловочном файле stdio.h следующим образом:
#define |
getcharО |
getc(stdin) |
#define |
putchar(c) |
putc ((c), stdout) |
Здесь переменная с определена как int с.
Функции getc() и putc( ), с помощью которых определены функции getchar( ) и putchar(), имеют следующие прототипы;
int getc (FILE |
‘ stream); |
int putc (int c, |
FILE ‘ stream); |
Глава 7. Ввод и вывод |
333 |
Указатели на поток, задаваемые в этих функциях в качестве параметра, при определении макросов getchar() и putchar() имеют соответственно предопределенные значения stdin (стан дартный ввод) и stdout (стандартный вывод).
Интересно отметить, что функции getc() и putc(), в свою очередь, также реализуются как макросы. Соответствующие строки легко найти в заголовочном файле stdio.h.
Не разбирая подробно эти макросы, заметим, что вызов биб лиотечной функции getc( ) приводит к чтению очередного байта информации из стандартного ввода с помощью системной функции (ее имя зависит от операционной системы) лишь в том случае, если буфер операционной системы окажется пустым. Если буфер не пуст, то в программу пользователя будет передан очередной символ из буфера. Это необходимо учитывать при работе с программой, которая использует функцию getchar() для ввода символов.
При наборе текста на клавиатуре коды символов записыва ются во внутренний буфер операционной системы, Одновре менно они отображаются (для визуального контроля) на экране дисплея. Набранные на клавиатуре символы можно редактиро вать (удалять и набирать новые). Фактический перенос симво лов из внутреннего буфера в программу происходит при нажа тии клавиши <Enter>. При этом код клавиши <Enter> также за носится во внутренний буфер. Таким образом, при нажатии на клавишу 'А' и клавишу <Enter> (завершение ввода) во внутрен нем буфере оказываются: код символа 'А' и код клавиши <Enter>.
Об этом необходимо помнить, если вы рассчитываете на ввод функцией getchar() одиночного символа.
Приведем фрагмент программы, в которой функция getchar(.) используется для временной приостановки работы программы с целью анализа промежуточных значений контро лируемых переменных.
#±nclude <stdio.h> int main ()
{
printf("a");
334 |
|
|
Программирование на языке Си |
getchar(); |
/* |
#1 |
*/ |
printf("b"); |
/* |
#2 |
*/ |
getcharO ; |
|||
printf("c"); |
|
|
|
return 0; |
|
|
|
Сначала на экран выводится символ 'а', и работа программы приостанавливается до ввода очередного (в данном случае - любого) символа. Если, как это делается обычно, нажать, на пример, клавишу <q> и затем клавишу <Enter> (для завершения ввода), то на следующей строке появятся символы Ьс, и про грамма завершит свою работу. Первая (в программе) функция getchar() (#1) прочитала из внутреннего буфера код символа 'q', и следующая за ней функция printf( ) вывела на экран символ Ъ'. Остановки работы программы не произошло, потому что вторая функция getchar() (#2) прочитала код клавиши <Enter> из внутреннего буфера, а не очередной символ с клавиатуры. Произошло это потому, что к моменту вызова функции getchar( ) внутренний буфер не был пуст.
Приведенная программа будет работать правильно, если в момент остановки программы нажимать только клавишу <Enter>.
Функция putchar() служит для вывода на устройство стан дартного вывода одного символа, заданного в качестве парамет ра. Ниже приведены примеры задания выводимого символа:
int с;
1с = getchar( );
2putchar(c);
3 putchar('А');
4putchar('\007');
5putchar('\t');
Встроке 2 фрагмента программы на экран дисплея выводит ся символ, введенный в предыдущей строке функцией getchar( ). В строке 3 выводится символ 'А', в строке 4 выводит
ся управляющий символ, заданный кодом 007 (звуковой сиг нал). В последней строке выводится неотображаемый (управ-
Глава 7. Ввод и вывод |
335 |
ляющий) символ табуляции, перемещающий курсор в следую щую позицию табуляции. Обычно эти позиции задаются сле дующим числовым рядом: 1,9,17,25...
Приведем в качестве примера применения функций getchar() и putchar() программу копирования данных из стан дартного ввода в стандартный вывод, которую можно найти практически в любом пособии по программированию на Си:
#include <stdio.h> int main()
{
int c;
while ((c = getchar()) != EOF) putchar(c) ;
return 0;
}
Эта же программа с использованием функций getc() и putc() будет выглядеть так:
♦include <stdio.h> int main ()
{
int с ;
while ((с = getc(stdin)) != EOF) putc(c, stdout);
return 0;
}
Для завершения приведенной выше программы копирования необходимо ввести с клавиатуры сигнал прерывания Ctrl+C (одновременно нажать клавиши <Ctrl> и <С>).
В [1, §1.5] приведены примеры использования функций getchar() и putchar() для подсчета во входном потоке числа отдельных введенных символов, строк и слов.
Ввод-вывод строк. Одной из наиболее популярных опера ций ввода-вывода является операция ввода-вывода строки сим волов. В библиотеку языка Си для обмена данными через стандартные потоки ввода-вывода включены функции вводавывода строк gets() и puts(),' которые удобно использовать при
336 |
Программирование на языке Си |
создании диалоговых систем. Прототипы этих функций имеют следующий вид:
char * gets (char * s); |
/* Функция ввода *1 |
int puts (char * s); |
/* Функция вывода */ |
Обе функции имеют только один аргумент - указатель s на массив символов. Если строка прочитана удачно, функция gets( ) возвращает адрес того массива s, в который производился ввод строки. Если произошла ошибка, то возвращается NULL.
Функция puts() в случае успешного завершения возвращает последний выведенный символ, который всегда является сим волом V . Если произошла ошибка, то возвращается EOF.
Приведем простейший пример использования этих функций.
# i n c l u d e < s t d i o . h >
c h a r |
s t r l [ ] = " В в е д и т е ф амилию с о т р у д н и к а : " ; |
i n t |
m a in () |
{
char name[80]; puts(strl); gets(name); return 0;
}
Напомним, что любая строка символов в языке Си должна заканчиваться нуль-символом 'W. В последний элемент массива strl нуль-символ будет записан автоматически во время транс ляции при инициализации массива. Для функции puts() нали чие нуль-символа в конце строки является обязательным. В противном случае, т.е. при отсутствии в символьном массиве символа 'W, программа может завершиться аварийно, так как функция puts() в поисках нуль-символа будет перебирать всю доступную память байт за байтом, начиная в нашем примере с адреса strl. Об этом необходимо помнить, если в программе происходит формирование строки для вывода ее на экран дис плея. Функция gets( ) завершает свою работу при вводе символа 'Vn', .который автоматически передается от клавиатуры в ЭВМ при нажатии на клавишу <Enter>. При этом сам символ '\п' во
Ввод и вывод |
337 |
вводимую строку не записывается. Вместо него в строку поме щается нуль-символ '\0'. Таким образом, функция gets() произ водит ввод "правильной" строки, а не просто последователь ности символов.
Здесь следует обратить внимание на следующую особен ность ввода данных с клавиатуры. Функция gets() начинает об работку информации от клавиатуры только после нажатия клавиши <Enter>. Таким образом, она "ожидает", пока не будет набрана нужная информация и нажата клавиша <Enter>. Только после этого начинается ввод данных в программу.
Форматный ввод-вывод. В состав стандартной библиотеки языка Си включены функции форматного ввода-вывода. Ис пользование таких функций позволяет создавать программы, способные обрабатывать данные в заданном формате, а также осуществлять элементарный синтаксический анализ вводимой информации уже на этапе ее чтения. Функции форматного вво да-вывода предназначены для ввода-вывода отдельных симво лов, строк, целых восьмеричных, шестнадцатеричных, десятичных чисел и вещественных чисел всех типов.
Для работы со стандартными потоками в режиме форматного ввода-вывода определены две функции:
printf() - форматный вывод; scanf() - форматный ввод.
Форматный вывод в стандартный выходной поток. Про тотип функции printf( ) имеет вид:
int printf(const char *format,...);
При обращении к функции printf() возможны две формы за дания первого параметра:
int printf ( форматная строка, список аргументов)', int printf ( указатель на форматную строку,
списокаргументов)',
В обоих случаях функция printfQ преобразует данные из внутреннего представления в символьный вид в соответствии с
2 2 “3124
338 |
Программирование на языке Си |
форматной строкой и выводит их в выходной поток. Данные, которые преобразуются и выводятся, задаются как аргументы функции printf().
Возвращаемое значение функции printf() - число напеча танных символов; а в случае ошибки - отрицательное число.
Форматнаястрока ограничена двойными кавычками и мо жет включать произвольный текст, управляющие символы и спецификации преобразования данных. Текст и управляющие символы из форматной строки просто копируются в выходной поток. Форматная строка обычно размещается в списке факти ческих параметров функции, что соответствует первому вариан ту вызова функции printf(). Второй вариант предполагает, что первый фактический параметр - это указатель типа char *, а сама форматная строка определена в программе как обычная строковая константа или переменная.
В список аргументов функции printf() включают выраже ния, значения которых должны быть выведены из программы. Частные случаи этих выражений - переменные и константы. Количество аргументов и их типы должны соответствовать по следовательности спецификаций преобразования в форматной строке. Для каждого аргумента должна быть указана точно одна
спецификация преобразования.
Если аргументов недостаточно для данной форматной стро ки, то результат зависит от реализации (от операционной систе мы и от системы программирования). Если аргументов больше, чем указано в форматной строке, "лишние" аргументы игнори руются. Гарантируется, что при любом количестве параметров и любом их типе после выполнения функции printf() дальнейшее выполнение программы будет корректным.
Списокаргументов (с предшествующей запятой) может от сутствовать,
Спецификация преобразования имеет следующую форму:
% флаги ширина_поля.точностъ модификатор спецификатор
. Символ % является признаком спецификации преобразова ния. В спецификации преобразования обязательными являются только два элемента: признак % и спецификатор.
Глава 7. Ввод и вывод |
339 |
Спецификация преобразования не должна содержать внутри себя пробелов. Каждый элемент спецификации является оди ночным символом или числом.
Предупреждение. Спецификации преобразований должны соответствовать типу указанных аргументов. При несовпаде нии не будет выдано сообщений об ошибках во время ком пиляции или выполнения программы, но в выводе результатов выполнения программы может содержаться "мусор".
Начнем рассмотрение составных элементов спецификации преобразования с обязательного элемента - спецификатора, который определяет, как будет интерпретироваться соответст вующий аргумент: как символ, как строка или как число (табл. 7.1).
Таблица 7 . 1
Спецификаторы форматной строки для функции форматного вывода
Спе Тип цифи аргумента катор
dint, char, unsigned
1int, char, unsigned
Uint, char, unsigned
Оint, char, unsigned
Xint, char, unsigned
Xint, char, unsigned
гdouble,- float
Формат вывода
Десятичное целое со знаком
Десятичное целое со знаком
Десятичное целое без знака
Восьмеричное целое без знака
Шестнадцатеричное целое без знака; при выводе ис пользуются символы "0...9а...Г Шестнадцатеричное целое без знака; при выводе ис пользуются символы "0...9A...F
Вещественное значение со знаком в виде:
3 H a K _ u u c a a d d d d .d d d d ,
где dddd - одна йли более десятичных цифр. Количе ство цифр перед десятичной точкой зависит от вели чины выводимого числа, а количество цифр после десятичной точки зависит от требуемой точности. З н а к _ ч и с л а при отсутствии модификатора '+' изобра жается только для отрицательного числа
22’
340 |
Программирование на языке Си |
|
|
П р о д о л ж е н и е |
|
Спе |
Тип |
Формат вывода |
|
цифи |
|||
аргумента |
|||
|
|||
катор |
|
|
|
е |
double, |
Вещественное значение в виде: |
|
|
float |
знакчнслат.ббббезнакххх, |
|
|
|
где m.dddd - изображение мантиссы числа; |
|
|
|
m - одна десятичная цифра; |
|
|
|
dddd - последовательность десятичных цифр; |
|
|
|
е - признак порядка; |
|
|
|
з н а к - знак порядка; |
|
|
|
ххх - десятичные цифры для представления поряд |
|
|
|
ка числа; |
|
|
|
з н а к ч и с л а при отсутствии модификатора '+' изо |
|
|
|
бражается только для отрицательного числа |
Еdouble, Идентичен спецификатору "е", за исключением того,
float
gdouble, float
что признаком порядка служит "Е"
Вещественное значение со знаком печатается в форма те спецификаторов "Г или "е" в зависимости от того, какой из них более компактен для данного значения и точности. Формат спецификатора "е" используется то-
. гда, когда значение показателя меньше -4 или больше заданной точности. Конечные нули отбрасываются, а десятичная точка появляется, если за ней следует хотя бы одна цифра
G |
double, |
Идентичен формату спецификатора "g", за исключени |
|
float |
ем того, что признаком порядка служит "Е" |
Сint, char, Одиночный символ unsigned
S |
char * |
Символьная строка. Символы печатаются либо до пер |
|
|
вого нулевого символа ('\0') или печатается то количе |
|
|
ство символов, которое задано в поле т о ч н о с т ь спе |
|
|
цификации преобразования |
рvoid * Значение адреса. Печатает адрес, указанный аргумен
том (представление адреса зависит от реализации)
Приведем примеры использования различных спецификато ров. В каждой строке вызова функции printf() в качестве ком ментариев приведены результаты выбода. Переменная code
Глава 7. Ввод и вывод |
341 |
содержит код возврата функции printf() - число напечатанных символов при выводе значения переменной f.
#±nclude <stdio.h> int main()
{
int number = 27; |
|
|
|||
float |
f = |
123.456; |
|
|
|
char |
str[4] = |
"abc"; |
|
|
|
char |
c = |
'a ';. |
|
|
|
int code; |
|
|
|
|
|
printf("%d\n", |
number); |
/* |
27 |
||
printf("%o\n", number); |
/* |
33 |
|||
printf("%x\n", number); |
/* |
lb |
|||
code |
= printf("%f\n", f); |
/* |
123.456001 |
||
printf("code = |
%d\n", code); |
/* |
code = 11 |
||
printf("%e\n", |
f); |
/* |
1.23456e+02 |
||
printf("%c\n", c); |
/* |
a |
|||
printf("%s\n", str); |
/* |
abc |
|||
return 0; |
|
|
|
|
}
V
*/
V
V
*/
V
V
*/
Необязательные элементы спецификации преобразования управляют другими параметрами форматирования.
Флаги управляют выравниванием вывода и печатью знака числа, пробелов, десятичной точки, префиксов восьмеричной и шестнадцатеричной систем счисления. Флаги могут отсутство вать, а если они есть, то могут стоять в любом порядке.- Смысл флагов следующий:
Выводимое изображение значения прижимается к левому краю поля. По умолчанию, т.е. при отсут ствии этого флага, происходит выравнивание по правой границе поля.
+Если выводимое значение имеет знак (любой: '+'
|
или |
то он выводится. Без этого флага знак |
|
выводится только при отрицательном значении. |
|
пробел |
Используется для вставки пробела на месте знака |
|
|
перед положительными числами. |