Преговор - УПП, Седмица 2, 13.10.2023
Конвертиране на данни, побитови оператори, условни оператори
Конвертиране на данни
#- Неявно (скрито, експлицитно): компилаторът сам се досеща да промени типа
int a = 5;
double b = a;
double a = 5.7, b = 3.42;
int m = (int)a + (int)b;
- Със загуба на информация (от по-голям тип в по-малък)
double a = 5.8371;
int b = a;
int a = 1000;
long b = a;
Побитови оператори
#Първо ще ги погледнем чисто теоретично.
Внимавайте, те са различни от логическите оператори!
Означавам побитовите числа с водеща буква "b"!
Тоест, числото b1001 е двоичното число 1001, което е десетичното число 9.
- Отрицание/негация,
~: обръща 0 в 1 и 1 в 0
~ b0010 = b1101
- Побитово "и",
&: за два бита, ако и двете са 1, връща 1, иначе връща 0
3 & 5 = 1
b0011 & b0101 = b0001
|: за два бита, ако и двете са 0, връща 0, иначе връща 1
3 | 5 = 7
b0011 | b0101 = b0111
^: ако само един от двата бита е 1, връща 1, иначе връща 0
3 ^ 5 = 6
b0011 ^ b0101 = b0110
- Побитово отместване на ляво,
<<: отмества всеки бит с n позиции на ляво Винаги "запълва" с нули (няма разлика между логическо и аритметично ляво отместване)
b1010 << 1 = b0100
b0001 << 3 = b1000
(приемаме, че типа данни съхранява само 4 бита данни)
>>: отмества всеки бит с n позиции на дясно
При аритметичното отместване, дупките се запълват с предходната стойност на старшия бит
При логическото отместване, винаги запълваме с 0
В C++ има един оператор, дали е аритметическо или логическо се определя от типа
b1000 >> 1 = b0100 или пък b1100
b1010 >> 3 = b0001 или пък b1111
int a = 3, b = 5;
int n1 = ~ a; // -4
int n2 = ~ (unsigned int)a; // 4294967292
int i1 = 3 & 5; // 1
int i2 = 3 | 5; // 7
int i3 = 3 ^ 5; // 6
int l1 = b << 1; // 10
int l2 = b << 3; // 40
int r1 = b >> 1; // 2
int r2 = b >> 2; // 1
int r3 = -b >> 1; // -3
int r4 = (unsigned int)b >> 1; // 2
int r5 = (unsigned int)-b >> 1; // 2147483645
Логически оператори
#Много приличат на побитовите, обаче побитовите работят върху битове, докато логическите работят върху bool.
!: обръщаtrueвъвfalseи обратно
! true // false
! false // true
&&: "логическо и", ако и двете стойности саtrue, тогава и резултатът еtrue
true && true // true
false && true // false
false && false // false
||: "логическо или", само ако и двете са false, тогава е false
true || true // true
false || true // true
false || false // false
Условни конструкции
#if: приема булева стойност, ако еtrue, изпълнява кода в къдравите скоби, ако еfalseги пропуска
if (expression) {
dosomething;
}
dootherthing;
expression се конвертира към типа bool
Ако в къдравите скоби имаме един израз (тоест е само един ред код, завършващ на ) можем да ги пропуснем.
if (expression) dosomething;
dootherthing;
if-else: работи катоif, обаче след къдравите скоби добавяме {` else { ... }}.
if (expression) {
dothing1;
}
else {
dothing2;
}
dootherthing;
Ако expression е истина, dothing1 се изпълнява и dothing2 се пропуска изцяло.
Аналогично, ако expression е лъжа, dothing1 се изпуска и dothing2 се изпълнява.
Както с if, ако dothing2 е само един израз, можем да пропуснем къдравите скоби
if (expression) {
dothing1;
}
else dothing2;
dootherthing;
- благодарение на изпускането на къдрави скоби, можем да пишем
if (expression1) {
doSomething1;
}
else if (expression2) {
doSometing2;
}
...
else {
doSomethingN;
}
Това е еквивалентно на:
if (expression1) doSomething1;
else {
if (expression2) doSomething2;
else {
...
else doSomethingN;
}
}
expressionвинаги се конвертира до типbool(ако е нужно) Никога не правете такива неща:
bool a;
if (expression) a = true;
else a = false;
bool a = false;
if (expression) a = true;
Просто правите bool a = expression
bool a;
if (expression) a = false;
else a = true;
Просто правите bool a = ! expression
- Тернарен оператор: ако искате да имате такава условна конструкция като част от израз (който взема стойност) използвате
(expression) ? valueA : valueB
Ако expression е истина, връща се valueA, иначе се връща valueB
int grade;
std::cin >> grade;
double a = (grade < 300) ? 2.0 : grade / 100.0;
Има много нисък приоритет, в повечето случаи ще ви се наложи да го оградите в скоби.
int grade;
std::cin >> grade;
std::cout << ((grade < 300) ? 2.0 : grade / 100.0);
switch: приема стойност и изпълнява случая, при който стойността съвпада с определената
switch (value) {
case valueA: doSomething1; break;
case valueB: doSomething2; break;
case valueC: doSomething3; break;
}
Служи като улеснение на синтаксиса:
if (value == valueA) doSomething1;
else if (value == valueB) doSomething2;
else if (value == valueC) doSomething3;
otherwise е като else, това е случая когато не съвпада с никоя стойност.
Може да бъде изпуснат.
Без break изпълнението продължава към следващия case
char characterInput;
std::cin >> characterInput;
switch(characterInput) {
case 'h':
case '?': std::cout << "This is a helpful message."; break;
case 'w': std::cout << "Hello World"; break;
default: std::cout << "Error"; break;
}