// Prim3_1.cpp

#include <stdio. h>

void main(void)

{

char ch; int i, j; float х, x2; char name[81];

printf("\nВведите Ваше имя: "); scanf("%s", name):

printf("Здравствуйте, %s. Вас приветствует звонком компьютер\а\n", name);

printf("Введите любое целое число: ");

fflush(stdin);

scanf("%d", &i);

j = i + 4;

printf("%d+ 4 = %d, верно?\n", i, j);

printf("Введите число с плавающей точкой: ");

scanf("%f", &х);

x2 = х • х;

printf("% f в квадрате = %f, верно?", x, x2);

printf("Введите любой символ:");

fflush(stdin);

scanf("%c", &ch);

printf("ASCII-код символа %c = %d (%#x)\n", ch, ch, ch);

}

Далее приводятся результаты работы программы

g:\l3_1 - запуск программы на выполнение;

Введите ваше имя: Александр Касаткин

Здравствуйте, Александр. Вас приветствует звонком компьютер

Введите любое целое число: 36

36 + 4 = 40, верно?

Введите число с плавающей точкой: 5.е1

50.000000 в квадрате = 2500. верно?

Введите любой, символ: 1

ASCII-код символа х31)

Программа последовательно выдает приглашения. После набора запрашиваемой информации следует нажать клавишу ENTER. После ее нажатия функция scanf() прекращает при­ем символов во внутренний буфер и переходит к обработке ввода в соответствии с форматной строкой. Обратите внима­ние, что на приглашение ввести имя в буфер функции было помещено два слова - имя и фамилия. При выводе же строки name функцией printf() на экране появляется только первое слово - имя. Дело в том, что по спецификации %s функция scanf() передает в программу все символы до первого раздели­теля, в том числе и пробела. Оставшиеся в буфере символы будут поступать в программу при следующих обращениях к функции scanf(), что не входит в наши планы. Вот почему перед очередным обращением к функции scanf() выполняется очистка буфера stdin функцией fflushf(). После вывода на экран второй стро­ки звенит звонок, так как на консоль выдается символ `\а`.

НЕ нашли? Не то? Что вы ищете?

Функции неформатированного консольного ввода-вывода работают с отдельными символами или строками символов. Для ввода символа используется функция getchar(), не имеющая ар­гументов и возвращающая целое число. Для вывода символа используется функция putchar(int). Ввод-вывод строк символов выполняют соответственно функции gets(char *string) и puts(char *string), где string задает адрес области памяти, в которую поме­щаются символы вводимой строки и откуда они выводятся на эк­ран. Функции gets(string) и puts(string) пo выполняемым действиям подобны scanf("%s",string) и printf("%s\n",string) соответственно. Однако функция gets() передает в программу все символы до '\n'. Поэтому, заменив в предыдущей програм­ме строку ввода имени scanf("%s", name); на строку gets(name); удалось бы ввести как имя, так и отчество.

3.2. Функция ввода cin

Компиляторы языка С++ поддерживают функции gets(), getchar() и scanf(), о которых мы говорили в этой главе. Кроме того, С++ имеет собственное многоцелевое средство ввода для всех типов данных. Стандартный поток ввода cin в сочетании с двумя символами «больше» (>>), которые называются оператором извлечения, служит для считывания данных с клавиатуры. Программа

int count;

cin » count;

вносит целочисленные данные с клавиатуры в значение переменной count. Стандартный поток ввода cin не требует указания адреса переменной для числовых и символьных данных, указывается только имя переменной.

При использовании cin нет необходимости определять формат с помощью указателей формата. Поток ввода cin имеет возможность определять тип данных самостоятельно на основании вводимой информации. Это свойство называется перегрузкой. Из-за этой особенности оператора cin большинство программистов предпочитают использовать именно его, а не функцию scanf().

При работе с несколькими аргументами необходимо отделять каждое имя переменной оператором извлечения:

cin » amount » count » age » name;

Возможно, первое время вы будете испытывать затруднения в использовании операторов извлечения » и вставки «. На рис. 4 показан простой способ запоминания этих операторов, изображенных в виде стрелок, которые указыва­ют направление вперед или назад относительно переменной из списка данных.

Оператор извлечения » изображен в виде стрелки, направленной в сторону переменной. Это означает, что данные поступают к ней в виде ввода.

Рис. 4. Оператор вставки и оператор извлечения

Когда вы применяете cin для ввода данных, пользуйтесь оператором, который как бы указывает направление к переменной.

Оператор вставки « изображен в виде стрелки, направленной от переменной. Это значит, что данные выводятся из переменной на экран. Со стандартным потоком вывода cout используйте, соответственно, тот оператор, который как бы указывает направление от переменной.

3.3. Неинициализированные переменнее

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

При включении компьютера области памяти, которые не используются опера­ционной системой, заполнены случайными данными. Когда С++ резервирует память для переменных при их определении, то содержимое этих областей памяти не меняется до тех пор, пока переменная не инициализирована или пока ей не присвоены введенные данные. Поэтому, если в программе в качестве параметра функции вывода используется переменная, которой не было присво­ено к этому моменту никакого значения, на экране появятся те случайные данные, что все еще хранятся в памяти. Но это еще не самое худшее. Если подобная переменная используется при расчетах, компилятор С++ тоже не сообщит об ошибке, но при этом все полученные результаты будут лишены смысла, а поскольку вы не были предупреждены о том, что произошло, вы можете принять их как вполне достоверные.

Чтобы избежать неприятностей, многие программисты присваивают начальные значения всем переменным. Можно присвоить ноль в качестве начального значения числовой переменной и пробел символьной и строковой переменным:

int count = 0;

char initial = ' ';

float rate = 0.0;

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

Поступив подобным образом, можно, как минимум, избежать появления на экране бессмысленных символов, если с функцией вывода будет использована переменная, которой не присвоено никакого значения. Позже вы узнаете, как протестировать список переменных, чтобы убедиться, что они имеют правильные значения. Помните: чистый вход — чистый выход.

В табл. 6 собраны все средства ввода данных, о которых говорилось в этой главе.

3.4. Функция вывода cout

Все обсуждавшиеся ранее приемы программирования относятся к выводу даныных как в языке С, так и С++. Однако язык С++ имеет дополнительный способ вывода данных всех типов.

В С++ существует стандартный поток вывода cout, позволяющий в сочетании с двумя символами «меньше» («), которые называются оператором вставки, отображать литералы или значения констант и переменных без использования указателей формата.

Если у вас есть компилятор С++, посмотрите документацию к нему. Не исключено, что необходим специальный файл заголовков для того, чтобы иметь возможность использовать преимущества стандартного потока вывода cout и стандартного потока ввода cin (о нем вы прочтете в следующей главе).

Таблица 6

Основные средства ввода данных в языке Си/Си++

Функция

Тип данных

Комментарии

gets()

Только строки

Си и Си++. Используется для ввода строк, возможно наличие пробелов. По­сле ввода данных необходимо нажать Enter.

getchar()

Единичные символы

Си и Си++. Используется для ввода единичных символов в переменную, определенную как int или char. После ввода символа не надо нажимать Enter. Используется без параметров в качестве переменной (например, letter=getchar()) или сама по себе для временной оста­новки программы.

scanf()

Все типы данных

Си и Си++. Требует указателей формата для каждого элемента вводимых дан­ных. Не используется для ввода строк, имеющих пробелы. Необходимо сле­дить за правильностью формата вводи­мых данных. Может иметь несколько аргументов. Перед переменной типа char нельзя ставить пробел.

cin

Все типы данных

Только Си++. Не нуждается в указа­телях формата и операторе получения адреса. Может вводить значения для нескольких аргументов. Аргументы от­деляются операторами ».

Для некоторых компиляторов, например, необходимо включить файл STREAM. H с помощью директивы #include в начале программы.

Рис. 5. Стандартный поток вывода.

Структура инструкции, использующей cout, показана на рис. 5. После cout надо ставить два знака <. Они указывают cout отобразить помещенную после них информацию. Информация может быть представлена в виде литерала (тогда ее заключают в кавычки) либо имени константы или переменной.

Рассмотрим инструкцию

cout<<"Привет, меня зовут Сэм. Мы с вами уже встречались";

При ее выполнении произойдет вывод на дисплей строки, заключенной в кавычки. Инструкция

int count;

count = 4509;

cout<<count;

отобразит значение переменной с именем count – число 4509.

Используя один стандартный поток вывода cout, можно отобразить несколько аргументов. Между собой аргументы разделяются операторами вставки, как это продемонстрировано на рис. 6. Например, инструкция

int age;

age = 43;

cout « "Вам исполнилось " « age « " года.";

отображает текст

Вам исполнилось 43 года.

Рис. 6. Вывод нескольких аргументов с помощью cout

Стандартный поток вывода cout отображает каждый пункт, указанный с по­мощью оператора вставки, в том порядке, в каком они записаны в инструкции.

Так же, как и функция printf(), cout не добавляет никаких команд новой строки после отображения данных. Чтобы перейти к новой строке, там, где вы хотите ее начать, надо добавить управляющий код \n, как это показано на рис. 6.

Стандартный поток вывода cout не требует обязательного использования указа­телей формата, но позволяет их ввести. С помощью указателей формата можно определять ширину поля, количество пробелов и число знаков после точки в вещественных числах. Описание форматирования вывода при использовании cout не входит в задачу этой книги. Если у вас есть компилятор Си++, вы можете подробно прочитать об этом в его описании. Не забудьте посмотреть в документа­ции, надо ли включать специальные файлы заголовков при использовании cout.

Одна из особенностей языка С++ - так называемая перегрузка – делает необязательным использование указателей формата. В отличие от функции printf(), которая требует обязательного указания формата данных, cout при передаче параметров сам определяет формат на основании типа получаемых данных. Этот процесс и называется перегрузкой.

Таблица 7

Средства вывода информации в языке С++.

Функция или ключевое слово

Тип данных

Комментарии

puts()

только строки

С и С++. Используется только для вывода строк. Выводит строковые литералы в кавычках, значения переменных и констант. Может автоматически перемещать курсор на следующую строку после вывода (не забудьте проверить документацию).

putchar()

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

С и С++. Используется для вывода символа, определенного как char или int. Не переводит курсор на следующую строку автоматически (проверьте документацию). Используйте для вывода литералов в одинарных кавычках, констант, переменных типа char, специальных символов или escape-последовательностей.

printf()

все типы данных

С и С++. Необходимы указатели формата для каждого элемента данных. Может обеспечить вывод нескольких аргументов. Не переводит курсор автоматически, используйте escape-последовательность \n.

cout

все типы данных

Только С++. Отделяйте аргументы знаками <<. Не переводит курсор автоматически. Указатели формата не обязательны

4. ОПЕРАЦИИ И ВЫРАЖЕНИЯ

4.1. Выражение и его интерпретация

Выражения в языке С++ - это последовательность операндов, операций и символов-разделителей. Операнды - это переменные, константы либо другие выражения. Разделителями в С++ являются символы [ ] ( ) { } , ; : ... * = #, каждый из которых выполняет свою функцию. Выражение может состоять из одной или более операций и определять выполнение целого ряда элементарных шагов по преобразованию информации. Компилятор соблюдает строгий порядок интерпретации выражений, называемый правилами предшествования. Этот порядок может быть изменён, если отдельные части выражения заключить в круглые скобки. Элементарная операция по преобразованию информации задаётся знаком операции. По числу операндов участвующих в операции различают две группы операций: унарные (один операнд) и бинарные (два операнда). По типу выполняемой операции различают арифметические, поразрядные, логические, присваивания, операции отношения и др.

4.2. Основные операции и их приоритет

4.2.1. Арифметические операции

Язык С++ включает стандартный набор арифметических операций сложения (задаётся знаком +), вычитания (-), умножения(*), деления (/), не требующих особого пояснения. Специфичными для С++ являются операции определения остатка (%), инкремента (++) и декремента (--). Операцию % поясняет следующий пример:

int a = 5, b = 2, c = 0, d;

d = a%b; /* d=1 – остаток от целого деления 5/2 */

d = b%a; /* d=2 */

d = a%c; /* сообщение об ошибке деления на 0 */

Операции инкремента и декремента соответственно увеличивают и уменьшают операнд на 1. Операции ++ и – могут применяться только к переменным. Существуют две формы их записи: префиксная, когда операнд располагается справа от знака операции, и постфиксная, когда операнд располагается перед знаком операции. В префиксной форме сначала выполняется увеличение операнда на 1 и увеличенное значение используется в выражении. В постфиксной форме сначала берётся значение операнда и только после этого его значение увеличивается на 1. Например:

int a = 0, b = 1, c;

c = a++; /* c равно 0, а равно 1 */

c = ++a; /* теперь с=2, а=2 */

c = ++b; /* с=2, b=2 */

Форма записи операций ++ и -- сказывается в составных выражениях. Ясно, что нет никакого различия между одиночными выражениями a++; и ++a; b--; и –b;

4.2.2. Поразрядные логические операции

С++ поддерживает следующие поразрядные логические операции:

& поразрядное логическое И (AND);

^ поразрядное сложение по модулю 2 (XOR – исключающее или);

| поразрядное логическое ИЛИ (OR);

~ поразрядная инверсия.

Каждый бит результата определяется по битам операндов так, как это показано в табл. 8.

Таблица 8

Операнд 1

Операнд 2

AND

OR

XOR

0

0

0

0

0

0

1

0

1

1

1

0

0

1

1

1

1

1

1

0

Инверсия требует использования единственного операнда справа от знака ~. Результат образуется поразрядной инверсией всех битов операнда. Примеры:

int s = 0x53c9, mask = 0x356c, r_or, r_and, r_xor, r_inv;

r_or = s|mask; /* r_or=0x77ed */

r_and = s&mask; /* r_and=0x1148 */

r_xor = s^mask; /* r_xor=0x66a5 */

r_inv = ~mask; /* r_inv=0xca93 */

Поразрядные логические операции широко применяют для быстрого выделения остатка от деления операндов типа unsigned int на значения, кратные двум, а также для определения значения одного или нескольких заданных битов числа.

Например, определение остатка от деления операнда unsigned int на 2, 4, 8, 16 и т. д. требует поразрядной логической операции И делимого соответственно с масками 0х01, 0х03, 0х07, 0х0f, 0x1f и т. д. Другими словами, выделяются младшие биты числа, а остальные биты устанавливаются в 0. Это наиболее быстрый способ выделения остатка.

Пример:

int s = 0x05, mask = 0x01;

r_or = s&mask = 0x05 & 0x01 = 0x01;

Это наиболее быстрый способ выделения остатка.

4.2.3. Операции сдвига

Язык С++ включает две операции поразрядного сдвига:

<< - сдвиг влево операнда слева от знака операции на число двоичных разрядов справа от знака операции;

>> - сдвиг вправо операнда слева от знака операции на число двоичных разрядов справа от знака операции.

Выдвигаемые биты теряются, а «вдвигаются» нулевые биты.

Сдвиг операндов влево на 1, 2, 3 и более разрядов – наиболее быстрый способ деления на 2, 4, 8,… Например:

half_adr = adr >> 1; /* деление на 2 */

double_adr = adr << 1; /* умножение на 2*/

Часто операции сдвига выполняются при преобразовании чисел или при формировании целого из частей.

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

int var1, shift = 5;

var1 = var1 >> shift;

4.2.4. Логические операции и операции отношения

Логические операции и операции отношения используются при формировании логических выражений, имеющих только два значения: 1, если логическое значение ИСТИННО; 0, если логическое выражение ЛОЖНО. Логические выражения наиболее часто используются вместе с операторами управления потоком вычислений – операторами циклов и ветвлений.

С++ поддерживает следующие операции отношения:

==

>=

<=

!=

Если для операнда слева и для операнда справа отношение выполняется, результат равен 1 (ИСТИНА), если не выполняется – результат равен 0 (ЛОЖЬ).

С++ поддерживает следующие логические операции:

&& - логические И;

|| - логическое ИЛИ;

! – логическое НЕ;

В С++ значению ИСТИНА соответствует не только значение 1, но и любое другое ненулевое значение.

4.2.5. Операция условия?:

Специфичным для С++ является операция условия, задаваемая знаками операции? и : следующим образом:

cond_expression? TRUE_statement:FALSE_statement

При выполнении операции условия сначала вычисляется значение логического выражения cond_expression. Если оно – ИСТИНА, результатом всей операции условия является результат выражения TRUE_statement, если ЛОЖЬ, - результат выражения FALSE_statement.

Например:

int a = 4, b = 3, c;

c = a > b? a * a + b * b : 0; /* c = a * a + b * b = 25 */

4.2.6. Операции присваивания

Язык С++ имеет несколько особенностей выполнения присваивания, задаваемого символом операции =. При выполнении операции значение операнда справа от знака равенства пересылается в ячейку памяти, отведенную компилятором под переменную, ссылка на которую записана слева от знака.

В большинстве языков программирования присваивание – это отдельное предложение языка, задающее только операцию пересылки значения. В С++ операция присваивания дополнительно имеет еще и значение результата выполнения, совпадающее с присваиваемым значением. поэтому С++ допускает запись в одном предложении сразу нескольких операторов присваивания. Пример:

int a, b, c, d;

a = b = c = d = 0;

Другая особенность операции присваивания в С++ – наличие так называемой комбинированной операции присваивания:

var1 op= expression;

где var1 – переменная, имеющая ячейку памяти, op – одна из операций, задаваемых знаками *, /, +, -, %, <<, >>, &, ^, |; expression – любое выражение. Комбинированная операция присваивания эквивалентна следующей записи:

var1 = var1 op expression;

var1 += 1; /* var1 = var1 + 1; */

4.2.7. Операция sizeof

Результатом операции sizeof является размер в байтах типа или объявленной переменной. Применение операции к массивам возвращает число байтов, необходимое для размещения всех элементов массива.

Например:

int i, r; char c; long double ff;

r = sizeof char; /* 1 */

r = sizeof c; /* 1 */

r = sizeof ff; /* 10 */

r = sizeof (long double) /* 10 */

4.2.8. Операция приведения типа (type)

Рассмотренные в предыдущем параграфе преобразования выполняются автоматически при смешивании в одном выражении операндов разных типов (так называемое неявное приведение типов). Язык С++ позволяет задать и явное приведение типа операндов, используя операцию (type), где type – любой допустимый тип языка С++. Результатом операции (type) expression является значение выражения expression, преобразованное к типу type. Приведение к типу происходит в соответствии с правилами, рассмотренными в п. 2.5.6. Например:

int a = 8, b = 5, c, d; float var1, var2;

var1 = a / b; /* var1 = 1.0 – неверно */

var2 = (float)a / (float)b; /* var2 = 1.6 – верно */

4.2.9. Приоритет операций и порядок их выполнения

Все операции, распознаваемые компилятором, упорядочены по приоритету, который определяет порядок интерпретации выражения. Он может изменяться круглыми скобками. Если внутри скобок или при отсутствии скобок вообще в выражении есть несколько операций одного приоритета, компилятор учитывает дополнительно порядок выполнения операций, например слева направо или справа налево. Заключенное в скобки выражение интерпретируется компилятором в первую очередь. В сложном выражении первым выполняется выражение в самых «глубоких» скобках. В табл.6 приведен перечень всех операций языка С++, упорядоченных в порядке убывания приоритета (тонкая горизонтальная черта определяет операции с одинаковым приоритетом).

Грамматика языка С++ определяет 16 категорий приоритетов операций. В табл. 9 категории приоритетов названы рангами. Операции ранга 1 имеют наивысший приоритет. Операции одного ранга имеют одинаковый приоритет, и если их в выражении несколько, то они выполняются в соответствии с правилом ассоциативности либо слева направо(®), либо справа налево(). Если один и тот же знак приведен в таблице дважды, то первое появление(с меньшим по номеру, т. е. старшим по приоритету, рангом) соответствует унарной операции, а второе – бинарной. Отметим, что кроме стандартных режимов использования операций языка С++ допускает расширение их действия на объекты класса, вводимых пользователем или уже определенных в конкретной реализации языка. Примером такого расширения (перегрузки) является операция извлечения данных из потока << и операция передачи в выходной поток >>, применяемые к потокам ввода и вывода cout.

Таблица 9

Ранги операций

Ранг

Операции

Ассоци-атив-ность

1

() [] -> :: .

®

2

! ~ + - ++ -- & * (тип) sizeof new

delete тип () (функциональное преобразование типа)

3

. * ->*

®

4

* / % (мультипликптивные бинарные операции)

®

5

+ - (аддитивные бинарные операции)

®

6

<< >>

®

7

< <= >= >

®

8

== !=

®

9

&

®

10

^

®

11

|

®

12

&&

®

13

||

®

14

? : (условная операция)

15

= *= /= %= += -= &= ^= |= <<= >>=

16

, (операция запятая)

®

Важной особенностью компилятора Borland C++ является ускоренное вычисление логических выражений: вычисление их значения прекращается тогда, когда результат уже ясен.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7