Преговор - УПП, Седмица 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, иначе връща 03 & 5 = 1 b0011 & b0101 = b0001
Побитово “или”,
|
: за два бита, ако и двете са 0, връща 0, иначе връща 13 | 5 = 7 b0011 | b0101 = b0111
Изключващо “или”,
^
: ако само един от двата бита е 1, връща 1, иначе връща 03 ^ 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;
}