# Преговор - УПП, Седмица 2, 13.10.2023 \n [$presentation-controller] :title_slide # Конвертиране на данни, побитови оператори, условни оператори :slide ## Конвертиране на данни [$br3] :unordered - Неявно (скрито, експлицитно): компилаторът сам се досеща да промени типа ```cpp int a = 5; double b = a; - Явно (изрично, експлицитно): казваме как типът да се конвертира ```cpp double a = 5.7, b = 3.42; int m = (int)a + (int)b; :slide [$br5] :unordered - Със загуба на информация (от по-голям тип в по-малък) ```cpp double a = 5.8371; int b = a; - Без загуба на информация (от по-малък тип в по-голям) ```cpp int a = 1000; long b = a; :slide ## Побитови оператори .p Първо ще ги погледнем чисто теоретично. .p =[Внимавайте, те са различни от логическите оператори!]= .p =[Означавам побитовите числа с водеща буква "b"!]= Тоест, числото `[b1001]` е двоичното число `[1001]`, което е десетичното число `[9]`. [$br3] :unordered - Отрицание/негация, `[~]`: обръща 0 в 1 и 1 в 0 ``` ~ b0010 = b1101 :slide :unordered - Побитово "и", `[&]`: за два бита, ако и двете са 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 :middle_slide27 :unordered - Побитово отместване на ляво, `[<<]`: отмества всеки бит с n позиции на ляво\n Винаги "запълва" с нули (няма разлика между логическо и аритметично ляво отместване) ``` b1010 << 1 = b0100 b0001 << 3 = b1000 (приемаме, че типа данни съхранява само 4 бита данни) - Побитово отместване на дясно, `[>>]`: отмества всеки бит с n позиции на дясно\n При аритметичното отместване, дупките се запълват с предходната стойност на старшия бит\n При логическото отместване, винаги запълваме с 0\n В C++ има един оператор, дали е аритметическо или логическо се определя от типа ``` b1000 >> 1 = b0100 или пък b1100 b1010 >> 3 = b0001 или пък b1111 :middle_slide Примери с код: :code_cpp 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 :slide ## Логически оператори .p Много приличат на побитовите, обаче побитовите работят върху битове, докато логическите работят върху bool. [$br4] :unordered - `[!]`: обръща `[true]` във `[false]` и обратно ```cpp ! true // false ! false // true :middle_slide :unordered - `[&&]`: "логическо и", ако и двете стойности са `[true]`, тогава и резултатът е `[true]` ```cpp true && true // true false && true // false false && false // false - `[||]`: "логическо или", само ако и двете са `[false]`, тогава е `[false]` ```cpp true || true // true false || true // true false || false // false :slide ## Условни конструкции :unordered - `[if]`: приема булева стойност, ако е `[true]`, изпълнява кода в къдравите скоби, ако е `[false]` ги пропуска ```cpp if (expression) { dosomething; } dootherthing; `[expression]` се конвертира към типа `[bool]`\n Ако в къдравите скоби имаме един израз (тоест е само един ред код, завършващ на `[;]`) можем да ги пропуснем. ```cpp if (expression) dosomething; dootherthing; :middle_slide25 :unordered - `[if-else]`: работи като `[if]`, обаче след къдравите скоби добавяме `[else { ... }]`. ```cpp if (expression) { dothing1; } else { dothing2; } dootherthing; .p Ако `[expression]` е истина, `[dothing1]` се изпълнява и `[dothing2]` се пропуска изцяло. Аналогично, ако `[expression]` е лъжа, `[dothing1]` се изпуска и `[dothing2]` се изпълнява. .p Както с `[if]`, ако `[dothing2]` е само един израз, можем да пропуснем къдравите скоби ```cpp if (expression) { dothing1; } else dothing2; dootherthing; :slide25 :unordered - благодарение на изпускането на къдрави скоби, можем да пишем ```cpp if (expression1) { doSomething1; } else if (expression2) { doSometing2; } ... else { doSomethingN; } Това е еквивалентно на: ```cpp if (expression1) doSomething1; else { if (expression2) doSomething2; else { ... else doSomethingN; } } :slide :unordered - `[expression]` винаги се конвертира до тип `[bool]` (ако е нужно)\n =[Никога не правете такива неща:]= ```cpp bool a; if (expression) a = true; else a = false; ```cpp bool a = false; if (expression) a = true; Просто правите `[bool a = expression;]` ```cpp bool a; if (expression) a = false; else a = true; Просто правите `[bool a = ! expression;]` :slide :unordered - Тернарен оператор: ако искате да имате такава условна конструкция като част от израз (който взема стойност) използвате ```cpp (expression) ? valueA : valueB Ако `[expression]` е истина, връща се `[valueA]`, иначе се връща `[valueB]` ```cpp int grade; std::cin >> grade; double a = (grade < 300) ? 2.0 : grade / 100.0; Има много нисък приоритет, в повечето случаи ще ви се наложи да го оградите в скоби. ```cpp int grade; std::cin >> grade; std::cout << ((grade < 300) ? 2.0 : grade / 100.0); :middle_slide27 :unordered - `[switch]`: приема стойност и изпълнява случая, при който стойността съвпада с определената ```cpp switch (value) { case valueA: doSomething1; break; case valueB: doSomething2; break; case valueC: doSomething3; break; } Служи като улеснение на синтаксиса: ```cpp if (value == valueA) doSomething1; else if (value == valueB) doSomething2; else if (value == valueC) doSomething3; .p `[otherwise]` е като `[else]`, това е случая когато не съвпада с никоя стойност. Може да бъде изпуснат. .p Без `[break]` изпълнението продължава към следващия `[case]` :middle_slide ```cpp 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; }