|
Форматирование ввода-вывода средствами языка СНачнем наше изучение функций printf() и scanf() с того, что определим для чего они нам нужны. Функции printf() и scanf() используются для ввода и вывода информации. Точнее, функция printf() заведует выводом, а функция scanf() - вводом. Эти две функции очень похожи между собой, поэтому рассмотрим сначала функцию printf(), а после перейдем к изучению scanf(). Кстати, чтобы работать с этими функциями без проблем, не забывайте подключать в своих приложениях библиотеку stdio.h Функция printf()Как уже упоминалась ранее, функция printf() является функцией вывода. Рассмотрим прототип данной функции: int printf(const char *control-str[, argument1 [, argument2 [, ... ]]]); Начнем с того, что же эта функция возвращает. А возвращает она при удачном стечении обстоятельств количество выведенных символов, в противном случае вернет код ошибки. Параметр control-str (управляющая строка) - это строка в двойных кавычках. Данный параметр может быть единственным в функции. Например: строка кода Параметры argument1, argument2 и т.д. - это те элементы, которые необходимо вывести на экран. Они могут быть переменными или константами либо даже выражениями, значение которых вычисляется при выводе на печать. Если в функции есть хотя-бы один параметр argument, управляющая строка должна содержать спецификатор преобразования для него. Для каждого параметра argument необходим спецификатор преобразования. Сами спецификаторы перечислены в таблице.
Элементы, которые необходимо вывести на экран, нужно расположить в функции в таком порядке, в каком в управляющей строке расположены для них спецификаторы преобразования. Это связано с работой функции printf(). Функция выводит без изменений все символы управляющей строки за исключением спецификаторов преобразования. Когда функция находит в управляющей строке первый спецификатор преобразования, она подставляет значение второго параметра (т.е. argument1)на место спецификатора, предварительно преобразовав это значение в соответствии с данным спецификатором. Далее, найдя следующий спецификатор, функция подставляет на его место третий параметр и так далее. Рассмотрим примеры: int numPages = 273; Согласитесь, в последнем примере цифры, выведенные на экран, выглядят не очень красиво. Возникает вопрос - что же с ними делать? Для того, чтобы исправить сложившееся положение при помощи функции printf(), необходимо рассмотреть как выглядит полностью прототип спецификатора преобразования. На самом деле спецификатор преобразования -это не только знак процента с определенной буквой. Спецификатор имеет несколько необязательных параметров и выглядит он следующим образом: %[flags] [width] [.precision] [{h | l | L}]type
В данном прототипе type - это как раз те буквы, которые мы рассмотрели ранее. До этого момента мы использовали, так скажем, упрощенные спецификаторы преобразования, то есть в нашем случае прототип выглядел бы так: %type Что тоже является правильным, правда, не всегда удобным. Чтобы понять, зачем нужны спецификатору преобразования необязательные параметры, рассмотрим их по порядку. И начнем наше рассмотрение с первого необязательного параметра - flags. Все существующие флаги приведены в таблице. Сразу необходимо отметить, что в спецификаторе могут применяться сразу несколько флагов.
Рассмотрим несколько примеров с использованием флагов: int books = 10; width - минимальная ширина поля. Более широкое поле будет использоваться, если выводимое число или строка не будет соответствовать полю. Пример: int num = 345; .precision - точность. Для преобразований %e, %E и %f задается количество цифр, которые будут выведены справа от десятичного числа. Для преобразований %g и %G задается максимальное число значащих цифр. Для преобразования %s задается максимальное число символов, которое будет напечатано. Для преобразований целого числа задается минимальное число цифр, которые должны появиться; если целое число содержит меньше цифр, чем задано, то в начало числа добавляются нули. При использовании точки (.) подразумевается следующий далее нуль, так что %.f - тот же спецификатор, что и %.0f. Приведем пример: float nQuantity = 100; Если вместо числа в модификаторе width поставить звездочку (*), то для данного спецификатора не будет задана фиксированная ширина поля, а ширину будет регулировать переменная (целое число). То же самое касается точности - если вместо числа в модификаторе precision поставить *, то за количество знаков после запятой будет отвечать переменная. Пример: float num = 12.5; h | l | L -необязательные префиксы, приставляемые к типу спецификатора модификации. Они уточняют размер параметра argument, относящегося к данному спецификатору. h используется при целочисленном преобразовании для кодирования значений short int или unsigned short int. l используется при целочисленном преобразовании для кодирования значений long int или unsigned long int. L используется для преобразований с плавающей точкой для кодирования значений long double. Итак, мы рассмотрели как работает функция printf() и переходим к изучению второй не менее полезной функции. Функция scanf()Как уже упоминалось в начале функция scanf() используется для обработки информации, введенной пользователем с клавиатуры. Несомненный плюс данной функции, что она может преобразовывать введенную информацию не только в символы, но и в числа, в том числе и в числа с плавающей точкой. Прототип функции scanf() на удивление похож на прототип предыдущей изучаемой функции, а именно printf(). Выглядит он следующим образом: int scanf(const char *control-str[, argument1 [, argument2 [, ... ]]]); Возвращает эта функция число элементов, которые она успешно прочитала. Если она не прочла никаких элементов, функция возвращает значение 0. Функция scanf() вернет значение EOF, если обнаружит символ конца строки или символ конца файла, а также в случае ошибки. Первый параметр функции - control-str - как и в предыдущей функции это управляющая строка, сопровождаемая списком параметров argument. После управляющей строки идут параметры argument, каждый из которых является адресом переменной, в которую будет записано введенное и считанное значение. Следовательно,если мы используем функцию для чтения строки в символьный массив, в качестве аргумента мы передаем название символьного массива, в остальных случаях, то есть для чтения других типов - мы передаем название переменной со знаком амперсанта (&). Управляющая строка указывает, в какие форматы должен быть преобразован вводимый текст. В ней также используются спецификаторы преобразования, их прототип похож на прототип спецификатора функции printf, но все же отличается. Вот как выглядит прототип спецификатора преобразования функции scanf(): % [*] [width] [{h | l | L}] type
Рассмотрим типы (type) спецификаторов преобразования для данной функции. Они идентичны спецификаторам функции printf.
Для того, чтобы отделить вводимые значения, функция scanf() использует символы, называемые служебными. К ним относятся символы перевода строки, табуляции и пробелы. Что сие значит: во время ввода информации пользователь должен после каждого введенного значения вводить служебный символ для того, чтобы показать функции, что он закончил ввод очередного значения. Единственное исключение - спецификатор %c, который читает каждый следующий символ, даже если этот символ является служебным. Приведем пример: char name[15]; Модификатор * заставляет функцию scanf() игнорировать соответствующий ввод. То есть, если в спецификаторе преобразования стоит звездочка, то функция введенное значение не записывает в переменную. Пример: int num; Второй необязательный модификатор спецификатора - width - максимальная ширина поля. Ввод останавливается, когда достигнута максимальная ширина поля или при обнаружении служебного символа. После достижения максимальной ширины поля функция считает, что начался ввод следующего значения. Использование необязательных префиксов h | l | L рассмотрено в таблице:
Как Вы уже заметили, в контрольной строке функции scanf() между спецификаторами преобразования в примерах использовались пробелы. Пробел в контрольной строке означает, что нужно пропускать любой служебный символ перед следующим получаемым элементом. Так как практически все спецификаторы, за исключением %с, автоматически пропускают служебные символы, то : int n; Если же используется спецификатор преобразования %с, то без пробела перед этим спецификатором функция считает любой первый символ, в том числе и служебный. Но если же перед спецификатором %с стоит пробел, то функция считает первый неслужебный символ. В контрольной строке можно также использовать обычные символы, отличные от пробела. Например, scanf("%d + %f", &n, &m);
В этом примере функция будет ожидать от пользователя, что он введет между двумя значениями знак +. Если же не ввести с клавиатуры символ +, то в последующие элементы не будут занесены значения. Форматирование ввода-вывода средствами языка С++Чтобы, например, указать ширину полей, левое или правое выравнивание и т.д. можно использовать printf(), а можно сделать то же самое при помощи средств форматирования ввода/вывода языка С++. Существуют два способа форматирования ввода/вывода, которые мы по очереди рассмотрим в данной главе. Первый способ предусматривает использование функций для установки определенных флагов форматирования, которые перечислены в классе ios_base enum { skipws = 0x0001,
Рассмотрим что делают перечисленные выше флаги.
Что делают флаги мы рассмотрели. Теперь необходимо познакомиться с функциями, которые устанавливают и сбрасывают эти флаги. Первая функция, которую мы рассмотрим, - это функция setf(), используемая для установки флагов long setf(long flags); Функция принимает в качестве параметра рассмотренные выше флаг или флаги, соединенные между собой при помощи побитового ИЛИ. Она возвращает предыдущее значение флага. Рассмотрим пример: cout.setf(ios::hex); Для отключения установленных флагов нужно использовать функцию unsetf(). Она имеет следующий прототип: long unsetf(long flags); Функция возвращает значение предыдущей установки флага и сбрасывает флаги, определяемые параметром flags. Пример: cout.setf(ios::showpos | ios::hex); Кроме флага форматирования также можно установить ширину поля потока, символ для заполнения и число цифр после десятичной запятой. Для этого используются следующие функции: int width(int len); Функция width() устанавливает ширину поля и возвращает текущую ширину. Вторая функция - fill() устанавливает текущий символ заполнения и возвращает предыдущий символ заполнения. По умолчанию используется пробел. А функция precision устанавливает точность чисел с плавающей точкой. В научном режиме эта функция определяет количество цифр после десятичной запятой. В обычной нотации функция обозначает количество выводимых цифр. Точность, установленная по умолчанию, равна 6. Функция width() воздействует только на один вывод информации, а после этого в действие вступают параметры принятые по умолчанию. В случае с остальными двумя функциями новые установки остаются действовать до их явного обновления. Приведем пример: cout.width(10); А теперь мы переходим к рассмотрению второго способа форматирования ввода/вывода. Второй способ - это использование манипуляторов. Манипуляторы являются специальными функциями, которые позволяют изменять флаги потока. Существуют манипуляторы с параметрами и без. Если Вы используете манипуляторы с параметрами, подключите файл iomanip.h Рассмотрим манипуляторы без параметров:
Манипуляторы с параметрами
<<<<Назад [Содержание] вперед>>>> |
|
