10.6 Ввод-вывод в С
Поскольку текст программ на С и на С++ часто путают, то путают иногда
и потоковый ввод-вывод С++ и функции ввода-вывода семейства printf для
языка С. Далее, т.к. С-функции можно вызывать из программы на С++, то
многие предпочитают использовать более знакомые функции ввода-вывода С.
По этой причине здесь будет дана основа функций ввода-вывода С.
Обычно операции ввода-вывода на С и на С++ могут идти по очереди на
уровне строк. Перемешивание их на уровне посимвольного ввода-вывода
возможно для некоторых реализаций, но такая программа может быть
непереносимой. Некоторые реализации потоковой библиотеки С++ при допущении
ввода-вывода на С требуют вызова статической функции-члена
ios::sync_with_stdio().
В общем, потоковые функции вывода имеют перед стандартной
функцией С printf() то преимущество, что потоковые функции обладают
определенной типовой надежностью и единообразно определяют вывод
объектов предопределенного и пользовательского типов.
Основная функция вывода С есть
int printf(const char* format, ...)
и она выводит произвольную последовательность параметров в формате,
задаваемом строкой форматирования format. Строка форматирования состоит
из объектов двух типов: простые символы, которые просто копируются в
выходной поток, и спецификации преобразований, каждая из которых
преобразует и печатает очередной параметр. Каждая спецификация
преобразования начинается с символа %, например
printf("there were %d members present.",no_of_members);
Здесь %d указывает, что no_of_members следует считать целым и печатать
как соответствующую последовательность десятичных цифр. Если
no_of_members==127, то будет напечатано
there were 127 members present.
Набор спецификаций преобразований достаточно большой и обеспечивает
большую гибкость печати. За символом % может следовать:
- необязательный знак минус, задающий выравнивание влево в указанном
поле для преобразованного значения;
d необязательная строка цифр, задающая ширину поля; если в
преобразованном значении меньше символов, чем ширина строки, то оно
дополнится до ширины поля пробелами слева (или справа, если дана
спецификация выравнивания влево); если строка ширины поля начинается
с нуля, то дополнение будет проводится нулями, а не пробелами;
. необязательный символ точка служит для отделения ширины поля от
последующей строки цифр;
d необязательная строка цифр, задающая точность, которая определяет
число цифр после десятичной точки для значений в спецификациях
e или f, или же задает максимальное число печатаемых символов
строки;
* для задания ширины поля или точности может использоваться * вместо
строки цифр. В этом случае должен быть параметр целого типа, который
содержит значение ширины поля или точности;
h необязательный символ h указывает, что последующая спецификация d,
o, x или u относится к параметру типа короткое целое;
l необязательный символ l указывает, что последующая спецификация d,
o, x или u относится к параметру типа длинное целое;
% обозначает, что нужно напечатать сам символ %; параметр не нужен;
c символ, указывающий тип требуемого преобразования. Символы
преобразования и их смысл следующие:
d Целый параметр выдается в десятичной записи;
o Целый параметр выдается в восьмеричной записи;
x Целый параметр выдается в шестнадцатеричной записи;
f Вещественный или с двойной точностью параметр выдается в
десятичной записи вида [-]ddd.ddd, где число цифр после
точки равно спецификации точности для параметра. Если точность
не задана, печатается шесть цифр; если явно задана точность 0,
точка и цифры после нее не печатаются;
e Вещественный или с двойной точностью параметр выдается в
десятичной записи вида [-]d.ddde+dd; здесь одна цифра перед
точкой, а число цифр после точки равно спецификации точности
для параметра; если она не задана печатается шесть цифр;
g Вещественный или с двойной точностью параметр печатается по той
спецификации d, f или e, которая дает большую точность при
меньшей ширине поля;
c Символьный параметр печатается. Нулевые символы игнорируются;
s Параметр считается строкой (символьный указатель), и печатаются
символы из строки до нулевого символа или до достижения числа
символов, равного спецификации точности; но, если точность
равна 0 или не указана, печатаются все символы до нулевого;
p Параметр считается указателем и его вид на печати зависит от
реализации;
u Беззнаковый целый параметр печатается в десятичной записи.
Несуществующее поле или поле с шириной, меньшей реальной, приведет
к усечению поля. Дополнение пробелами происходит, если только
спецификация ширины поля больше реальной ширины.
Ниже приведен более сложный пример:
char* src_file_name;
int line;
char* line_format = "\n#line %d \"%s\"\n";
main()
{
line = 13;
src_file_name = "C++/main.c";
printf("int a;\n");
printf(line_format,line,src_file_name);
printf("int b;\n");
}
в котором печатается
int a;
#line 13 "C++/main.c"
int b;
Использование printf() ненадежно в том смысле, что нет никакого
контроля типов. Так, ниже приведен известный способ получения
неожиданного результата - печати мусорного значения или чего похуже:
char x;
// ...
printf("bad input char: %s",x);
Однако, эти функции обеспечивают большую гибкость и знакомы
программирующим на С.
Как обычно, getchar() позволяет знакомым способом читать символы из
входного потока:
int i;:
while ((i=getchar())!=EOF) { // символьный ввод C
// используем i
}
Обратите внимание: чтобы было законным сравнение с величиной EOF типа
int при проверке на конец файла, результат getchar() надо помещать в
переменную типа int, а не char.
За подробностями о вводе-выводе на С отсылаем к вашему руководству
по С или книге Кернигана и Ритчи "Язык программирования С".
Достарыңызбен бөлісу: |