390 likes | 559 Views
Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů. Podmínky a cykly …. Dokončení stručného přehledu řídících struktur jazyka C. Složený příkaz, blok. Pascalské BEGIN a END představují v jazyce C složené závorky „ { “ a „ } “ .
E N D
Začínáme vážně programovat Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů
Podmínky a cykly… Dokončení stručného přehledu řídících struktur jazyka C.
Složený příkaz, blok • Pascalské BEGIN a END představují v jazyce C složené závorky „{“ a „}“. • Příkazy uvnitř složených závorek „{ … }“ představují jeden složený příkaz. • Používá se tehdy, potřebujeme-li provést několik příkazů tam, kde se očekává pouze jeden, např. v cyklech. • Závorky „{}“ uzavírají také blok, proto uvnitř závorek smíme (mimo jiné) deklarovat proměnné.
Podmíněný příkaz – větvení if(podmínka) příkaz_1; else příkaz_2; • Platí-li podmínka, provede se „příkaz_1”. • Neplatí-li podmínka, provede se „příkaz_2”. if(podmínka) příkaz_1; • Platí-li podmínka, provede se „příkaz_1”. ano ? ne příkaz_1 příkaz_2 ano ne ? příkaz_1 (Je-li v sobě vnořeno několik if, patří else k poslednímu if bez else)
Příkaz switch – přepínač • Příkaz pro mnohonásobné větvení programu. • Nejedná se o plný ekvivalent příkazu CASE známého z Pascalu: • nelze jednoduše napsat prostý výčet několika hodnot pro jeden příkaz • rozhodovací výraz musí být typu int • v každé větvi smí být více příkazů bez „{}“ složených závorek • každá větev musí být ukončena break; • jednu větev lze definovat jako „default“
switch (výraz){ case h1: př_1;break;case h2:case h3:př_3;break;default: př_def; [break;] } Příkaz switch – přepínač (2) výraz == h1 ano př_1 break; ne == h2 ano ne == h3 ano př_3 ne př_def break; break;
Cyklus – for for (inicializace;podmínka;iterační výraz) příkaz; • Inicializace se provede pouze jedenkrát na začátku. • Cyklicky se pak provádí: • test platnosti podmínky • je-li splněna • provedení příkazu • vyhodnocení iteračního výrazu • Příklad: for(int x = 0; x<10; x++)printf(“Ahoj”); inicializace ano ? ne příkaz iterační výraz
Cyklus – while a do-while while(podmínka) příkaz; • Dokud platí podmínka, provádí se „příkaz”. • (příkaz se nemusí provést) do příkaz; while(podmínka); • Provede se příkaz. • Dokud platí podmínka, provádí se „příkaz”. • (příkaz se provede nejméně jednou) ano ne ? příkaz příkaz ano ? ne
Příkazy break a continue • Mění normální průběh cyklu. • Použití má smysl v cyklech (for, while, do-while) a v případě break i v přepínači. • break • ukončuje smyčku • opouští ihned cyklus • continue • skáče na konec smyčky – vynutí další iteraci cyklu • neopouští cyklus • Oba se vztahují k nejvnitřnější neuzavřené smyčce.
Příkazy break a continue (2) int x = 0; while(x++< 5) { if(x == 3) break; if(x == 2) continue; printf ("%d\n", x); } printf ("%d\n", x); 1 – uvnitř cyklu 3 – mimo cyklus x = 0 ne < 5 ano == 3 ano break; ne continue; ano == 2 ne printf() printf()
Příklady „ekvivalentních“ cyklů for(x = 0; x < 10; x++) vysledek += x; x = 0; while (x < 10) { vysledek += x; x++; } x = 0; do{ vysledek += x; x++; } while (x < 10); x = 0; if(x < 10) do { vysledek += x; x++; }while (x < 10);
Příklady „ekvivalentních“ cyklů x = 0; if(x < 10) do ;while(vysledek += x++, x < 10); x = 0; for (;;) { vysledek += x; if(++x >= 10) break; }
Fibonacciho posloupnost int p1 = 0, p2 = 1, f; printf ("0 : 0\n"); printf ("1 : 1\n"); for (int x = 2; x < 10; x++) { f = p1 + p2; p1 = p2; p2 = f; printf ("%d : %d\n", x, f); }
Fibonacciho posloupnost • Vaším úkolem je program přepsat bez použití cyklu for.
Fibonacciho posloupnost • Vaším úkolem je program přepsat bez použití cyklu for. int x = 2, p1 = 0, p2 = 1, f; printf ("0 : 0\n"); printf ("1 : 1\n"); while(x < 10) { f = p1 + p2; p1 = p2; p2 = f; printf ("%d : %d\n", x, f); x++; }
Přetypování Přetypování Typová konverze
Přetypování, typová konverze • Převod proměnné nebo hodnoty určitého typu na typ jiný. • Dva typy typové konverze • Implicitní • prováděny automaticky • nemůžeme téměř ovlivnit • Explicitní • přetypování (typecasting) • plně pod naší kontrolou • používá se často, zejména při práci s ukazateli • nevhodné použití může způsobit značné komplikace • v C probíhá v době překladu, C++ i dynamicky
Přetypování – příklad použití int a = 10, b = 3; printf("10/3 = %d\n", a/b); printf("10/3 = %f\n",(double)a/b); 10/3 = 3 10/3 = 3.333333 double d = 5.4, e = 5.9; int c =(int)d; //c == 5 c =(int)e; //c == 5
Vstupně výstupní operace Základní informace.
Vstupně výstupní operace • Programovací jazyk C neimplementuje žádnou IO (Input Output) operaci jako vlastní součást jazyka (jako tomu je třeba u jazyka Pascal). • Standardní knihovna proto obsahuje několik IO funkcí, které vstupně výstupní operace zajišťují. • Prototypy těchto základních funkcí jsou v hlavičkovém souboru „stdio.h“.
Čtení/zápis znak po znaku • putchar() • zajistí výstup jednoho znaku • getchar() • zajistí vstup jednoho znaku • Obě pracují s celočíselným typem int (ne s char).
Formátovaný vstup a výstup • scanf(“řídící řetězec formátu”, parametry) • zajišťuje vstup • printf(“řídící řetězec formátu”, parametry) • zajišťuje výstup • „Řídící řetězec formátu“ obsahuje • „Formátové specifikace“ • začínají ‘%’ • určují formát výstupu či vstupu • „Znakové posloupnosti“ • nejsou uvozeny ‘%’ • používají se zejména u printf()
Formátovaný vstup a výstup (2) • Formátování je přehledně uvedeno na stránkách předmětu. • Pozor, při čtení pomocí funkce scanf() musí být před proměnnou znak ‘&’ – pokud se nejedná o ukazatel (problém předávání hodnotou). • Funkce scanf() vrací počet přečtených položek (“%d %d” odpovídá návratové hodnotě 2). • Funkce printf() vrací počet vypsaných znaků („%d %d” může odpovídat návratové hodnotě více než 2). • %16.10lf ... tisk celkem na 16 míst, z toho 10 za desetinnou tečkou. První číslo se nedodrží, pokud s daným počtem nelze hodnotu vypsat.
Vstupně výstupní operace (2) • Probíhají asynchronně (buffer) • pokud někdo zadá vstup „10 20 30 40 50“ • a budeme číst desítková čísla v cyklu • proběhne cyklus 5x a pak scanf() vrátí EOF 10 20 30 40 50 1: opis: 10 2: opis: 20 3: opis: 30 4: opis: 40 5: opis: 50 while (scanf("%d", &cislo)!=EOF) { ++poradi; printf("%d: opis: %d\n", poradi, cislo); }
1. Úkol – průměr • Napište program pro výpočet aritmetického průměru bez použití pole. • Jednotlivé hodnoty čtěte ze vstupu až do konce souboru (Ctrl+D) nebo do výskytu záporné hodnoty. • Poté vypište aritmetický průměr zadaných hodnot. • Hodnoty >= 100 ignorujte (nezapočítávejte). • Snažte se použít příkazů break i continue. • Zkusit lze napočítači Aisa: /home/xbayer/open/prumer
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) {
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) { if (vstup >= 100) continue;
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) { if (vstup >= 100) continue; else if (vstup < 0) break;
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) { if (vstup >= 100) continue; else if (vstup < 0) break; printf("Zadano: %d\n", vstup);
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) { if (vstup >= 100) continue; else if (vstup < 0) break; printf("Zadano: %d\n", vstup); soucet += vstup;
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) { if (vstup >= 100) continue; else if (vstup < 0) break; printf("Zadano: %d\n", vstup); soucet += vstup; pocet++; }
1. Úkol – průměr(2) while (scanf ("%d", &vstup) != EOF) { if (vstup >= 100) continue; else if (vstup < 0) break; printf("Zadano: %d\n", vstup); soucet += vstup; pocet++; } //vypocet pak muze byt ((double)soucet / pocet));
2. Úkol – koza, vlk a zelí • Na počítači Aisa si stáhněte soubor: /home/xbayer/open/zeli.c • Dokončete program tak, aby pracoval. • Vyzkoušet lze na: /home/xbayer/open/zelifull • K dispozici je již řada hotových funkcí, Vaším úkolem bude zejména naprogramovat vlastní ovládání.
2. Úkol – koza, vlk a zelí – cíle • Na jedné straně (A) jezera se vyskytujete Vy, koza, vlk a zelí. • Koza má zálusk na zelí. • a vlk na kozu • Máte loďku a vždy můžete přepravit sebe a jednoho společníka. • Úkolem je dostat všechny tři na druhou stranu (B) jezera. • (Triviální řešení, kdy necháme kozu sežrat zelí, poté vlka kozu a následně převezeme vlka, bude uznáno pouze, pokud předvedete i reversní proces )
2. Úkol – hotové funkce (1) • Vzhledem k probrané látce není program napsán příliš elegantně. • Tři globální proměnné typu char (k, v, z) nabývají hodnot ‘A’ a ‘B’, dle umístění kozy, vlka a zelí. • Pro testování konfliktů a korektního vstupu již máte napsány funkce, stačí použít, např.: do { if (scanf ("%c",&vstup) == EOF) return 1; }while (preprav ('a', vstup));
2. Úkol – hotové funkce (2) • Funkce test() • int test (char breh); • Zjistí, zda nedošlo ke konfliktu na jednom z břehů (parametr breh – ‘A’, ‘B’). • V případě konfliktu vypíše hlášení a vrátí hodnotu 1. • Pokud vše OK, vrátí hodnotu 0 a nic nevypisuje. • Funkce kdo_ceka() • void kdo_ceka (char breh); • Nepovinné, jen vypíše, kdo je na daném břehu.
2. Úkol – hotové funkce (3) • Funkce preprav() • int preprav (char odkud,char vstup); • Pokusí se přepravit „vstup“(změnit stav globálních proměnných). • Na vstup obdrží znak, co uživatel zadal. • Jako parametr „odkud“ obdrží ‘A’ nebo ‘B’, dle toho, odkud kam „vstup“ přepravujeme. • Vrátí hodnotu 0, pokud vše OK. • Vrátí hodnotu 1, pokud se vyskytnul problém. • Řeší i nemožnost přepravy, jelikož „pasažér“ je na druhém břehu, vypisuje odpovídající hlášení.
2. Úkol – hotové funkce (4) • Funkce test_vitezstvi() • int test_vitezstvi (void) • Vrátí hodnotu 0, pokud nebylo dosaženo vítězství. • Vrátí hodnotu 1, pokud hráč vyhrává. • Způsoby volání funkcí: • test (‘B’); //test konzistence na břehu B • kdo_ceka (‘B’); //výpis, kdo čeká na břehu B • while (preprav (‘A', vstup)); //kde vstup je znak • test_vitezstvi (); //pravda, když hráč vyhrál
Shrnutí • Bez cyklů nelze programovat, je žádoucí jimi plně proniknout. • IO v jazyku C je značně problematické a nejednou možná strávíte mnoho hodin hledáním chyby – v C++ je značně vylepšeno. • Děkuji za pozornost.