- •Введение
- •План лекции
- •Лекция 1.2. Работа в среде Visual Studio План лекции
- •Практические задания
- •Контрольные вопросы
- •Лекция 2.1. Структура простой программы План лекции
- •Лекция 2.2. Использование функций План лекции
- •Практические задания
- •Контрольные вопросы
- •Тема 3: Переменные и константы Лекция 3.1. Встроенные типы данных. План лекции
- •Лекция 3.2. Константы, перечисления, синонимы типа План лекции
- •Практические задания
- •Контрольные вопросы
- •Тема 4: Операции и выражения Лекция 4.1. Математические операторы и выражения План лекции
- •Лекция 4.2. Логические операторы и выражения. План лекции
- •Практические задания
- •Контрольные вопросы
- •Тема 5: Функции. Лекция 5.1. Личные и встроенные функции. План лекции
- •Основные библиотечные функции c для работы с символьными массивами (string.H)
- •Лекция 5.2. Параметры. Значения по умолчанию. Перегрузка. Рекурсия. План лекции
- •Inline-функции
- •Практические задания
- •Контрольные вопросы
- •Тема 6: Структуры. Классы и объекты. Лекция 6.1. Структуры в языке с. План лекции
- •Лекция 6.2. Классы с открытыми данными. План лекции
- •Лекция 6.3. Конструкторы и деструктор.Cкрытие данных. План лекции
- •Лекция 6.4. Введение в библиотеки классов План лекции
- •Практические задания
- •Контрольные вопросы
- •Тема 7: Циклы, выбор вариантов. Лекция 7.1. Циклы. План лекции
- •Лекция 7.2. Выбор из вариантов. План лекции
- •Практические задания
- •Контрольные вопросы
- •Заключение
- •Литература
- •Содержание
Тема 4: Операции и выражения Лекция 4.1. Математические операторы и выражения План лекции
Пустой оператор и пустые символы
Понятие лексемы
Использование блоков
Операции С++
Унарные и бинарные операции
Математические и логические выражения
Оператор присваивания
Сочетание математических операций с присваиванием
Инкремент и декремент
Приведение типа
Вычисление математических выражений
Приоритет операций
Вычитание беззнаковых целых и переполнение
Ошибки времени выполнения (на примере деления на 0)
Пустой оператор и пустые символы
Все операторы в С++ заканчиваются точкой с запятой. Точка с запятой – пустой оператор, не выполняющий никаких действий. Пустые символы (пробелы, табуляторы, символы новой строки) компилятором игнорируются. Везде, где допустим один пробел, вы может поставить сколько угодно пробелов.
// Пример 4.1.1
//Использование пустых символов - так писать можно, но не рекомендуется!!!
#include <iostream>
using namespace std;
int main() {
int a=0, b=0, y=35; double x=0, z=7.5; cout << "a:" <<
a << " b:" << b << endl; cout << "x:" << x
<< " y:" << y << " z:" << z << endl;
a
=
9
;
b
=
7; cout << " x:" << x
<< " y:" << y
<< endl;
cin.get();
return 0;
}
// Пример 4.1.2
//Использование пустых символов - лучше записать так!!!
#include <iostream>
using namespace std;
int main() {
int a=0, b=-9, y=35;
double x=0, z=7.5;
cout << "a:" << a << " b:" << b << endl;
cout << "x:" << x << " y:" << y << " z:" << z << endl;
a=9; b=7;
cout << " x:" << x << " y:" << y << endl;
// логическая ошибка
if (a <= b); // ; - ничего не делать!
cout << "a<b\n"; // не относится к if
// логическая ошибка
for (int i=0; i<5; i++); // ; - ничего не делай в цикле!
cout << "H e l l o!"; // не в цикле
cin.get();
return 0;
}
Понятие лексемы
Компилятор в тексте программы выделяет лексемы – минимальные единицы языка, имеющие смысл, и на их основе выполняет проверку синтаксических ошибок. Лексемой может быть : ключевое слово, неименованная константа, имя переменной, константы, функции, обозначение операции и т.д. Пробелы внутри лексем недопустимы.
Использование блоков
Везде, где можно поставить одиночный оператор, вы можете поставить составной оператор – блок. Блок - последовательность одиночных операторов, заключенных между фигурными скобками - { оператор1; оператор2; … оператор n; } . В С++ блок определяет область видимости и время жизни объекта . Переменные, объявленные внутри блока являются локальными.
// Пример 4.1.3
// Использование блоков
#include <iostream>
using namespace std;
int main() {
// локальные переменные функции main()
int a=1, b=2, c=a+b;
cout << "a=" << a << " b=" << b << " c=" << c << endl;
cin.get();
// это блок - в нем объявлены блочные локальные переменные
{
int a=2, b=3, c=a+b;
cout << "a=" << a << " b=" << b << " c=" << c << endl;
}
cin.get();
cout << "a=" << a << " b=" << b << " c=" << c << endl;
cin.get();
return 0;
}
Операции С++
Операция – это символ, который заставляет компилятор выполнить действие. В С++ выделяют следующие основные категории операций:
операция присваивания (=);
математические операции ( +, -, *, /, % );
сочетание присваивания и операций ( +=, - =, *=, /=, %= );
инкремент и декремент (префиксный и постфиксный) ( ++, – – );
операция приведения типа ( (имя_типа) );
операции отношения ( >, <, >=, <=, != (не равно) , = = (равно) );
логические операции (&& (и) , || (или), ! (не));
получить адрес (& );
получить значение по адресу (разадресация) ( * );
оператор индексации ( [ ] );
оператор видимости ( : : );
оператор прямого доступа к объекту ( . );
оператор косвенного доступа к объекту ( –> );
оператор вызова функции ( () );
операторы вставки и извлечения в поток ( << , >> );
побитовые операции ( &, !, ^, ~,>>,<< ) и т.д.
Унарные и бинарные операции
Операция называется унарной, если в ней принимает участие один операнд (минус перед числом или именем переменной, ++, – – , & (адрес), * (разадресация)). Бинарная операция – операция с двумя операндами ( +, -, *, /, % ).
// Пример 4.1.4
// Унарные и бинарные операции
#include <iostream>
using namespace std;
int main() {
setlocale( LC_ALL, "Russian"); // для вывода на экран русского текста
int a=1, b=2, c=0;
// ++, --, -, &(адрес) - это примеры унарных операций
c++;
c=-c;
cout << "адрес a=" << &a << "\tзначение а=" << a << endl;
cout << "адрес b=" << &b << "\tзначение b=" << b << endl;
cout << "адрес c=" << c << "\tзначение c=" << c << endl;
cin.get();
// +, - - это примеры бинарных операций
a=a+2; // + - бинарная операция сложение
c=a-b; // - бинарная операция вычитания
cin.get();
return 0;
}
Математические и логические выражения
Все, что может быть вычислено в С++ называется выражением. Выражения бывают математические и логические. Выражение всегда возвращает значение. Математическое выражение возвращает числовое значение, а логическое - «истину» (1) или «ложь» (0).
// Пример 4.1.5
// Математические и логические выражения
#include <iostream>
using namespace std;
int main() {
int a=2, b=3, c=0;
//математическое выражение возвращает числовое значение
c=a+b;
cout << "c=" << c << endl;
//логическое выражение возвращает 0/1 (false/true, ложь/истину)
c=a!=b;
cout << "c=" << c << endl;
cin.get();
return 0;
}
Оператор присваивания
Операция присваивания (=) изменяет значение операнда находящегося с левой стороны от знака = (lvalue) на значение операнда, находящегося справа от = (rvalue). Lvalue-это обязательно имя переменной. Rvalue может быть константой, именем или выражением. Множественное присваивание выполняется справа налево.
// Пример 4.1.6
// Присваивание
#include <iostream>
using namespace std;
int main() {
const double Qe=-1.6e-19; // инициализация константы обязательна
double result=0, r1=0,r2=0,r3=0; // инициализация
r1=0; r2=0; r3=0; // обычное присваивание
r1=r2=r3=0; // множественное присваивание выполняется справа налево!!!
//Qe=0; // Ошибка! Константу изменить нельзя!!!
//10.5=result; // Ошибка! Lvalue - обязательно имя
result=10.5; // Rvalue - числовая вещественная константа
cout << "Result=" << result << endl;
result=Qe; // Rvalue - имя другой величины
cout << "Result=" << result << endl;
result=Qe*Qe*Qe; // Rvalue - выражение
cout << "Result=" << result << endl;
r1=r2=r3=result/3.; // множественное присваивание
cout << "r1=" << r1 << "\tr2=" << r2 <<"\tr3=" << r3 << endl;
cin.get();
return 0;
}
Сочетание математических операций с присваиванием
Любую математическую операцию можно сочетать с присваиванием. Операторы myAge=myAge +2; и myAge+=2; эквивалентны.
// Пример 4.1.7
// Сочетание присваиваний и математических операций
#include <iostream>
using namespace std;
int main() {
int TestValue=10;
int a=2;
TestValue+=5; // TestValue=TestValue+5
cout << "TestValue=" << TestValue << endl;
TestValue*=a; // TestValue=TestValue*a;
cout << "TestValue=" << TestValue << endl;
TestValue-=3; // TestValue=TestValue-3;
cout << "TestValue=" << TestValue << endl;
TestValue/=2; // TestValue=TestValue/2;
cout << "TestValue=" << TestValue << endl;
TestValue%=3;
cout << "TestValue=" << TestValue << endl;
cin.get();
return 0;
}
Инкремент и декремент
Операции инкремент и декремент увеличивают/уменьшают значение переменной на единицу. Операторы myAge++; myAge=myAge+1; и myAge+=1; эквивалентны. Префиксность/постфикность важны в выражениях и определяют что выполнить сначала : инкремент/декремент, а затем участвовать в вычислениях или наоборот.
// Пример 4.1.8
// Использование инкремента и декремента
#include <iostream>
using namespace std;
int main() {
int myAge=33, yourAge=33, sumAge=0;
cout << "myAge:\t" << myAge << "\nyourAge:\t" << yourAge << endl;
cin.get();
myAge++; // постфиксный ++
++yourAge; // префиксный ++
cout << "myAge:\t" << myAge << "\nyourAge:\t" << yourAge << endl;
cin.get();
cout << "myAge:\t" << myAge++ << "\nyourAge:\t" << ++yourAge << endl;
cin.get();
cout << "myAge:\t" << myAge << "\nyourAge:\t" << yourAge << endl;
cin.get();
//sumAge=++myAge + yourAge++;
//sumAge=++myAge + ++yourAge;
sumAge=myAge++ + yourAge++;
cout << "sumAge:\t" << sumAge << endl;
cout << "myAge:\t" << myAge << "\nyourAge:\t" << yourAge << endl;
cin.get();
return 0;
}
Приведение типа
Операция приведения типа (type casting) заставляет компилятор изменить тип переменной. Для приведения типа существует два способа : старый С-стиль и новый оператор static_cast :
int a=2; double b, c;
b=(double) a; // старый стиль C
c=static_cast<double>(a); // современный стиль C++
Компилятор часто может выполнять и неявные преобразования типов.
// Пример 4.1.9
//Явные и неявные преобразование типов
#include <iostream>
using namespace std;
int main()
{
unsigned char ch='A';
cout << ch << endl;
//неявное преобразование типов выполняет компилятор
ch=ch+1;
cout << ch << endl;
//явное преобразование типов выполняет программист (стиль С)
ch=(char)((int)ch+1);
cout << ch << endl;
//явное преобразование типов выполняет программист (стиль С++)
ch=static_cast<char>(static_cast<int>(ch)+1);
cout << ch << endl;
cin.get();
return 0;
}
Вычисление математических выражений
Для вычисления промежуточных выражений в сложных формулах компилятор выделяет временные ячейки памяти. Их тип определяется типом операндов. Например, если два операнда целые, то и тип временной ячейки – целый. Если тип числовых операндов различен, то тип временной ячейки такой, как у более сложного операнда. Поэтому возможны ошибочные вычисления на стадии промежуточных расчетов. Это проблема программиста.
// Пример 4.1.10
// Вычисление сложных выражений
#include <iostream>
using namespace std;
int main()
{
int a=0, b=0, y=35;
double x=0, z=7.5;
cout << "a:" << a << " b:" << b;
cout << " x:" << x << " y:" << y << " z:" << z << endl;
a=9; b=7;
y=x=a+b; // a+b - математическое выражение. Для его вычисления
// компилятор использует временную ячейку памяти целого типа // (int temp=a+b;),т.к. оба операнда целые и возвращает ее значение в качестве // результата. Этот результат присваивается справа налево переменным x и y.
cout << "a:" << a << " b:" << b;
cout << " x:" << x << " y:" << y << endl;
y=x=a+z; // a+z - математическое выражение. Для его вычисления
// компилятор использует временную ячейку памяти вещественного типа
// (double temp=a+b;), т.к. второй операнд вещественный и возвращает ее
// значение в качестве результата. Этот результат присваивается справа налево // переменным x и y. При этом происходит усечение дробной части на стадии
/ / присвоения.
cout << "Temporary value a+z=" << (a+z) << endl;
cout << "x:" << x << " y:" << y << endl;
cin.get();
return 0;
}
// Пример 4.1.11
// Потеря дробной части на стадии промежуточных вычислений
#include <iostream>
using namespace std;
int main() {
// Вычисление параметров шара
const double PI=3.14; // константа PI
const double k=0.01; // коэффициент для перевода мм. в см.
double R=1.5; // радиус, мм
double Ro=7.8; // плотность, г/см^3
double C=0; // длина окружности, см
double S=0; // площадь окружности, см^2
double V=0; // объем шара, см^3
double VErr=0; // неправильно вычисленный объем шара, см^3
double M=0; // масса шара, г
double MErr=0; // неправильно вычисленная масса шара, г
C=2*PI*R*k;
S=PI*R*R;
//PI=3.1; // значения констант изменять нельзя!!!
VErr=4/3*PI*R*R*R; // 4/3-неправильно! ->целый тип->потеря дробной части
//V=4./3*PI*R*R*R; // 4./3.-правильно!->вещ.тип->потери дробной части нет
//V=(double)4/3*PI*R*R*R;// правильно!->вещ.тип->потери дробной части нет
V=4*PI*R*R*R/3; // правильно!->вещ.тип->потери дробной части нет
MErr=Ro*VErr;
M=Ro*V;
cout << "R=" << R << '\t' << "Ro=" << Ro << endl;
cout << "C=" << C << '\t' << "S=" << S << endl;
cout << "VErr=" << VErr << '\t'<< "MErr=" << MErr << endl;
cout << "V=" << V << '\t'<< "M=" << M << endl;
cin.get();
return 0;
}
Приоритет операций
Все выражения вычисляются слева направо с учетом приоритета математических операций. Для изменения приоритета используются круглые скобки. Круглые скобки могут быть вложенными.
// Пример 4.1.12
// Приоритеты и скобки
#include <iostream>
using namespace std;
int main() {
setlocale( LC_ALL, "Russian"); // для вывода на экран русского текста
// Вычисление средней зарплаты трех человек
int z1=100, z2=150, z3=120; // зарплата трех человек
int isz; //средняя зарплата(int-неправильно->возможна потеря дробной части)
double dsz; // средняя зарплата (double - правильно)
isz=z1+z2+z3/3; // неправильно : делится на 3 только z3!!!
cout << "Ошибка! isz=" << isz << endl;
isz=(z1+z2+z3)/3.; // неправильно : потеря дробной части при присваивании!!!
cout << "Ошибка! isz=" << isz << endl;
dsz=(z1+z2+z3)/3; //неправильно : потеря дробной части до присваивании!!!
cout << "Ошибка! dsz=" << dsz << endl;
dsz=(z1+z2+z3)/3.; //правильно 3. - double константа
cout << "ПРАВИЛЬНО! dsz=" << dsz << endl;
dsz=(double)(z1+z2+z3)/3; //правильно -- преобразование C-стиля
cout << "ПРАВИЛЬНО! dsz=" << dsz << endl;
dsz=static_cast<double>(z1+z2+z3)/3; //правильно -- преобразования С++-стиля
cout << "ПРАВИЛЬНО! dsz=" << dsz << endl;
cin.get();
return 0;
}
Вычитание беззнаковых целых и переполнение
При выполнении вычитания беззнаковых целых возможно целочисленное переполнение, если от меньшего вычесть большее число.
// Пример 4.1.13
// Вычитание и целочисленное переполнение беззнаковых целых
#include <iostream>
using namespace std;
int main() {
setlocale( LC_ALL, "Russian"); // для вывода на экран русского текста
// переполнение беззнакового целого при вычитании
unsigned int difference=0, bigNumber=100, smallNumber=50;
difference=smallNumber - bigNumber;
cout << "\nРазность = " << difference;
difference+=500;
cout << "\nРезультат = " << difference;
cin.get();
return 0;
}
Ошибки времени выполнения (на примере деления на 0)
При делении на 0 возникает ошибка времени выполнения (run time error). // Пример 4.1.14
// Деление на 0
#include <iostream>
using namespace std;
void main() {
setlocale( LC_ALL, "Russian"); // для вывода на экран русского текста
int a=1, b=0, c=0;
cout << "a=" << a << " b=" << b << " c=" << c << endl;
cin.get();
// run time error
c=a/b; // деление на 0
cout << "a=" << a << " b=" << b << " c=" << c << endl;
cin.get();
if (b == 0) {
cout << "Деление на 0!!!" << endl;
cin.get();
return;
}
else c=a/b;
cout << "a=" << a << " b=" << b << " c=" << c << endl;
cin.get();
}