Proměnná a její uložení v paměti Počítačová paměť - řada buněk uložených za sebou, každá buňka má velikost 1 bajt (byte, B) - buňky jsou očíslovány, tato čísla se nazývají adresy Proměnná - data, se kterými programy pracují jsou ukládána do tzv. proměnných - proměnná = místo v paměti počítače, kde je uložena nějaká informace - může zabírat jednu i více buněk (podle typu proměnné - později) Název proměnné (identifikátor) - označení buňky, ve které je uložena proměnná - pomocí názvu můžeme využívat a měnit hodnotu proměnné, aniž bychom se starali o přesnou adresu, na které je uložená (názvu se také říká symbolická adresa ) 1 bajt (byte, 1B) proměnná s názvem P zabírá jeden bajt paměti a je uložena na adrese 254 proměnná P paměť adresa 250 251 252 253 254 255 256 257 258 259 Jan Hnilica Počítačové modelování I / 2 1
Zákadní typy proměnných - chcete-li vytvořit proměnnou, je nutné kompilátoru oznámit jakého bude typu - tím se určí: kolik místa v paměti se pro ni vyhradí (a tím také rozsah hodnot, které se do ní vejdou) co s ní lze v programu provádět - do jazyka C jsou zakomponovány tyto základní datové typy: URČENÍ TYP POZNÁMKA celá čísla reálná čísla short int (short) int long int (long) float double long double - typy pro uložení a práci s celočíselnými údaji (např. počet studentů ve třídě) - od standardu C99 lze použít i typ long long int - typy pro uložení a práci s reálnými čísly (např. 3.142) - ve skutečnosti lze přesně uložit pouze čísla s konečným desetinným rozvojem (tzv. racionální čísla) znaky char - typ pro práci se znaky (např. a ) Jan Hnilica Počítačové modelování I / 2 2
Definice proměnné v programu - chcete-li v programu používat nějakou proměnnou, musíte ji nejprve definovat definice obsahuje (v tomto pořadí): 1. typ proměnné 2. mezeru 3. název proměnné 4. středník (definice je příkaz a všechny příkazy v C jsou ukončeny středníkem) - příklady definic proměnných: int pocet_aut_v_servisu; char znak; double teplotapacienta; Co se děje při definici? kompilátor vyhradí (alokuje) v paměti potřebné místo pro proměnnou proměnné přidělí název - hodnota proměnné je v této chvíli náhodná pozn. definovat lze i více proměnných (stejného typu) najednou - názvy jednotlivých proměnných jsou pak odděleny čárkou - celý příkaz je opět ukončen středníkem: int a, b; double x, y; Jan Hnilica Počítačové modelování I / 2 3
Přiřazení hodnoty do proměnné - provádí se pomocí operátoru přiřazení = int a, b; // definice dvou proměnných typu int a = 5; // přiřazení hodnoty 5 do proměnné a b = 7; // přiřazení hodnoty 7 do proměnné b a = b; // přiřazení hodnoty a do b (obě proměnné mají teď hodnotu 7) float c; c = -2.165; double d = 6.3; // definice proměnné typu float // přiřazení hodnoty -2.165 do proměnné c // definici a přiřazení lze spojit do jediného příkazu - na levé straně operátoru přiřazení musí být proměnná (proměnná má adresu, na kterou je uložena hodnota z pravé strany) int = 5; // chyba - nelze přiřadit hodnotu do datového typu! - na pravé straně operátoru přiřazení jsme zatím viděli konstanty (5, -2.165) nebo proměnné (b) - obecně je ale na pravé straně výraz (výrazy probereme později) - přiřazení je ukončeno středníkem (jako každý příkaz) Jan Hnilica Počítačové modelování I / 2 4
Přiřazení hodnoty do proměnné int a; // krok 1 a = 12; // krok 2 int b; // krok 3 b = 7; // krok 4 a = b; // krok 5 Co se děje v jednotlivých krocích? krok 1: v paměti se vyhradí prostor pro proměnnou typu int a je pojmenován a, hodnota je zatím neznámá krok 2: do paměti vyhrazené pro a je zapsána hodnota 12 krok 3: jinde v paměti je vyhrazen prostor pro proměnnou b a a 12 a 12 b krok 4: do prostoru pro b je zapsána hodnota 7 krok 5: do prostoru pro a je zapsána hodnota proměnné b a b 12 7 a b 7 7 Jan Hnilica Počítačové modelování I / 2 5
Konstanty celočíselné sekvence číslic, která nesmí začínat nulou: 1, -58, 1258770 konstantu lze zapsat i v osmičkové soustavě: nula + sekvence osmičkových číslic: 0714 v šestnáctkové soustavě: nula + znak X (nebo x) + sekvence šestnáctkových číslic: 0X3A reálné např. 0.123, 55.1 exponenciální zápis, např. 5.123e3 ( = 5.123 10 3 ), nebo s velkým E: 5.123E3 můžou začínat i končit desetinnou tečkou, např..11 ( = 0.11), 4. ( = 4.0) znakové jeden znak z obou stran uzavřený apostrofy, např. a řetězce posloupnost znaků uzavřená v uvozovkách, např. toto je retezcova konstanta řetězce znaků budeme probírat později Symbolické konstanty - vytvoříme je z proměnných pomocí klíčového slova const const int a = 5; - a je proměnná, která má pevně danou hodnotu po celou dobu běhu programu - jakýkoliv pokus o změnu hodnoty a povede k chybě v době kompilace Jan Hnilica Počítačové modelování I / 2 6
Speciální znaky - slouží k formátování výpisu (na monitor nebo do souboru) - zapisují se jako kombinace dvou znaků: zpětného lomítka \ (tzv. backslash) znaku - nejčastěji používané speciální znaky: Znak Význam \n nový řádek \t tabulátor \r posun kurzoru zpět na začátek řádky \b posun kurzoru o jeden znak zpět \a pípnutí pozn. 1: těmto znakům se také říká escape sekvence pozn. 2: existují i jiné způsoby jejich zápisu, ale stačí umět tento způsob, tzn. \ + znak. - znakovou konstantu těchto znaků vyrobíte opět s pomocí apostrofů: char znak_tabulatoru = \t ; Jan Hnilica Počítačové modelování I / 2 7
Rozsah hodnot číselných typů - rozsah hodnot pro jednotlivé typy závisí na počítači (procesoru) a na použitém kompilátoru (jazyk C rozsahy hodnot přímo nedefinuje!) - pro získání informace o rozsazích hodnot na vašem počítači lze použít tyto konstanty: typ konstanty vymezující rozsah přibližný očekávatelný rozsah (nespoléhat se) short int (short) int long int (long) float double long double SHRT_MIN SHRT_MAX INT_MIN INT_MAX LONG_MIN LONG_MAX FLT_MIN FLT_MAX DBL_MIN DBL_MAX LDBL_MIN LDBL_MAX -32 767... 32 767 stejný jako short nebo vyšší -2 147 483 648... 2 147 483 647 1e-37... 1e+37 1e-308... 1e308 stejný jako double nebo vyšší (tyto konstanty si rozhodně nemusíte pamatovat, pouze o nich vědět) - pro použití celočíselných konstant musíte do programu vložit soubor <limits.h> #include <limits.h> - pro použití reálných konstant musíte zahrnout soubor <float.h> #include <float.h> operátor sizeof - vrací velikost datového typu v bajtech (tzn. kolik místa pro proměnnou je vyhrazeno při její definici) sizeof(char) sizeof(int) // vrátí velikost typu char (vždy 1 bajt) // vrátí velikost typu int (obvykle 2 nebo 4 bajty) Jan Hnilica Počítačové modelování I / 2 8
Celá čísla a znaménka - celočíselné datové typy mají dvě varianty: signed - mohou nabývat záporných i kladných hodnot (např. signed int) unsigned - mohou nabývat pouze kladných hodnot (např. unsigned int) obě varianty jednoho typu zabírají stejné množství paměti => největší hodnota typu unsigned je dvakrát větší než největší hodnota typu signed (protože polovina rozsahu typu signed je vyhrazena pro záporné hodnoty) např.: typ signed short nabývá hodnot* -32 768. 32 767 typ unsigned short nabývá hodnot 0.. 65 535 - oba typy obsahují prostor pro uložení 65 536 hodnot, ale typ signed spotřebuje polovinu tohoto prostoru pro záporné hodnoty pozn. 1: pokud při definici proměnné neuvedete variantu signed / unsigned, bude proměnná implicitně typu signed pozn. 2: konstanty maximálních hodnot unsigned typů jsou USHRT_MAX, UINT_MAX, ULONG_MAX * na vašem počítači se rozsah může lišit Jan Hnilica Počítačové modelování I / 2 9
Znaky - jsou vnitřně reprezentovány jako čísla 0 255 - číslo příslušící znaku je jeho kód z ASCII tabulky (tzv. ordinální číslo) - kompilátor umí znaky a jejich ordinální čísla mezi sebou oběma směry převádět ASCII tabulka - obsahuje kódy číslic, malých a velkých písmen, interpunkčních znamének a dalších znaků - vybrané úseky: Znaky Kódy ASCII tabulky (ordinální čísla) číslice 0 9 48 57 velká písmena A Z 65 90 malá písmena a z 97-122 - pokud tedy proměnná typu char obsahuje znak a, ve skutečnosti obsahuje číslo 97 char znak1 = a ; char znak2 = 97; obě proměnné mají přiřazenu stejnou hodnotu pozor: celočíselná hodnota 3 znak 3 obě jsou to čísla, ale číselná hodnota znaku 3 je 51 Jan Hnilica Počítačové modelování I / 2 10
Názvy proměnných - názvy proměnných by měly výstižně vyjadřovat, co je v proměnné uloženo int rokzakoupenivozidla; vhodný název int rzakvoz; méně vhodný název int qqf1a43f4s; nesmyslný (ale povolený) název Víceslovné názvy - jejich používání je doporučeno - dva obvyklé způsoby zápisu: rokzakoupenivozidla (tzv. velbloudí notace) rok_zakoupeni_vozidla Malá a velká písmena - jazyk C je rozlišuje, tzn. rok_vyroby a Rok_Vyroby jsou dvě různé proměnné Klíčová slova - vyhrazená slova, která mají v jazyce C zvláštní význam - nemohou být proto použita jako názvy proměnných (např. while, for, if atd.) pozn. žádné klíčové slovo není vhodným názvem proměnné DOPORUČENÍ - volte výstižné názvy (nejlépe víceslovné) - vytvořte si postupně svůj styl pojmenovávání a ten dodržujte - nepoužívejte k odlišení proměnných malá / velká písmena Jan Hnilica Počítačové modelování I / 2 11
Výpis na monitor - abychom mohli používat dále popsané funkce, je nutné připojit soubor stdio.h - to provedeme příkazem #include <stdio.h> // instrukce preprocesoru nekončí středníkem funkce printf - zajišťuje výpis na monitor - základním parametrem je řetězcová konstanta (tzv. řídící řetězec) printf( jak se dnes vede? ); - do řetězce je možné vkládat výpis proměnných // vypíše: jak se dnes vede? int pocetusaku = 5; printf( bylo uloveno %i zajicu, pocetusaku); // vypíše: bylo uloveno 5 zajicu rozbor druhého příkladu: - řetězec obsahuje znak % který oznamuje, že na toto místo výpisu bude vložená proměnná - znak i oznamuje, že proměnná bude typu int - samotná proměnná (pocetusaku) je uvedena jako druhý parametr funkce, hned za řetězcem - řetězec a proměnná jsou odděleny čárkou znaky %i tvoří tzv. FORMÁTOVOU SPECIFIKACI Jan Hnilica Počítačové modelování I / 2 12
Formátové specifikace funkce printf - kompletní formátová specifikace se skládá z několika částí: % příznak šířka přesnost modifikace typ červené položky jsou povinné zelené položky jsou nepovinné typ - určuje typ proměnné, která se bude tisknout - tabulka uvádí specifikace pro tisk základních typů: datový typ celé číslo se znaménkem celé číslo bez znaménka float, double znak řetězec znaků* specifikace ukazatel (pointer)* p přesnost * typy řetězec znaků a ukazatel - číslo, jehož význam se liší podle typu proměnné budeme probírat později - pro tisk float a double nastavuje počet cifer za desetinnou tečkou - před údajem přesnost se píše desetinná tečka: double a = 12.1287; printf( %.3f, a); // vytiskne: 12.129 příznak, šířka, modifikace - umožňují podrobnější formátování výpisu, zatím se jimi nebudeme zabývat i, d u f c s Jan Hnilica Počítačové modelování I / 2 13
Příklady použití funkce printf int a = 1; double b = 2.03059; printf( hodnota a je %i, hodnota b je %.2f\n, a, b); - vytiskne: hodnota a je 1, hodnota b je 2.03 a odřádkuje - lze tedy tisknout více proměnných najednou - počet proměnných musí být shodný s počtem formátových specifikací v řídícím řetězci! char znak = x ; printf( ASCII kod znaku %c je %i, znak, znak); - vytiskne: ASCII kod znaku x je 120 - dvakrát byla použita stejná proměnná typu char, poprvé byla vytištěna jako znak, podruhé jako int (=> takže se vytisklo její ordinální číslo) printf( ASCII kod znaku %c je %i, x, x ); - vytiskne to samé jako v předchozím případě pozn. funkce printf má i návratovou hodnotu - celé číslo, které udává počet vypsaných znaků Jan Hnilica Počítačové modelování I / 2 14
Funkce scanf - funkce pro načítání vstupů z klávesnice - funguje velmi podobně jako funkce printf, také obsahuje řídící řetězec a formátové specifikace int a; scanf( %i, &a); // přečte zadání z klávesnice a uloží ho do proměnné a - před názvem proměnné je nutné napsat znak & (ampersand) - to je rozdíl oproti printf - vynechání & je chyba, funkce scanf pak nebude pracovat správně - pro načítání typu double platí formátová specifikace lf (malé L + f), pro float jen f int main() { printf( zadejte cele cislo: ); int a; scanf( %i, &a); printf( zadane cislo je %i, a); return 0; } int a, b, c; scanf( %i %i %i, &a, &b, &c); pozn. funkce scanf má také návratovou hodnotu - celé číslo, které udává počet úspěšně načtených hodnot - program vyzve k zadání celého čísla - uživatel napíše číslo a stiskne enter - funkce scanf zadané číslo uloží do proměnné a - hodnota proměnné a je vytisknuta na monitor - načtení tří čísel najednou - uživatel napíše čísla oddělená prázdnými znaky (mezerami, tabulátory) a stiskne enter - funkce scanf postupně zadaná čísla uloží do proměnných a b c, prázdné znaky přeskočí Jan Hnilica Počítačové modelování I / 2 15
Načtení a výpis jednoho znaku funkce putchar - provádí výpis jednoho znaku na monitor putchar( r ); putchar(promenna); putchar( \n ); // vypíše na monitor znak r // vypíše obsah proměnné promenna // vypíše znak nového řádku (odřádkuje výstup) funkce getchar - načítá jeden znak z klávesnice - funkce getchar nemá žádné argumenty, prázdné kulaté závorky je ale nutné při jejím volání napsat int znak = getchar(); // načte jeden znak poznámka - obě funkce oficiálně pracují s typem int a ne s typem char (důvodem je práce se soubory, bude vysvětleno později) - jak už ale bylo řečeno, typ char je ve skutečnosti celé číslo putchar( a ); // vypíše na monitor a putchar(97); // vypíše na monitor a char znak = getchar(); // načtení znaku z klávesnice char znak = (char) getchar(); // čistější způsob: přetypování na char (později) Jan Hnilica Počítačové modelování I / 2 16
Výrazy - pojmem VÝRAZ označujeme vše, co se vyhodnotí na nějakou hodnotu - dosud jsme se setkali s konstantami a proměnnými 3.11 je výraz a hodnota tohoto výrazu je 3.11 a je výraz a hodnota tohoto výrazu je rovna hodnotě proměnné a - s proměnnými a konstantami můžeme provádět aritmetické operace - syntaxe a sémantika jsou většinou stejné jako v matematice (jako bychom psali do sešitu) 6 / 2 je výraz a hodnota tohoto výrazu je rovna 3 x + y je výraz a hodnota tohoto výrazu je rovna součtu hodnot proměnných x a y Co přesně dělá operátor přiřazení? - vyhodnotí výraz na pravé straně a jeho hodnotu dosadí ho do proměnné na levé straně int x = 3 + 3; // definice x a nastavení jeho hodnoty na 6 int y = x + 2; // definice y a nastavení jeho hodnoty na 8 x = x + 2; // zvýšení hodnoty x o 2.0 (= neznamená rovná se!!!) - samotné přiřazení je výrazem, jeho hodnota je rovna hodnotě pravé strany - může být tedy na pravé straně dalšího přiřazení x = y = 5; // nastavení hodnoty 5 oběma proměnným x, y přiřazení se stává příkazem až když je ukončeno středníkem! Jan Hnilica Počítačové modelování I / 2 17
Aritmetické operátory - operátor je symbol (např. +), který přiměje kompilátor vykonat nějakou akci s operandy (např. je sečíst) - operandy jsou výrazy operátor význam příklad + sčítání 6 + 3 vrací hodnotu 9 - odečítání 6-3 vrací hodnotu 3 * násobení 6 * 3 vrací hodnotu 18 / dělení 6 / 3 vrací hodnotu 2 % zbytek po celočíselném dělení 9 % 2 vrací hodnotu 1 obvyklé použití jako test dělitelnosti Dělení celočíselné a reálné - při celočíselném dělení se odřízne desetinná část výsledku (např. 3 / 2 vrací hodnotu 1) - dělení je celočíselné, pouze pokud oba operandy jsou celá čísla int x = 5; int y = 2; double z = 2.1; x / y vrací hodnotu 2 x / z vrací hodnotu 2.380952 Jan Hnilica Počítačové modelování I / 2 18
Priorita operátorů - operátory v jednom výrazu je možné kombinovat 4 + 6 / 2 // jaká je hodnota tohoto výrazu? - výrazy se vyhodnocují podle priorit operátorů - operátory * / % mají přednost před operátory + - - hodnota výrazu je tedy 7 (nejdřív se provede dělení) Závorky - mají nejvyšší prioritu ze všech operátorů - pomocí závorek je možné změnit pořadí vyhodnocování (4 + 6) / 2 // hodnota výrazu je nyní 5 Vyhodnocení výrazů 1. uzávorkování 2. priorita operátorů 3. operátory stejné priority zleva dopava DOPORUČENÍ: 1) nepište příliš komplikované výrazy (lze je rozepsat do několika jdnodušších) 2) pokud jste na pochybách, závorkujte!!! - závorky mohou být libovolně hluboko vnořené (4 + 30 / (2 + 2 * 1.5)) / 2 * (7-3) // hodnota výrazu je 20 Jan Hnilica Počítačové modelování I / 2 19
Operátory inkrementace a dekrementace - jazyk C nabízí dva speciální operátory, které mění hodnotu operandu o jedničku Inkrementace - zvýšení hodnoty o jedničku - provádí se operátorem ++ (dva symboly plus za sebou) Dekrementace - snížení hodnoty o jedničku - provádí se operátorem -- (dva symboly mínus za sebou) int a = 5; a++; // zvýšení hodnoty a na 6 a--; // snížení hodnoty a na 5 - příkaz a++; je ekvivalentní příkazu a = a + 1; Prefixová a postfixová varianta - inkrementace i dekrementace mají dvě varianty - rozdíly mezi nimi se projeví, pokud je spojíte do jednoho příkazu s přiřazením postfix: a++ 1. nejprve je vrácena hodnota výrazu 2. potom dojde k inkrementaci proměnné prefix: ++a 1. nejprve dojde k inkrementaci 2. potom je vrácena hodnota výrazu int a = 5; int b = a++; // hodnota b je 5 int a = 5; int b = ++a; // hodnota b je 6 (konečná hodnota proměnné a je v obou případech 6) Jan Hnilica Počítačové modelování I / 2 20
Složené operátory přiřazení - dovolují úsporně spojit operátor přiřazení s dalšími operátory místo lze napsat proměnná = proměnná operátor výraz proměnná operátor= výraz - např. a = a + 5; je ekvivalentiní zápisu a += 5; mojepromennasestrasnedlouhymnazvem = mojepromennasestrasnedlouhymnazvem + 3; mojepromennasestrasnedlouhymnazvem += 3; - stejným způsobem lze používat i operátory -= *= /= %= int a = 1; a += 4; // a má hodnotu 5 int b = 20; b /= a; // b má hodnotu 4 int c = 0; c -= (a + b); // c má hodnotu -9 a %= 2; // a má hodnotu 1 Jan Hnilica Počítačové modelování I / 2 21
Přetečení celočíselných proměnných - celá čísla mají omezenou velikost (např. typ int nabývá rozsahu INT_MIN... INT_MAX) - pokud se pokusíme zvýšit/snížit hodnotu celého čísla nad/pod možný rozsah, dojde k tzv. přetečení přetečení: hodnota čísla se skokem dostane na opačný konec rozsahu čísla bez znaménka unsigned short int a; a = USHRT_MAX; // nastavení na maximální hodnotu (např. 65 535) a++; // zvýšení nad limit, a má teď hodnotu 0 a--; // snížení pod limit, a má teď hodnotu USHRT_MAX čísla se znaménkem short int a; a = SHRT_MAX; // nastavení na maximální hodnotu (např. 32 767) a++; // zvýšení nad limit, a má teď hodnotu SHRT_MIN a--; // snížení pod limit, a má teď hodnotu SHRT_MAX Jan Hnilica Počítačové modelování I / 2 22