Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие С(часть1-3).doc
Скачиваний:
23
Добавлен:
12.02.2015
Размер:
854.02 Кб
Скачать

Задание 2. Описание переменных и преобразование типов

Каждому студенту рекомендуется выполнить упражнения 1–3.

1. Опишите переменные всех типов, приведенных в таблице 2. Определите количество байтов, которые занимают в памяти переменные этих типов. Результат выведите на экран в виде

sizeof(int)=2

sizeof(long)=4…

2. Опишите в программе две переменные целого типа и введите их значения с клавиатуры. Выведите на экран вещественное число, равное делению первой переменной на вторую. (Используйте операцию деления /. При делении целых чисел эта операция возвращает только целую часть частого. Результат операции деления / будет вещественным, если делимое или (и) делитель – вещественное число. Поэтому, в данной задачи необходимо использовать явное преобразование типов)

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

3. Ввод – вывод значений переменных

Значение переменной может быть указано при описании, а может быть введено с клавиатуры. Рассмотрим, как происходит ввод – вывод в языке С.

В языке С не определено никаких ключевых слов, с помощью которых можно выполнять ввод – вывод. Вместо них используются библиотечные функции. Заголовочным файлом для функций ввода–вывода является <stdio.h>. Имеются как консольные (ввод с клавиатуры, вывод на экран), так и файловые функции ввода/вывода. С практической точки зрения консольный и файловый ввод/вывод отличаются друг от друга очень мало. В данной главе мы рассмотрим консольные функции.

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

Пример использования функций getchar() и putchar():

char c;

printf("Enter symbol: ");

c=getchar();

printf("Symbol= ");

putchar(c);

Для считывания и отображения строк можно использовать функции gets() и puts() соотвественно.

Функция gets() читает строку символов, введенную с клавиатуры, и записывает ее в память по адресу, на который указывает ее аргумент. Символы можно вводить с клавиатуры до тех пор, пока не будет введен символ возврата каретки. Он не станет частью строки, а вместо него в ее конец будет помещен символ конца строки ('0'). Необходимо очень осторожно использовать gets(), потому что эта функция не проверяет границы массива, в который записываются введенные символы. Таким образом, может случиться, что пользователь введет больше символов, чем помещается в этом массиве. Хотя функция gets() прекрасно подходит для программ-примеров и простых программ, предназначенных для «домашнего использования», но в профессиональных программах ею лучше не пользоваться.

Функция puts() отображает на экране свой строковый аргумент, после чего курсор переходит на новую строку. Отметим, что функция выполняется быстрее, чем printf(), но не позволяет числа или делать преобразования формата.

Пример использования функций gets() и puts():

char str[10];

printf("Enter string: ");

gets(str);

printf("String= ");

puts(str);

Для консольного чтения и записи данных в разных форматах (форматный ввод-вывод) в языке С изпользуются функции scanf() и printf() соотвественно. Обе функции могут работать с любым встроенным типом данных, а также с символьными строками, которые завершаются символом конца строки ('0').

Функция printf(управляющая_строка) вывод данные на экран и в качестве результата возвращает число выведенных символов или отрицательное значение в случае ошибки.

Управляющая_строка состоит из элементов двух видов. Первый из них — это символы, которые предстоит вывести на экран; второй — это спецификаторы преобразования, которые определяют способ вывода стоящих за ними аргументов. Каждый такой спецификатор начинается со знака процента, за которым следует код формата. Аргументов должно быть ровно столько, сколько и спецификаторов, причем спецификаторы преобразования и аргументы должны попарно соответствовать друг другу в направлении слева направо. Например, в результате такого вызова printf()

printf("Мне нравится язык %c %s", 'C', "и к тому же очень сильно!");

будет выведено

Мне нравится язык C и к тому же очень сильно!

В этом примере первому спецификатору преобразования (%c), соответствует символ 'C', а второму (%s), — строка "и к тому же очень сильно!".

Спецификаторы преобразования для функции printf() приведены в таблицы 3.

Таблица 3. Спецификаторы преобразования для функции printf()

Код

Формат

%a

Шестнадцатеричное в виде 0xh.hhhhp+d

%A

Шестнадцатеричное в виде 0Xh.hhhhP+d

%c

Символ

%d

Десятичное целое со знаком

%i

Десятичное целое со знаком

%e

Экспоненциальное представление ('е' на нижнем регистре)

%E

Экспоненциальное представление ('Е' на верхнем регистре)

%f

Десятичное с плавающей точкой

%g

В зависимости от того, какой вывод будет короче, используется %е или %f

%G

В зависимости от того, какой вывод будет короче, используется %Е или %F

%o

Восьмеричное без знака

%s

Строка символов

%u

Десятичное целое без знака

%x

Шестнадцатеричное без знака (буквы на нижнем регистре)

%X

Шестнадцатеричное без знака (буквы на верхнем регистре)

%p

Выводит указатель

%n

Аргумент, соответствующий этому спецификатору, должен быть указателем на целочисленную переменную. Спецификатор позволяет сохранить в этой переменной количество записанных символов (записанных до того места, в котором находится код %n)

%%

Выводит знак %

Например,

printf("%s%d%c%o%c%Х","This is number 10 : ",10, ',',10,',',10);

выведет на экран

This is number 10 : 10,12,A

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

Целое число, расположенное между знаком % и кодом формата, играет роль модификатора минимальной ширины поля. Если указан модификатор минимальной ширины поля, то чтобы ширина поля вывода была не меньше указанной минимальной длины, при необходимости вывод будет дополнен пробелами. Если же выводятся строки или числа, которые длиннее указанного минимума, то они все равно будут отображаться полностью. По умолчанию для дополнения используются пробелы. А если для этого надо использовать нули, то перед модификатором ширины поля следует поместить 0. Например, %05d означает, что любое число, количество цифр которого меньше пяти, будет дополнено таким количеством нулей, чтобы число состояло из пяти цифр. Например, при выполнении следующего фрагмента программы

double item;

item = 123.45;

printf("%f\n", item);

printf("%10f\n", item);

printf("%012f\n", item);

на экран выведется:

123.450000

123.450000

00123.450000

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

Модификатор точности следует за модификатором минимальной ширины поля (если таковой имеется). Он состоит из точки и расположенного за ней целого числа. Значение этого модификатора зависит от типа данных, к которым его применяют.

Когда модификатор точности применяется к данным с плавающей точкой, для преобразования которых используются спецификаторы преобразования %f, %e или %E, то он определяет количество выводимых десятичных разрядов. Например, %10.2f означает, что ширина поля вывода будет не менее 5 символов, причем для десятичных разрядов будет отведено две позиции.

Если модификатор точности применяется к %g или %G, то он определяет количество значащих цифр.

Примененный к строкам, модификатор точности определяет максимальную длину поля. Например, %5.7s означает, что длина выводимой строки будет составлять минимум пять и максимум семь символов. Если строка окажется длиннее, чем максимальная длина поля, то конечные символы выводиться не будут.

Если модификатор точности применяется к целым типам, то он определяет минимальное количество цифр, которые будут выведены для каждого из чисел. Чтобы получилось требуемое количество цифр, добавляется некоторое количество ведущих нулей.

Пример, использования модификатора точности:

printf("%.3f\n", 123.1234567);

printf("%8.8d\n", 1000);

printf("%3.7s\n", "This is string");

При выполнении этого фрагмента программы на экран будет выведена следующая информациия:

123.123

00001000

Thisis

По умолчанию весь вывод выравнивается по правому краю. То есть если ширина поля больше ширины выводимых данных, то эти данные располагаются по правому краю поля. Вывод по левому краю можно назначить принудительно, поместив знак минус прямо за %. Например, %–5.2f означает, что число с плавающей точкой и с двумя десятичными разрядами будет выровнено по левому краю 5–символьного поля.

Например, при выполнении следующего фрагмента кода

printf("%15d\n", 100);

printf("%-15d\n", 100);

на экран выведется:

100

100

Непосредственное расположение # перед спецификаторами преобразования g, G, f, Е или e означает, что при выводе обязательно появится десятичная точка — даже если десятичных цифр нет. Если вы поставите # непосредственно перед x или X, то шестнадцатеричное число будет выведено с префиксом 0x. Если # будет непосредственно предшествовать спецификатору преобразования o, число будет выведено с ведущим нулем. К любым другим спецификаторам преобразования модификатор # применять нельзя.

Функция scanf(управляющая_строка) выполняет ввод с клавиатуры и возвращает количество тех элементов данных, которым было успешно присвоено значение, либо EOF в случае ошибки.

Управляющая строка состоит из символов трех видов: спецификаторов преобразования, разделителей и символов, не являющихся разделителями.

Каждый спецификатор формата ввода начинается со знака %, причем спецификаторы формата ввода сообщают функции scanf() тип считываемых данных. Перечень этих кодов приведен в таблице 4.

Таблица 4. Спецификаторы преобразования для функции scanf()

Код

Значение

%a

Читает значение с плавающей точкой

%c

Читает одиночный символ

%d

Читает десятичное целое число

%i

Читает целое число как в десятичном, так и восьмеричном или шестнадцатеричном формате

%e

Читает число с плавающей точкой

%f

Читает число с плавающей точкой

%g

Читает число с плавающей точкой

Читает восьмеричное число

%s

Читает строку

%x

Читает шестнадцатеричное число

%p

Читает указатель

%n

Принимает целое значение, равное количеству уже считанных символов

%u

Читает десятичное целое число без знака

%[]

Читает набор сканируемых символов

%%

Читает знак процента

Спецификаторам преобразования в порядке слева направо ставятся в соответствие элементы, представляющие собой адреса объектов, куда необходмо считать информацию. То есть если необходмо считать данные в переменную а, то следуется указать, не ее имя, а ее адрес, т.е. &a.

Например, следующая программа читает десятичное, восьмеричное и шестнадцатеричное число и выводит их на экран в десятичном виде:

int a, b,c;

scanf("%d%o%x", &a, &b, &c);

printf("%d %d %d", a,b,c);

При чтении одиночного символа символы разделителей читаются так же, как и любой другой символ, хотя при чтении данных других типов разделители интерпретируются как разделители полей. Например, при вводе с клавиатуры "x y" фрагмент кода

scanf("%c%c%c", &a, &b, &c);

помещает символ x в a, пробел — в b, а символ y — в c.

Для чтения из входного потока строки можно использовать функцию scanf() со спецификатором преобразования %s. Использование спецификатора преобразования %s заставляет scanf() читать символы до тех пор, пока не встретится какой-либо разделитель. Читаемые символы помещаются в символьный массив, на который указывает соответствующий аргумент, а после введенных символов еще добавляется символ конца строки ('0'). Что касается scanf(), то таким разделителем может быть пробел, разделитель строк, табуляция, вертикальная табуляция или подача страницы. В отличие от gets(), которая читает строку, пока не будет нажата клавиша <ENTER>, scanf() читает строку до тех пор, пока не встретится первый разделитель. Это означает, что scanf() нельзя использовать для чтения строки "Hello,World", потому что после пробела процесс чтения прекратится. Пример ввода строки:

char str[80];

printf("Введите строку: ");

scanf("%s", str);

printf("Вот Ваша строка: %s", str);

Если введена строка "Hello,World", то на экран будет выведено "Hello,". Обратите внимание, что передstr, не стоит операция взятия адреса &, так как имя массива является адресом его первого элемента.

Ввод-вывод массив и символьных массивов это различные процедуры. Например, если дан массив

int str[]={1,2,3};

то запись

printf("%i", str);

приведет не к его выводу, а к выводу на экран адреса массива, преобразованного к целому числу,

а запись

scanf("%i", str);

приведет к чтению только первого элемента массива.

Чтобы ввести, а затем вывести элементы данного массива, необходимо использовать запись

scanf("%i%i%i", &str[0],&str[1],&str[2]);

printf("Элементы массива: %i %i %i", str[0],str[1],str[2]);

Разделитель в управляющей строке дает scanf() указание пропустить в потоке ввода один или несколько начальных разделителей. Разделителями являются пробелы, табуляции, вертикальные табуляции, подачи страниц и разделители строк. В сущности, один разделитель в управляющей строке заставляет scanf() читать, но не сохранять любое количество (в том числе и нулевое) разделителей, которые находятся перед первым символом, не являющимся разделителем.

Если в управляющей строке находится символ, не являющийся разделителем, то функция scanf() прочитает символ из входного потока, проверит, совпадает ли прочитанный символ с указанным в управляющей строке, и в случае совпадения пропустит прочитанный символ. Например, "%d,%d" заставляет scanf() прочитать целое значение, прочитать запятую и пропустить ее (если это была запятая!), а затем прочитать следующее целое значение. Если же указанный символ во входном потоке не будет найден, то scanf() завершится.

Как и printf(), функция scanf() дает возможность модифицировать некоторое число своих спецификаторов формата. В спецификаторах формата моно указать модификатор максимальной длины поля. Это целое число, расположенное между % и спецификатором формата; оно ограничивает число символов, считываемых из этого поля. Например, чтобы считывать в переменную str не более 20 символов, пишите

scanf("%20s", str);

Если поток ввода содержит больше 20 символов, то при следующем вызове функций ввода считывание начнется после того места, где оно закончилось при предыдущем вызове. Например, если вы в ответ на вызов scanf() из этого примера введете

ABCDEFGHIJKLMNOPRSTUVWXYZ

то в str из-за спецификатора максимальной ширины поля будет помещено только 20 символов, то есть символы вплоть до Т. Это значит, что оставшиеся символы UVWXYZ пока еще не прочитаны. При следующем вызове scanf(), например при выполнении оператора

scanf("%s", str);

в str будут помешены буквы UVWXYZ. Ввод из поля может завершиться и до того, как будет достигнута максимальная длина поля — если встретится разделитель. В таком случае scanf() переходит к следующему полю.

Чтобы прочитать длинное целое, перед спецификатором формата поместите l (эль). А для чтения короткого целого значения перед спецификатором формата следует поместить n. Эти модификаторы можно использовать со следующими кодами форматов: d, i, o, u, x и n.

По умолчанию спецификаторы f, e и g дают scanf() указание присваивать данные переменной типа float. Если перед одним из этих спецификаторов будет помещен l (эль), то scanf() будет присваивать данные переменной типа double. Использование L дает scanf() указание, чтобы переменная, принимающая данные, имела тип long double.

Функция scanf() может прочитать поле, но не присваивать прочитанное значение никакой переменной; для этого надо перед литерой-спецификатором формата поля поставить звездочку, *. Например, когда выполняется оператор

scanf("%d%*c%d", &x, &y);

можно ввести пару координат 10,10. Запятая будет прочитана правильно, но ничему не будет присвоена. Подавление присвоения особенно полезно тогда, когда нужно обработать только часть того, что вводится.

Пример 1. Ввести с клавиатуры два вещественных числа, очистить экран и вывести на экран два вещественных числа в формате 2 знака поле запятой и заполнить пространство между ними символом 0 следующим образом:

32.760000000000000000000000000000000000000000000000000000005.41

#include <stdio.h>

#include <conio.h>

#include <iostream>