- •Конспект лекций Часть 1 Оглавление
- •Часть 1 1
- •Введение
- •1. Этапы и проблемы решения задач с использованием компьютера
- •Алфавит языка
- •Ключевые слова
- •Идентификаторы
- •Знаки операций
- •Константы
- •Комментарии
- •2.3. Структура и основные элементы программы
- •2.4. Трансляция программ и их выполнение
- •3. Стандартные (базовые) типы данных, операции и выражения
- •3.1. Типы данных, переменные и константы Понятие типов данных
- •Классификация простых предопределенных типов данных
- •Переменные, константы
- •3.2. Целочисленные типы данных
- •3.3. Вещественные типы данных
- •3.4. Логический тип данных
- •3.5. Символьный тип данных
- •3.6. Операции и выражения
- •Преобразования типов данных
- •Операция присваивания
- •Арифметические операции
- •Операции отношения
- •Логические операции
- •Поразрядные (битовые) операции
- •Операции составного присваивания
- •Условная операция
- •Операция sizeof
- •Приоритеты рассмотренных операций
- •3.7. Ввод и вывод простых типов данных
- •Вывод текстовых строк
- •Ввод/вывод арифметических типов данных
- •Форматирование ввода / вывода
- •4.1. Идеи структурного программирования
- •Условная инструкция (if)
- •Инструкция множественного выбора (switch)
- •Цикл с предусловием (while)
- •Цикл с постусловием (do while)
- •Итерационный цикл (for)
- •Инструкции перехода
- •5. Приемы программирования циклов
- •5.1. Рекуррентные вычисления
- •5.2. Инвариант цикла
- •6. Массивы
- •6.1. Понятие массива
- •6.2. Объявление массивов Объявление одномерных массивов
- •Объявление многомерных массивов
- •6.3. Ввод-вывод массивов
- •Вывод массивов
- •Ввод массивов
- •6.4. Текстовые строки как массивы символов
- •Определение текстовой строки
- •Ввод текстовых строк с клавиатуры
- •Обработка текстовых строк
- •Массивы текстовых строк
- •7. Разработка программ при работе с массивами
- •Не успел дописать. Некоторые примеры по этому разделу в Приложениях
Операция присваивания
Одна из наиболее часто используемых операций. Формат операции:
<Переменная> = <Выражение>
| |
Операнд 1 Операнд 2
Например: a = b; b = 3 * a; c = 1.234;
Сначала вычисляется значение выражения с правой стороны, а затем полученное значение присваивается переменной в левой части операции (значение выражения записывается в область памяти переменной). Старое значение переменной при этом безвозвратно теряется.
При выполнении операции присваивания тип значения выражения автоматически преобразуется к типу левого операнда (к типу данных переменной в левой части). При этом возможны потери данных или точности (см. явное преобразование типов). Например:
#include <iostream>
using namespace std;
int main()
{
int i = 100000, k;
short j = 10000, m;
k = j; // Короткое целое преобразуется к целому без потерь
m = i; // Преобразование целого к короткому целому приводит к искажению данных
cout << k << " " << m << endl; // На экран будет выведено: 10000 -31072
k = 12500;
m = k; // Потери данных нет
cout << k << " " << m << endl; // На экран будет выведено: 12500 12500
double d = 1.8234, n1, n2;
n1 = i; // Без ошибок
n2 = j; // Без ошибок
k = d; // С потерей точности
j = d; // С потерей точности
/* На экран будет выведено: 100000 10000 1 1 */
cout << n1 << " " << n2 << " " << k << " " << j << endl;
d = 1e+100;
k = d; // С потерей данных
m = d; // С потерей данных
/* На экран будет выведено: 1е+100 -2147483648 0 */
cout << d << " " << k << " " << m << endl;
system("Pause");
return 0;
}
Операция присваивания в свою очередь является выражением, значением которого является значение переменной в левой части после присваивания (эту переменную часто называют L-значением (от слова left – левая сторона)). Например:
#include <iostream>
using namespace std;
int main()
{
int i = 7, j = 30, k;
cout << i * j << endl;
cout << (k = i * j) << endl;
cout << k << endl;
system("Pause");
return 0;
}
Результат работы программы:
210
210
210
Благодаря тому, что операция присваивания является выражением, в языке C++ возможно множественное присваивание:
<Переменная1> = <Переменная2> = … = <ПеременнаяN> = <Выражение>
Например:
#include <iostream>
using namespace std;
int main()
{
int i = 7, j = 30, k, l, m, n;
k = l = m = n = i + j;
cout << k << " " << l << " " << m << " " << n << " " << endl;
system("Pause");
return 0;
}
Результат работы программы:
37 37 37 37
Операция присваивания имеет самый низкий приоритет.
Арифметические операции
Унарный плюс (+) и унарный минус (-) Единственный операнд любого арифметического типа. Формат записи:
+ < Выражение >
- < Выражение >
Унарный плюс возвращает значение операнда без изменений.
Унарный минус (его иногда называют арифметическим отрицанием) меняет знак операнда на обратный.
Умножение - * - бинарная операция. Примеры записи:
a * b 2 * 3 a * 0.56
Операнды могут быть любого арифметического типа данных. Тип данных результата операции определяется правилами неявного преобразования типов.
При выполнении возможен выход реального значения результата за допустимый диапазон значений типа данных – при этом значение результата операции трудно предсказать. Например:
cout << 1000000 * 1000000; // Результат: -727379968
cout << 1е20f * 1e20f; // Результат: 1.#INF – переполнение (+ бесконечность)
cout << 1е20f * -1e20f; // Результат: -1.#INF – переполнение (- бесконечность)
Деление - / - бинарная операция. Примеры записи:
a / b 2 / 3 a / 0.56
Если оба операнда являются целыми, то результат деления будет целым. В этом случае целый результат получается отбрасыванием дробной части от полученного реального значения (не округление). Например:
5 / 3 - результат равен 1.
Если все же в результате выполнения этой операции требуется получить значение с дробной частью, необходимо чтобы хотя бы один из операндов был вещественного типа. Например:
5.0 / 3 или 5 / 3. или 5.0 / 3.0 или 5 / 3f или 5f / 3 или 5f / 3f или
float (5) / 3 или double (5) / 3
Результатом вычисления всех этих выражений будет значение 1.6666… одного из вещественных типов.
Однако, например, выражение double (5 / 3) хотя и будет вещественного типа, но его значение все равно будет равно 1, поскольку сначала будет вычислено выражение в скобках, результат которого будет целого типа и будет равен 1, а затем это значение будет приведено к вещественному типу.
При выполнении операции возможен выход реального значения результата за допустимый диапазон значений типа данных – при этом значение результата операции трудно предсказать. Например:
cout << 1е35f / 0.0001f; // Результат: 1.#INF – переполнение (+ бесконечность)
cout << 1е20f / -0.0001f; // Результат: -1.#INF – переполнение (- бесконечность)
cout << 1е200 / 1e-200; // Результат: 1.#INF – переполнение (бесконечность)
Если первый операнд вещественного типа, то деление на 0 дает значение 1.#INF или -1.#INF. Если же он целого типа, возникает ошибка режима исполнения (деление на 0).
Остаток от деления - % - бинарная операция. Операнды только целого типа. Результат операции целого типа. Например:
5 % 1 - результат 0
5 % 2 - результат 1
5 % 3 - результат 2
5 % 4 - результат 1
5 % 5 - результат 0
5 % 6 - результат 5
…..
Если второй операнд равен 0, возникает ошибка режима исполнения (деление на 0).
Сложение (+) и вычитание (-) – бинарные операции. Операнды могут быть любых арифметических типов данных. Примеры записи:
a + b
a – b
Тип результата операций определяется правилами неявного преобразования типов.
При выполнении операций возможны ошибки переполнения и некорректного преобразования типов данных операндов. Например:
unsigned short n = 0, m;
m = n - 1;
cout << m << endl; // На экран будет выведено 65535
n = m + 1;
cout << n << endl; // На экран будет выведено 0
Инкремент (++) и декремент (--) – унарные операции увеличения и уменьшения операнда на 1 соответственно. Операнд может быть любого арифметического типа данных.
Операции имеют две формы – префиксную (++a, --a) и постфиксную (a++, a--).
Независимо от формы операция инкремента эквивалентна следующему оператору:
a = a + 1;
а операция декремента следующему:
a = a - 1;
Например:
#include <iostream>
using namespace std;
int main()
{
int i = 7, j = 10;
++ i;
j ++;
cout << i << "\t" << j << endl; // На экран выведено 8 11
-- i;
j --;
cout << i << "\t" << j << endl; // На экран выведено 7 10
system("Pause");
return 0;
}
Из примера видно, что разница между префиксной и постфиксной формами этих операций не чувствуется. Действительно в этом примере эти две формы работают одинаково.
Немного изменим текст программы:
#include <iostream>
using namespace std;
int main()
{
int i = 7, j = 10;
cout << ++ i << "\t " << j ++ << endl; // На экран выведено 8 10
cout << i << "\t " << j << endl; // На экран выведено 8 11
cout << -- i << "\t " << j -- << endl; // На экран выведено 7 11
cout << i << "\t " << j << endl; // На экран выведено 7 10
system("Pause");
return 0;
}
Разница между префиксной и постфиксной формами этих операций заключается в том, что при префиксной форме, переменная сначала меняет свое значение, а потом это измененное значение обрабатывается. В постфиксной форме значение переменной сначала обрабатывается и только потом ее значение изменяется на 1.
В первом примере операторы ++ i; j ++; просто изменяют значения переменных i и j без какой-либо другой обработки и только после окончания работы этих операторов на экран выводятся эти измененные значения. Поэтому различие между префиксной и постфиксной формами не чувствуется. То же самое происходит и при выполнении операторов -- i; j--;.
Во втором примере префиксные и постфиксные формы операций инкремента и декремента участвуют в выполнении оператора вывода данных на экран. Поэтому при выполнении префиксных операций сначала происходит изменение значений переменной i, потом эти измененные значения выводятся на экран, а при выполнении постфиксных операций сначала выводятся неизмененные значения переменной j, а уже после этого производятся изменения значения этой переменной.
Еще пример:
#include <iostream>
using namespace std;
int main()
{
int i = 7, j = 10, k;
k = (++ i) + (j --); // Или k = ++ i + j --;
cout << "k = " << k << endl; // k = 18
cout << "i = " << i << endl; // i = 8
cout << "j = " << j << endl; // j = 9
system("Pause");
return 0;
}
А чему будет равно значение переменной k в этих случаях:
int i = 7, k;
k = (i ++) + i;
Здесь k = 14.
int i = 7, k;
k = (++ i) + i;
Здесь k = 16.
int i = 7, k;
k = i + (++ i);
Здесь k = 16.
int i = 7, k;
k = (++ i) + (++ i);
Здесь k = 18.
То есть сначала просматривается все выражение, при каждой встрече операции инкремента (декремента) в префиксной форме выполняется изменение на единицу переменной, а затем вычисляется выражение.
А как интерпретировать такие выражения:
a+++b
a---b
Эти выражения следует интерпретировать так:
(a++) + b
(a--) - b
Но не так:
a + (++b)
a - (--b)
Для более понятной записи текста программы в подобных случаях лучше использовать скобки.