Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Алгоритмизация и программирование на языке С++. Ч.1. Учебник
.pdf
4. Операции (выражения)
== !=
10
&
11
^
12
|
13
&&
14
||
15
?: = op= throw
16
,
17
Окончание табл. 4.1
51
При определении порядка выполнения операций в С++
важным являются два момента. Кроме приоритета, на порядок операций в выражениях, содержащих более одной инструкции, влияет еще и ассоциативность. Последняя указывает, как группируются операции с одинаковым приоритетом
в выражении: с тем, который находится слева или справа.
В таблице, приведенной в прил. 3, операции собраны в
17 групп, но для каждой из них указана еще и ассоциативность. У большинства групп ассоциативность определяет,
что при вычислении выражения с одинаковыми приоритетами операций последние выполняются слева направо, например это группа 5. Но для группы 3 ассоциативность определяет выполнение операций справа налево. Рассмотрим это
на примере. Пусть дан такой фрагмент программы.
cout << "(6*4)/2 " << (6*4)/2 << endl ;
cout << "6*4/2 " << 6*4/2 << endl ;
cout << "6*(4/2) " << 6*(4/2) << endl << endl;
auto a = (int) (double) (12/5);
cout << "a " << a << " " << typeid(a).name() << endl;
auto b = (double) (int) (12/5);
cout << "b " << b << " " << typeid(b).name() << endl;
Результат выполнения приведен на рис. 4.3.
Операции * (умножения) и / (деления) имеют одинаковый приоритет и ассоциативность. Они выполняются слева

52
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
направо. И даже добавление скобок в выражении не меняет
результата. А вот с операцией приведения типа ситуация
a
другая. В приведенном фрагменте две переменные (
auto
саны ключевым словом
. Напомним, что в этом случае
и b) опи-
тип переменной определяется инициализацией. В примере
int
и
используются две инструкции приведения типа
double
Тип переменной назначается инструкцией, записанной слева (ассоциативность справа-налево).
Рис. 4.3. Ассоциативность операций
И в заключение остановимся на одной из важнейших операций – операции присваивания. Операция присваивания
имеет следующий вид:
Переменная = выражение,
где знак «=» – оператор присваивания.
Операция присваивания выполняется следующим образом:
сначала вычисляется выражение (r-значение), стоящее справа,
а затем результат помещается в переменную (l-значение), имя
которой указано слева от знака оператора присваивания.
Хорошим стилем является использование одинаковых типов для r-значения и l-значения. А вот при смешивании элементов разного типа результаты могут отличаться. Рассмотрим пример:
int a = 15/2/2;
int a1 = 15.0/2.0/2.0;
cout << a << " " << a1 << endl;
.

4. Операции (выражения)
53
oat f = 15/2/2;
oat f1 = 15.0/2.0/2.0;
cout << f << " " << f1 << endl;
int b = (oat)15/2;
int b1 = ( (oat)15 )/2;
cout << b << " " << b1 << endl;
Результат выполнения приведен на рис. 4.4.
Рис. 4.4. Разные типы данных в присваивании
Обратим внимание, что при вычислении целочисленных
а
и а1 получается один результат, как и при вычислении f.
f1
А вот при вычислении
(вещественный тип и у r-значения,
и у l-значения) результат другой. В примере с использованием операции приведения типа скобки можно не использо-
oat
вать, так как приоритет (
) выше, чем у деления.
Заметим, что в С++ определена не одна операция присва-
ивания. Есть еще пять:
+=
операция присваивания-сложения;
–=
операция присваивания-вычитания;
*=
операция присваивания-умножения;
/=
операция присваивания-деления;
%=
операция присваивания-остатка от деления.
Рассмотрим пример:
int i=1;
i+=2;
cout << i;
Результатом выполнения будет число 3. То есть запись
i+=2;
эквивалентна инструкции
i=i+2;
.

Как уже отмечалось выше, в языке программирования С++
нет встроенных средств для операций ввода-вывода. Они реализуются с использованием средств стандартных библиотек.
Последние можно разделить на две группы: функции в стиле С
или стандартные потоки, описанные в STL. Начнем с потокового ввода-вывода.
Для организации ввода-вывода используются стандартные
потоки:
cin
– стандартный входной;
cout
– стандартный выходной;
cerr
– стандартный выходной поток ошибок;
clog
– стандартный выходной поток ошибок с буфером.
<<
Для их использования применяются операции
торые на самом деле имеют другое основное назначение (сдвиг
вправо и сдвиг влево). Но благодаря описаниям, содержащимся в заголовочном файле iostream, они приобретают новые возможности. В современных технологиях программирования
это называется перегрузкой операторов. Операторы ввода-вывода уже перегружены (в заголовке
ли выполнять операции потокового ввода или вывода данных
любых встроенных С++-типов [31].
Начнем с вывода информации. Примеры использования
cout
и операции вывода ранее уже приводились многократно.
Для форматированного вывода в консоль используются специальные функции, флаги и манипуляторы.
Рассмотрим примеры вывода целых и вещественных чи-
сел.
cout << "1234567890" << "\n"; //1
int a=123; //2
cout.width(6); //3
cout << a << endl; //4
<iostream>
), чтобы они мог-
и >>, ко-

5. Ввод-вывод данных
cout.width(4); //5
cout << a << endl<<endl; //6
cout.setf(ios::xed); //7
cout.precision(3); //8
oat p=3.14; //9
cout.width(6); //10
cout << p << endl; //11
cout.precision(5); //12
cout.width(2); //13
cout << p << endl; //14
cout.precision(5); //15
cout.width(8); //16
cout << p << endl; //17
cout.precision(5); //18
cout.width(12); //19
cout << p << endl; //20
Результат выполнения приведен на рис. 5.1.
55
Рис. 5.1. Форматированный вывод чисел
В первой строке последовательно выводятся цифры от 1
до 0 для наглядной фиксации, в какую позицию будет выведен каждый следующий символ. Например, определенное
в программе целое значение 123 выводится сначала в поле

56
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
длиной 6, а затем в поле длиной 4. В первом случае цифра 1
попала в 4-ю позицию, а во втором – во 2-ю.
Для задания ширины поля вывода значения можно использовать так называемую функцию-член. Для задания ши-
width
рины поля используется
, которая, как и другие, получает свой аргумент в круглых скобках. Как видно из примера,
имя функции записывается после точки. Строки начиная
с 9-й показывают, как форматировать вывод вещественных
чисел. Для последних задается не только размер поля вывода, но и количество знаков в дробной части (
precision
).
Теперь рассмотрим пример с форматированным выводом,
в котором вещественное число выводится в экспоненциальной форме (флаг –
scientic
).
cout << "scientic" << endl;
cout.setf(ios::scientic);
cout.precision(3);
cout.width(6);
oat p1=3.14159;
cout << p1 << endl;
cout.precision(5);
cout.width(8);
p1=0.00314159E+03;
cout << p1 << endl;
p1=314.159E-02;
cout << p1 << endl;
Результат выполнения приведен на рис. 5.2.
Рис. 5.2. Вывод вещественного числа в экспоненциальной
форме

5. Ввод-вывод данных
57
В примерах использована функция
setf
. Он получает
только один аргумент – это строка. В ней указывается имя
одного флага или имена нескольких флагов, соединенных
|
поразрядной логической операцией ИЛИ (символ
). Такие
флаги позволяют установить разнообразные параметры ввода-вывода, например:
cout.setf(ios::scientic | ios::showpos);
приведет к выводу
+3.14159е+000
Здесь задано, что числа нужно выводить в экспоненци-
альной форме со знаком.
А такая инструкция приведет к замене маленьких букв
(по умолчанию) на большие:
cout.setf(ios::scientic | ios::showpos | ios::uppercase);
и обеспечит результат
+3.14159Е+000
(Буква е заменена на Е.)
Отменить действие уже установленного флага можно, ука-
unsetf
зав
.
Опишем еще один манипулятор
ll
. Он заполняет поле
вывода символами. Последние можно задать в одинарных
кавычках или указать его числовой код. В приведенном примере символ «ноль» задан обоими способами.
int a=123;
cout << "ll('0')" << endl;
cout.width(12);
cout.ll(48); // (48)
cout << a << endl;
cout.width(12);
// Надо еще раз указать длину. Иначе нет заполнения
cout.ll('0');
cout << a << endl;
double p=3.14159;
cout << "ll('*')" << endl;
cout.ll('*');

58
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
cout.precision(5);
cout.width(12);
cout << p << endl;
Результат выполнения приведен на рис. 5.3.
Рис. 5.3. Пример использования
Заметим, что в
ll
можно задавать не только константы,
но и переменные:
char g='z'; int c0=48;
for(int i=1; i<10; i++)
{
cout.width(i);
cout.ll(c0);
cout << g << endl;
}
Результат выполнения приведен на рис. 5.4.
Рис. 5.4. Использование переменных в
ll
cout.ll
Еще одним средством, обеспечивающим форматированный
вывод, являются манипуляторы. Они во многом повторяют

5. Ввод-вывод данных
59
возможности флагов, описанных в этом разделе выше. Приведем примеры. Но надо учесть, что для работы с манипуляторами требуются дополнительные описания, например подключе-
iomanip (#include <iomanip>
ние
).
cout << "1234567890" << "\n";
int a=123;
cout << setw(6) << a << endl;
cout << setw(4) << a << endl;
oat p=3.14159;
cout << setw(6) << setprecision(3) << p << endl;
cout << showpos << setw(5) << setprecision(2) << p << endl;
cout << left << setw(10) << setprecision(6) << p << endl;
cout << right << setw(10) << setprecision(5) << p << endl;
cout << setw(12) << setprecision(4) << p << endl;
Результат выполнения приведен на рис. 5.5.
Рис. 5.5. Использование манипуляторов
Для ввода данных с клавиатуры в С++ используется опе-
>>
рация извлечения (
). Приведем пример ее использования.
Здесь надо вести целое и вещественное значения.
int a;
cout << "Input int, for example 123" << endl;
cin >> a;
cout.width(6);
cout << a << endl;
// Если f – int, а ввести 3.14 ОШИБКИ НЕТ, но вывод 3

60
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
oat f;
cout << "Input oat, for example 3.14" << endl;
cin >> f;
cout.width(8);
cout << f << endl;
Как сработает программа показано на рис. 5.6.
Рис. 5.6. Ввод чисел с клавиатуры
Все возможные значения флагов, манипуляторов приве-
дены в [31, 32, 33].
И в заключение покажем, как выводить числа в разных
системах счисления.
int Val=15;
// binary oct hex
cout << bitset<4>(Val)<< endl;
cout << oct << Val << endl;
cout << hex << Val << endl;
Результат:
1111
17
F
С
Кратко опишем ввод и вывод в стиле классического С. За-
метим, что в разных языках программирования (например,
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
