Язык Си - руководство для начинающих
Шрифт:
И, наконец, попытаемся напечатать число (65616), превышающее максимальное значение, которое могут принимать данные типа int в нашей системе (32767):
printf(" %1d %d\n" , 65616, 65616);
Результат будет выглядеть так:
65616 80
Мы снова видим, что действия выполняются по "модулю" На этот раз счет ведется группами по 65536. Числа между 32767 и 65536 будут выводиться на печать как отрицательные из-за способа их представления в памяти машины. Системы с разными размера ми ячеек памяти, отводимых под данные целого
Мы не исчерпали всех возможных комбинаций данных и спецификаций преобразования, поэтому вы можете пытаться экспериментировать сами. Но будет лучше, конечно, если вы сможете за ранее предсказать результат, который будет получен при печати данных, когда используется какая-нибудь спецификация преобразования, выбранная вами.
Применение функции scanf
Поскольку в дальнейшем мы будем пользоваться функция scanf лишь эпизодически, мы рассмотрим здесь только основные особенности ее применения.
Так же как для функции printf, для функции scanf указываются управляющая строка и следующий за ней список аргументов. Основное различие двух этих функций заключается в особенности данного списка. Функция printf использует имена переменных константы и выражения, в то время как функция scanf– только указатели на переменные. К счастью, при применении этой функции мы ничего не должны знать о таких указателях. Необходимо помнить только два правила:
1. Если вам нужно ввести некоторое значение и присвоить его переменной одного из основных типов, то перед именем nepеменной требуется писать символ &.
2. Если вы хотите ввести значение строковой переменной, использовать символ & не нужно.
Приведем правильную программу:
main
{
int age;
float assets;
char pet [30];
printf(" Укажите ваш возраст, состояние и любимое животное.\n" );
scanf(" %d %f" , &age, &assets);
scanf(" %s" , pet); /* & отсутствует при указании массива
символов */ printf("%d $%.0f %s\n", age, assets, pet);
}
Вот пример диалога:
Укажите ВАШ ВОЗРАСТ, состояние и любимое животное.
82
8345245.19 носорог
82 $8345245 носорог
Функция scanf использует некоторые специальные знаки (про белы, символы табуляции и "новая строка") для разбиения входного потока символов на отдельные поля. Она согласует последовательность спецификаций преобразования с последовательностью полей, опуская упомянутые специальные знаки между ними. Обратите внимание, что наша входная информация располагается на двух строках. Точно
так же мы могли бы использовать одну или пять строк при условии, что вводимые величины разделяются по крайней мере одним знаком типа "новой строки", пробела или символа табуляции. Единственным исключением из этого является спецификация %с, обеспечивающая чтение каждого следующего символа даже в том случае, если это "пустой символ".Функция scanf использует практически тот же набор символов спецификации преобразования, что и функция printf. Основные отличия в случае функции scanf следующие:
1. Отсутствует спецификация %g.
2. Спецификации %f и %е эквивалентны. Обе спецификации до пускают наличие (или отсутствие) знака, строки цифр с десятичной точкой или без нее и поля показателя степени.
3. Для чтения целых чисел типа short применяется спецификация %h.
Функция scanf не является одной из наиболее часто используемых функций языка Си. Мы обсуждаем ее здесь главным образом из-за ее универсальности (она позволяет читать данные всех имеющихся типов); однако в Си имеется еще несколько других функций, осуществляющих ввод, например getchar и gets, которые более удобны для выполнения конкретных задач - чтения одиночных символов или строк, содержащих пробелы. Мы рассмотрим некоторые из этих функций в гл. 6, 13 и 15.
СОВЕТЫ ПО ПРИМЕНЕНИЮ
Задание фиксированной ширины полей оказывается полезным при печати данных столбцами. Поскольку шириной поля по умолчанию является "ширина" числа, при повторном использовании оператора
printf(" %d %d %d\n" , val1, val2, val3);
будут получены неровные столбцы чисел, если эти числа состоят из разного количества цифр. Например, результат мог бы выглядеть следующим образом:
12 234 1222
4 5 23
22334 2322 10001
(Здесь предполагается, что между обращениями к оператору печати значения переменных изменялись.)
Эти же данные можно представить в улучшенном виде, если за дать достаточно большую фиксированную ширину поля. При использовании оператора
printf( %9d %9d %9d\n" , val1, val2, val3);
результат будет выглядеть так:
12 234 1222
4 5 23
22334 2322 10001
Наличие пробелов между спецификациями преобразования гарантирует, что даже в том случае, если все поле будет заполнено, символы, соответствующие данному числу, не перейдут в следующее поле.
Это вызвано тем обстоятельством, что обычные символы, имеющиеся в управляющей строке, включая пробелы, всегда печатаются.
С другой стороны, если печатаемое число включено в некоторую фразу, то часто при его выводе оказывается удобным задать поля равной или меньше требуемой. Это дает возможность включить число в фразу без добавления лишних пробелов. Например, результатом работы оператора: