Простейшие средства ввода/вывода

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

// используются классы стандартной библиотеки

#include <iostream> // 1

using namespace std; // 2

int main() // 3

{ const double course = 35.8; // 4

double sum; // 5

cout << "Введите сумму в рублях:\n"; // 6

cin >> sum; // 7

double euro = sum / course; // 8

cout << "В рублях: " << sum

<< " В евро: " << euro

<< "\n"; // 9

return 0; // 10

}

Листинг 2.1. Программа перевода рублей в европейскую валюту (html, txt)

Это первый пример законченной программы, поэтому рассмотрим его подробно. В первой строке записана директива препроцессора. Директива вида

#include <имя_файла>

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

Строка 2 является описанием, по которому программе становятся доступными все имена, определенные в стандартном заголовочном файле <iostream>. Дело в том, что внутри этого файла все описания спрятаны в так называемую поименованную область (пространство имен) с именем std. Это касается всех стандартных заголовочных файлов и сделано для того, чтобы стандартные имена не конфликтовали с теми, которые ввел программист.

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

Формат основных функций ввода-вывода, унаследованных из С:

int scanf ( строка_формата, список адресов вводимых величин ) // ввод

int printf( строка_формата, список выводимых величин ) // вывод

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

Спецификация %d означает целое десятичное число, %f используется для величин типа float, %lf - для величин типа double. Оператор в строке 9 выводит на экран указанную в нем строку, заменив спецификации преобразования %lf на значения переменных sum и euro.

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

Выражения

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

( a + 0.12 ) / 6

x && y || ! z

( t * sin( x ) - 1.05e4 ) / ( ( 2 * k + 2 ) * (2 * k + 3 ) )

a = b = c

b++

cout << a

i++, j++

Операнды задают данные для вычислений. Операции задают действия, которые необходимо выполнить. Каждый операнд является, в свою очередь, выражением или одним из его частных случаев, например, константой или переменной. Операции выполняются в соответствии с приоритетами. Для изменения порядка выполнения операций используются круглые скобки. Уровень их вложенности не ограничен.

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

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

Если в одном выражении записано несколько операций одинакового приоритета, то унарные операции, условная операция и операции присваивания выполняются справа налево, остальные - слева направо. Например, a = b = c означает a = (b = c), а a + b + c означает ( a + b) + c.

Порядок вычисления операндов в выражении не определен: например, нельзя считать, что в выражении (sin(x + 2) + cos(y + 1)) обращение к синусу будет выполнено раньше, чем к косинусу. Только четыре операции гарантируют порядок вычислений слева направо: ,, ?:, && и ||.

Операции присваивания ( =, +=, -=, *= и т. д.). Формат операции простого присваивания ( = ):

операнд_1 = операнд_2

Левым операндом должно быть L -значение, а правым - любое выражение. Сначала вычисляется выражение, стоящее в правой части операции, а потом его результат записывается в область памяти, ссылка на которую стоит в левой части (мнемоническое правило: "присваивание - это передача данных "налево""). В простейшем и наиболее распространенном случае левый операнд представляет собой переменную, куда и записывается вычисленное значение. То, что ранее хранилось в этой переменной, естественно, теряется.

Если тип значения, полученного в результате вычисления, не совпадает с типом левого операнда, то выполняется преобразование типа по умолчанию (об этом - в конце этой лекции).

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

Результат выражения с присваиванием является L -значением, поэтому выражение с присваиванием может быть аргументом другой операции присваивания. Таким образом, допустимы многократные присваивания вида a = b = c: сначала вычисляется выражение b = c, а затем его результат становится правым операндом для операции присваивания переменной a.

Выражения с операциями присваивания могут использоваться и как самостоятельные операторы. Для этого нужно после выражения поставить точку с запятой. Пример операции присваивания:

#include <iostream>

using namespace std;

int main()

{ int a = 3, b = 5, с = 7; // инициализация

a = b; b = a; с = с + 1; // присваивание

cout << "a = " << a

<< "\t b = " << b

<< "\t c = " << c;

с = a + ( b = 5 );

cout << "\t c = " << c;

}

Результат работы программы:

a = 5 b = 5 c = 8 с = 10

В составных операциях присваивания ( +=, *=, /= и т. п.) при вычислении выражения, стоящего в правой части, используется и L -значение из левой части. Например, при сложении с присваиванием к значению левого операнда прибавляется значение правого, и результат записывается в левый операнд. Таким образом, выражение a += b является более компактной записью выражения a = a + b.

Операции увеличения и уменьшения на 1 ( ++ и -- ). Эти операции, называемые также инкрементом и декрементом, имеют две формы записи - префиксную, когда операция записывается перед операндом, и постфиксную. В префиксной форме сначала изменяется операнд, и новое значение является результатом операции. В постфиксной форме значением выражения является исходное значение операнда, после чего он изменяется:

#include <cstdio>

using namespace std;

int main()

{ int x = 3, y = 3;

printf( "Значение префиксного выражения: %d \n", ++x );

printf( "Значение постфиксного выражения: %d \n", y++ );

printf( "Значение х после приращения: %d \n", x );

printf( "Значение у после приращения: %d \n", у );

}

Результат работы программы:

Значение префиксного выражения: 4

Значение постфиксного выражения: 3

Значение х после приращения: 4

Значение у после приращения: 4

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

Операции отрицания ( -,!). Арифметическое отрицание (унарный минус -) изменяет знак операнда целого или вещественного типа на противоположный. Логическое отрицание ( !) дает в результате значение false, если операнд есть true, и значение true, если операнд равен false. Операнд может быть арифметического типа. В этом случае выполняется неявное преобразование в тип bool.

Деление ( / ) и остаток от деления ( % ). Операция деления применима к операндам арифметического типа. Если оба операнда целочисленные, результатом операции является целая часть частного (дробная часть отсекается). Например, результатом 5/2 будет 2. Если же хотя бы один операнд вещественный, то и результат будет вещественным числом. В этом случае тип результата определяется правилами преобразования типов, которые рассмотрены в следующем разделе. Операция остатка от деления применяется только к целочисленным операндам. Знак результата зависит от реализации.

#include <cstdio>

using namespace std;

int main()

{int x = 11, y = 4;

float z = 4;

printf( "Результаты деления: %d %f \n", x / y, x / z );

printf( "Остаток: %d \n", x % y );

}

Результат работы программы:

Результаты деления: 2 2.750000

Остаток: 3

Операции отношения (<, <=, >, >=, ==, !=) сравнивают первый операнд со вторым. Операнды могут быть арифметического типа или указателями. Результатом операции является значение true или false. Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции сравнения.

Логические операции (&& и ||). Операнды логических операций И (&&) и ИЛИ (||) должны иметь тип, допускающий преобразование к типу bool, при этом операнды в одной операции могут быть различных типов. Результатом операции является true или false. Результат операции логическое И имеет значение true только если оба операнда имеют значение true. Результат операции логическое ИЛИ имеет значение true, если хотя бы один из операндов имеет значение true. Логические операции выполняются слева направо. Если значения первого операнда достаточно, чтобы определить результат операции, второй операнд не вычисляется.

Условная операция ( ?:).Эта единственная в С++ тернарная операция (имеет три операнда), ее формат:

операнд_1 ? операнд_2 : операнд_3

Операнды вычисляются слева направо. Результат вычисления первого операнда должен быть типа, который можно преобразовать к типу bool. Если результат равен true, то результатом выполнения всей условной операции будет значение второго операнда, иначе - третьего операнда. Их типы могут быть различными.

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

i = ( i < n ) ? i + 1 : 1;

Операция последовательного вычисления "запятая" (,). Формат операции:

выражение_1, выражение_2

Операция выполняется слева направо: сначала вычисляется выражение слева от знака операции (его результат отбрасывается), а затем вычисляется выражение справа от знака и его результат принимается за результат операции. Вычисление левого выражения обязательно завершается до того, как начнется вычисление правого выражения. Это позволяет присваивать значения переменным в левом выражении, а затем использовать их в правом. Например, результатом операции j = 2, j = 1 будет 1, результатом операции j = 2, j++ будет 2, а результатом операции j = 2, ++j будет 3.

Стандарт разрешает любое выражение заменить последовательностью выражений, разделенных операцией "запятая". Результатом вычисления последовательности выражений будет значение самого правого выражения.

Наши рекомендации