Kurz C++ (3.)
Ve třetí lekci našeho kurzu o C/C++ se dostáváme k podstatné
části jazyka. Nejdříve
si povíme o funkcích getchar(), putchar(), printf() a scanf().
Povíme si o velice důležitém příkazu if-else.
Dále si řekneme, co jsou to iterační příkazy neboli cykly a ukážu vám
všechny typy takových cyklů. S cykly úzce souvisí
příkazy break a continue a nakonec vysvětlím příkaz switch.
5.1. Terminálový vstup a výstup
Na začátek je nutné poznamenat, že vše, co je uvedeno
v této lekci je podstata jazyka C a je nutné, abyste vše
správně pochopili, protože při dalším programování
se bez toho určitě neobejdete.
Abyste mohli využívat funkce pro vstup a výstup musíte
k vašemu programu připojit hlavičkový soubor (header file).
O vkládání hlavičkových souborů jsem se již zmínil v minulé
lekci. Provede to
příkazem include .
Vložte následující řádek na začátek vašeho programu:
#include <stdio.h>
Nyní můžete používat všechny funkce
deklarované právě v souboru
stdio.h a které
souvisí s I/O (input/output - vstup/výstup)
operacemi jako je i výstup na
obrazovku a vstup z klávesnice
(dále může obsahovat například
výstup na tiskárnu či čtení a zápis do souboru).
5.1.1. Vstup a výstup jednoho znaku
Výstup jednoho znaku zajišťuje funkce putchar() , která
má jeden parametr kupodivu typu int (nikoliv char),
který představuje hodnotu znaku v ASCII tabulce.
Druhá funkce getchar() přečte jeden znak. Pokud
na řádek napíšeme víc znaků a stiskneme Enter,
funkce přečte pouze první znak a ostatní ignoruje.
Program přečte znak, vypíše ho a odřádkuje.
Krátky příklad:
int c;
c = getchar();
putchar(c);
putchar('\n');
Všimněte si, že jako parametr funkce
putchar()
můžete použít znakovou konstantu tj. znak
uzavřený mezi apostrofy např.
'a', '5' apod.
Hodnota znakové konstanty odpovídá celočíselné
hodnotě z ASCII tabulky např.
'a' má hodnotu
97. (ASCII tabulka nemusí být na všech systémech
stejná).
Zápis
putchar(97);
a
putchar('a');
je ekvivalentní.
5.1.2. Formátovaný vstup a výstup
Co když ale chceme přečíst více než jeden znak nebo
naopak chceme vypsat celou větu? Od toho má C dvě funkce:
scanf() - načte znaky, řetězce nebo čísla z klávesnice a uloží je
v požadovaném formátu do proměnné.
printf() - vypíše řetězec v požadovaném
formátu na obrazovku.
Způsob formátování
Obě funkce mají proměnný počet parametrů a my
jim tedy musíme říct, kolik parametrů mají zpracovávat.
K tomu slouží první parametr, což je řetězcová konstanta (nebo také řídící řetězec)
obsahující jisté znaky, které právě říkají kolik má mít funkce
parametrů a jakého jsou typu.
Řídící řetězec může obsahovat:
- Formátové specifikace, které vždy začínají znakem "%" (procenta)
a určují typ vstupní nebo výstupní hodnoty. Konkretní typ je určen znaky,
které následuje těsně za tímto znakem.
- Znakové posloupnosti, jsou běžné čitelné řetezce, které
se vypíší tak jak jsou, ale dají se použít jen ve funkci
printf() .
Tabulka nejčastěji používaných formátových specifikací:
Znak za % | Typ parametru |
c | znak - je lepší použít funkci getchar() nebo putchar() |
d | celé číslo typu signed int |
ld | celé číslo typu signed long |
u | celé číslo typu unsigned int |
lu | celé číslo typu unsigned long |
f | reálné číslo typu float |
lf | reálné číslo typu double |
Lf | reálné číslo typu long double (L musí být skutečné velké) |
x | číslo v hexadecimálním tvaru s malými písmeny - 5b8f |
X | číslo v hexadecimálním tvaru s velkými písmeny - 5B8F |
o | číslo v osmičkovém tvaru |
s | řetězec |
Příklady použití printf() :
printf("Je presne %2d:%2d\n", hodiny, minuty);
Vypíše například "Je presne 21:27".
Číslem mezi % a formátovým znakem je počet cifer, které
se vypíší. U reálného čísla lze určit počet cifer
před a za desetinou tečkou následovně:
printf("Cena vyrobku je %6.2f Kc\n", cena);
Vypíše například "Cena vyrobku je 10.40 Kc".
Bude vytištěno 6 cifer z toho 2 budou za desetinou tečkou.
printf("Cislo %d je hexa %XH\n", cislo, cislo);
Vypíše například "Cislo 85 je v hexa 55H".
Všimněte si konverze dekadického čísla na hexadecimální číslo.
Příklady použití scanf() :
scanf("%d", &cele_cislo);
Tento příkaz přečte celé číslo z klávesnice a uloží ho do proměnné cele_cislo.
Pozor! Všimněte znaku & před proměnnou cele_cislo .
Funkci scanf() předáváme
ukazatel na proměnnou cele_cislo a tento operátor vrací právě ukazatel.
To je rozdíl od předchozí funkce a začínající programátor na to často zapomene. Kompilátor
žádnou chybu nevypíše, ale program funguje chybně.
Zatím vám stačí vědět, že na tento operátor nesmíte zapomenout.
scanf("%f", &realne_cislo);
Tento příkaz přečte reálné číslo z klávesnice a uloží ho do proměnné realne_cislo.
Poznámka:
Minule jsem se zmiňoval o objektech cout a cin .
Tyto objekty mají stejnou funkci
jako funkce printf() a scanf() .
5.2. Booleovské výrazy
Booleovský výraz je výraz, který vrací buď logickou
1 (TRUE - pravda) nebo logickou 0 (FALSE - nepravda).
Jazyk C nemá přímo typ Boolean a tak místo toho využívá
typ int , kde hodnota 0 představuje FALSE a nenulová
hodnota (nejčastěji 1, ale není to podmínkou)
představuje TRUE.
Následující tabulka ukazuje tzv. relační operátory,
které používáme v podmínkách. Vše si ukážeme na příkladu.
Operace | Syntaxe |
rovnost | = = |
nerovnost | != |
logický součin | && |
logický součet | || |
negace | ! |
větší | > |
menší | < |
větší nebo rovno | >= |
menší nebo rovno | <= |
Každý booleovský výraz obsahuje jeden nebo více těchto operátorů.
Příklad:
// Toto je prirazeni, nikoliv porovnani, menime hodnotu promenne i
i = 5
// Zde vidite porovnani hodnoty promenne i a cisla 5
// Vyraz vraci nenulovou hodnotu (TRUE) v pripade ze v promenne i je skutecne cislo 5, jinak vraci 0 (FALSE)
i == 5
5.1.1. Zkrácene vyhodnocování logických výrazů
Zkrácené vyhodnocování platí pro logické operace tzn. logický součin
a logický součet. Znamená to, že jakmile je možno určit konečný výsledek
vyhodnocování skončí.
Příklad:
// Toto je zcela správné a k dělení nulou nikdy nedojde,
// protože y != 0 ukončí vyhodnocování dříve než by k něčemu takovému došlo
if(y != 0 && x / y < z)
5.2. Příkaz if a if-else
Jak jsme si říkali výše, booleovský výraz vrací někajou logickou hodnotu (0 nebo 1).
K vyhodnocení takovéhoto výrazu použijeme příkaz if :
if(výraz) { // zavorky jsou nutne
příkaz_1;
}
příkaz_2;
Pokud je podmínka výrazu splněna (vrací TRUE), program provede
příkaz_1 a poté i příkaz_2 .
V opačném případě (pokud výraz vrátí FALSE) je proveden pouze příkaz_2 .
Příklad:
// Program testuje zdali hodnota promenne i je vetsi nez 5
// V kladnem pripade vypise hlasku
if(i > 5) {
printf("Hodnota promenne i je vetsi nez 5\n");
}
Všimněte si, že výraz je vždy uzavřen do kulatých závorek () a že příkazy "pod"
if jsou
uzavřeny do závorek složených {}. Pokud je "pod" if
pouze jeden příkaz, složené závorky
nejsou nutné, naproti tomu kulaté jsou nutné vždy!
Příkaz
if-else se liší jen málo. Příkazy "pod"
else jsou prováděny
jen když výraz vrací FALSE. Česky řečeno: "Když (if) něco (výraz),
tak udělej tohle (příkaz_1), jinak (else) udělej tamhleto (příkaz_2)."
Příklad:
// Program testuje zdali hodnota promenne i je vetsi nez 5
// V obou pripadech vypise logickou hlasku
if(i > 5) {
printf("Hodnota promenne i je vetsi nez 5\n)";
}
else {
printf("Hodnota promenne i je mensi, rovna nez 5\n)";
}
Všimněte si, jak jsou příkazy ať už "pod" if nebo else ,
mírně odsazeny
oproti ostatním příkazům. Je to zdůvodu čitelnosti programu a silně
doporučuji se toho držet.
Příkazy if-else jsou často vhnízděné do jiných příkazů
if nebo if-else . Každé další
if je odsazeno o jeden tabelátor doprava.
Příklad:
// Program nejprve testuje hodnotu promenne a a teprve pak pokracuje
if(a != 0) {
if(i > 5) {
printf("Hodnota promenne i je vetsi nez 5\n");
}
else {
printf("Hodnota promenne i je mensi nebo rovno nez 5\n");
}
}
Teď znovu přepíšu předchozí příklad, ale trochu jinak:
// Zde vidite uzity operator logickeho soucinu neboli AND (zaroven)
// Vyraz v zavorkach tedy znamena:
// Pokud a je ruzne od 0 A ZAROVEN i je vetsi nez 5, pak vypis hlasku
if(a != 0 && i > 5) {
printf("Hodnota promenne i je vetsi nez 5\n");
}
V následujím příkladu vidíte logický součet:
// Zde vidite uzity operator logickeho soucinu neboli OR (nebo)
// Vyraz v zavorkach tedy znamena:
// Pokud a je ruzne od 0 NEBO i je vetsi nez 5, pak vypis hlasku
if(a != 0 || i > 5) {
printf("Hodnota promenne i je vetsi nez 5\n");
}
Poznámka:
Často můžeme vidět příkaz if zkrácený.
Místo příkazu:
if(vyraz != 0)
píšeme jen
if(vyraz)
a místo příkazu:
if(vyraz == 0)
píšeme jen
if(!vyraz)
5.3. Ternární operátor
Ternární operátor má stejný význam jako příkaz if-else , jen syntaxe je jiná.
V některých případech je lepší použít ternární operátor kvůli
kratšímu zápisu na jeden řádek, ale doporučuji raději používat if-else .
Ternární operátor má následující syntaxy:
vyraz_podm ? vyraz_1 : vyraz_2;
Příklad:
// Pokud je a ruzne od 0, i bude rovno 5
// V opacnem pripade bude i rovno 10
i = (a != 0) ? 5 : 10;
Stejný příklad s použitím if-else :
// Funkce je uplna stejne jako v predchozim prikladu
// Vidite ze zapis pomoci if-else je delsi, ale je prehlednejsi
if(a != 0) {
i = 5;
}
else {
i = 10;
}
Poznámka: Závorky kolem podmínky u ternárního
operátoru nejsou nutné, ale vřele je doporučuji kvůli čitelnosti programu.
5.4. Iterační příkazy - cykly
Jazyk C rozlišuje tři typy iterace (opakování): for, while
a do-while .
5.4.1. Příkaz for
Tento cyklus použijeme v případě, když předem známe počet průchodů cyklem.
Syntaxe je následující:
for(vyraz_start; vyraz_stop; vyraz_iter) {
prikaz;
}
Cyklus for nejdříve vyhodnotí vyraz_start, otestuje pravdivost vyrazu_stop
(když výraz vratí FALSE, cyklus skončí) a provede příkazy
uvnitř cyklu a nakonec provede vyraz_iter. Toto celé se opakuje dokud vyraz_stop nevratí
nepravdu (FALSE).
Ukážeme si několik příkladů:
// Program vypise pod sebe 20 cisel (0-19)
// Promenna i je predem deklarovana jako int
// Toto je doporucene pouziti cyklu for
for(i = 0; i < 20; i++) {
printf("%d\n", i);
}
// Program vypise pod sebe 20 cisel (19-0)
// Promenna i je deklarovana primo v cyklu (toto nemusi vzdy fungovat)
// Toto je caste pouziti cyklu for
for(int i = 19; i >= 0; i--) {
printf("%d\n", i);
}
Můžeme využít nekonečný cyklus:
// Takovy program radeji nezkousejte, protoze nikdy neskonci
// ale za chvilku si povime jak ukoncit cyklus explicitne
for( ; ; ) {
printf("Ahoj\n");
}
5.4.2. Příkaz while
Dalším velice důležitým cyklem je cyklus while .
Testuje podmínku před průchodem cyklu, tzn., že
cyklus nemusí proběhnout ani jednou. Ukončovací
podmínka většinou závisí na příkazu v těle cyklu
a my předem nevíme kolikrát cyklus proběhne.
Syntaxe:
while(podm) {
prikaz;
}
Výraz podm se testuje a pokud vrátí
0 (FALSE), cyklus skončí.
5.4.3. Příkaz do-while
Posledním iteračním cyklem je do-while (dělej-dokud).
Liší se od předchozáho tím, že testuje podmínku
až po průchodu cyklem tzn., že cyklus proběhne alespoň jednou.
Cyklus je ukončen až když výraz v podmínce vrátí 0 (FALSE).
Syntaxe:
do {
prikaz;
} while(podm);
5.4.4. Příkazy break a continue
Příkazy break a continue ovlivňují normální
průběh cyklu. Lze je použít na všechny výše uvedené
typy cyklů.
- break
Tento příkaz ukončuje nejvnitřnější smyčku neboli opouští okamžitě cyklus.
- continue
Druhý uvedený příkaz skáče na konec cyklu a tím si vynutí další opakování cyklu,
ale cyklus neopouští.
5.4.5. Příkaz switch
C obsahuje jakýsi přepínač neboli switch, který
umožňuje mnohonásobné větvení programu.
Syntaxe:
switch(vyraz) {
case hodnota_1: // Toto je jedna vetev
prikaz_1; // ...
break; // ...
case hodnota_2: // A zde zacina dalsi vetev
prikaz_2;
break;
case hodnota_3:
prikaz_3;
break;
default:
prikaz_def;
break;
}
Program porovnává vyraz s jednotlivými
hodnotami_X každé větve a provede
tu větev, kde se vyraz rovná hodnote_X .
Pozor!
Není-li větev ukončena příkazem break ,
program začne zpracovávat další větve
v pořadí dokud nenarazí na break . Proto
je třeba na konci každé větve psát
break . Z tohoto ale vyplývá, že pokud
chceme pro více hodnot zpracovat pouze jednu větev,
stačí vynechat příkaz break v těchto větvích.
Například:
switch(vyraz) {
case hodnota_1:
prikaz_1;
break;
case hodnota_2:// Zde neni break
case hodnota_3:
prikaz_23;
break;
}
Prikaz_23 se provede, když je vyraz roven buď
hodnote_2 nebo hodnote_3 .
5.5. Příklad
Vše si samozřejmě ukážeme na příkladu. Příklad si můžete stáhnout z CD v sekci Downloads.
Vše, co potřebujete vědět k příkladu je v této nebo v minulé lekci a popis funkce najdete v komentářích.
#include <stdio.h>
int main(int argc, char* argv[])
{
int iVolba, i;
char c;
double f, g;
do {
//
// Informace pro uzivatele
printf("1) Test smycky for\n");
printf("2) Test smycky while\n");
printf("3) Test smycky do-while \n");
printf("4) Konec programu\n");
printf("Zadejte co chcete otestovat:");
//
// Ulozime uzivatelovu volbu do promenne iVolba jako hodnotu typu int
scanf("%d", &iVolba);
//
// Vetveni programu podle toho, co zvoli uzivatel
switch(iVolba) {
case 1:
//
// Test cyklu for
printf("Zvolil jste prikaz for, vypisu 10 cisel a skoncim.\n");
//
// Cyklus for od 0 do 9
for(i = 0; i < 10; i++) {
printf("%d\n", i);
}
//
// Nakonci jeste odradkujeme
printf("\n");
break;
case 2:
printf("\nZvolil jste prikaz while.\n");
printf("Program cte znaky z klavesnice, tisknutelne znaky opisuje,\n");
printf("neviditelne preskakuje a zastavi se pri precteni znaku 'z'.\n\n");
//
// Precteni znaku
while((c = getchar()) != 'z') {
if(c >= ' ') { // Vynechavame neviditelne znaky
putchar(c); // Tisk znaku
printf("\n"); // Odradkuju
}
}
break;
case 3:
printf("Zvolil jste prikaz do-while. \n");
printf("Program nacte dolni a horni mez intervalu\n");
printf("a pote vypise vsechny cela cisla z tohoto intervalu.\n");
//
// Nacteme dve realna cisla
printf("Zadejte dolni mez intervalu:");
scanf("%lf", &f);
printf("Zadejte horni mez intervalu:");
scanf("%lf", &g);
//
// Test zdali je horni mez skutecne vetsi nez dolni mez
if(f < g) {
//
// Zaokrouhleni realneho cislo na cele cislo (explicitni konverze)
i = (int) f;
do {
// Vypsani celeho cisla
printf("%d\n", i);
// Prejdeme na dalsi cele cislo
i++;
// A testujeme zdali jsme jiz dosahli horni hranice intervalu
} while(i <= g);
}
else {
printf("Chyba! Zadali jste chybne meze.\n");
}
break;
case 4:
//
// Konec
printf("Konec...\n");
break;
default:
printf("Zvolil jste kravinu\n");
break;
}
//
// Testujeme promennou iVolba na hodnotu 4,
// coz je volba, pri ktere ma program skoncit
} while(iVolba != 4);
return 0;
}
Poznámka:
Opět si všimněte odsazení jednotlivých větví příkazu switch a odsazení těl
cyklů. Toto je velmi dobré dělat kvůli přehlednosti v programu.
5.6. Závěr
Na závěr vám prozradím, co nás čeká příště.
Příště probereme preprocesor jazyka a funkce.
Mezi příkazy preprocesoru patří i nám známý příkaz
include . Zjistíte, že před každým příkazem preprocesoru
je znak '#' .
Dále si vytvoříme vlastní funkce mimo funkci
main() .
Tyto funkce pak budeme volat z funkce main() .
Těším se příště nashledanou.
|