Opakování - datové typy, operátory, ASCII
Tak se zase hlásím! A začnu hned opakováním a pár příklady, ať je jistota, že vše pasuje a sedí 😉.
Dělení
Prohlédněte si následující kód. Dokážete tipnout, jaký bude výstup?
#include <stdio.h>
int main(void) {
float x;
x = 5 / 2;
printf("Výsledek: %.2f\n", x);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Řešení (klikni na šipečku)
Výsledek: 2.00
Pozn.: Format specifier výše udává, že do textu bude vloženo desetinné číslo (f) a že bude omezeno na 2 místa za desetinnou čárkou (.2).
Zkusíte kód přepsat tak, aby byl výsledek správný?
Řešení 2 - upravený kód
#include <stdio.h>
int main(void) {
float x;
x = 5.0 / 2;
printf("Výsledek: %.2f\n", x);
return 0;
}
Stačí, aby jeden z operandů byl desetinným číslem, aby byl i výsledek desetinným číslem! Ideálně si oba prográmky zkuste zkompilovat a spustit. Pro připomenutí (pokud se váš soubor jmenuje ex1.c):
clang ex1.c
clang -Wall -Wextra -pedantic -o ex1 ex1.c
ASCII tabulka
ASCII tabulku jsem krátce zmínila ve druhém díle (První program, datové typy a printf). Tabulku tvoří tisknutelné a netisknutelné znaky a jejich ekvivalent v číselné podobě (desítkové, šestnáctkové a osmičkové soustavě) a jejich HTML znak.

Červeně jsem označila znaky, které nejsou tisknutelné. Schválně si zkuste přeložit a spustit následující kód, případně můj znak nahraďte jiným a koukněte, co se stane (tip: zapněte si zvuky u PC).
#include <stdio.h>
int main(void) {
char a = 7;
printf("Netisknutelný znak %c\n", a);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Věnujte chvíli pozornost tzv. format specifier, který udává, jak má program zpracovat výstup proměnné udané na místě dalších parametrů (prvním parametrem je náš textový řetězec, který může obsahovat takováto rezervovaná místa, která jsou následně ve výstupu nahrazena tím, co následuje za textovým řetězcem). V kódu výše udává %c, že bude (měl by) následovat tzv. character, char, tedy jednotlivý znak.
Co tedy bude výstupem?
Znak s číslem 7 je podle ASCII tabulky *bell*, neboli zvukový signál. Na konzoli se nám tedy zobrazí pouze text Netisknutelný znak , ale měl by být slyšet zvukový signál. Pokud byste v řetězci udali, že má být výstupem číslo, např. pomocí format specifieru %d, pak by nenásledoval žádný zvukový signál, ale na konzoli byste měli vidět text Netisknutelný znak 7. Vyzkoušejte si to! (Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Další ukázkou práce s ASCII tabulkou a znaky by mohl být následující program. Zkuste si nejdřív v hlavě (a za pomocí tabulky) tipnout, co by tak mohlo být výstupem!
#include <stdio.h>
int main(void)
{
int a1 = 0x41; // 0x znamena, ze se nejedna o decimal, ale o hexadecimal
int a2 = 0150; // 0 na zacatku znaci oktal
int a3 = 111;
int a4 = a2 + 2;
int a5 = '!';
printf("%c%c%c%c%c\n", a1, a2, a3, a4, a5);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výstup na konzoli:
Ahoj!
Všimněte si, že znaky jsou také jenom čísla. Můžeme tedy oboje zaměňovat a ukládat do char i int (pozor jenom na rozsah, pokud byste zaměňovali i jinde; u znaků problém zatím nehrozí), a také počty jsou možné.
A pro úplnost, pokud se nad tím někdo podivoval - jednoduché uvozovky slouží pro zápis znaků, dvojité pro textové řetězce.
Operátory
Operátory můžeme dělit podle dvou kritérií:
- kolik operandů potřebují pro danou operaci
- unární (např. inkrement a dekrement)
- binární (např. klasické sčítání, tedy +)
- ternární (zatím neznáme; jedná se o ? : operátor)
- na jaké pozici se nachází
- infix (tak, jak to známe, např. a + b)
- prefix (–a)
- postfix (a++)
Zatím jsme poznali aritmetické, logické, inkrement a dekrement a srovnání. Existují i bitové nebo třeba operátor, kterým se získá adresa proměnné.
Následuje opět pár příkladů. Zkuste si nejdřív v hlavě promyslet, co by mohlo být výsledkem.
Aritmetické operátory
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 4;
printf("a = %d, b = %d\n\n", a, b);
printf("%d\n", a / b);
printf("%d\n", a % b);
printf("%d\n", a += b);
printf("%d\n", a /= b);
printf("\na = %d, b = %d\n", a, b);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výstup na konzoli:
a = 5, b = 2
2
1
7
3
a = 3, b = 2
Procento je tzv. modulo operátor, jehož výsledkem je zbytek celočíselného dělení. 5 / 2 je 2, zbytek 1.
Následují zkrácené verze početních operací. Např. a += b je to samé jako a = a + b. Tudíž výstupem bude nejdříve 7 (protože a je nyní 5 + 2), potom 3 (protože 7 / 2 je 3, cokoli za desetinnou čárkou je zahozeno). První dva printf nezměnili hodnotu skrytou za proměnnou a nebo b!
Poslední řádek slouží už jenom pro úplnost a vytiskne obsah proměnných a, b.
Logické operátory a srovnání
Zkusíte si tipnout, co bude výsledkem?
#include <stdio.h>
int main(void) {
int a = 5;
int b = 2;
int c = (b != 0) && (a / b);
printf("%d\n", c);
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výsledek:
1
Snažte se vždy vyvarovat srovnávání desetinných čísel. Počítač ne vždy počítá s přesností, na jakou jsme zvyklí. I proto máme možnost využít float či double (double má 2x takovou přesnost). Pokud se dostanete do situace, že budete srovnávat desetinná čísla, použijte k tomu nějaké epsilon, hodnota v rámci které je srovnání ještě OK (např. +/- 0.00000001, při srovnání dvou čísel a, b by to vypadalo následovně: a > b - epsilon && a < b + epsilon; pokud by obě podmínky byly splněny, hledělo by se na a a b jako na dvě stejná čísla).
Ale pryč od teorie. Schválně si to vyzkoušejte.
#include <stdio.h>
int main(void) {
float a = 0.9f;
printf("%d\n", a == 0.9);
printf("%d\n", a == 0.9f);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výsledek:
0
1
#include <stdio.h>
int main(void) {
int a = 0;
int b = 1;
int c = a || (a || b) && (a > b);
printf("%d\n", c);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výsledek:
0
Inkrement a dekrement
Jako i předtím - představím kód a vy si zkuste v hlavě projít, co by asi tak mohlo být výsledkem.
#include <stdio.h>
int main(void) {
int a = 1;
int b = 1;
printf("a = %d, b = %d\n", a, b);
printf("%d\n", a++ + --b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výsledek:
a = 1, b = 1
1
a = 2, b = 0
#include <stdio.h>
int main(void) {
int a = 1;
int b = 1;
int c = 1;
printf("a = %d, b = %d, c = %d\n", a, ++b, c++);
printf("c = %d\n", c);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výsledek:
a = 1, b = 2, c = 1
c = 2
Overflow a underflow
Již jsem zmínila nahoře, že je třeba dbát na možný rozsah jednotlivých datových typů. Téma již jsem načla i v předposlední kapitole, kód je k nalezení na GitHubu. Zkoušeli jste, co se stane, pokud povolený rozsah přesáhnete?
#include <stdio.h>
int main(void) {
unsigned char a = 0;
a -= 1;
printf("%d\n", a);
char b = 127;
printf("%d\n", b + 1);
char c = 567;
printf("%d\n", c);
return 0;
}
(Kód je jako vždy k nalezení i na GitHubu a to pod následujícím odkazem)
Výsledek:
255
128
55
Pokud se dostanete přes povolený rozsah, jedná se o overflow. Pokud pod něho, pak se mluví o underflow.
Snad je to takhle vše pochopitelné (a kdyby ne, klidně se mi ozvětě na Discordu) 🙃.