Procedurlne programovanie 4 prednka Gabriela Koskov Obsah 1
Procedurálne programovanie: 4. prednáška Gabriela Kosková
Obsah 1. 2. 3. 4. 5. opakovanie (4 príklady) preprocesor príklady (4) funkcie a práca s pamäťou príklady (4)
Procedurálne programovanie: Práca so súborom - opakovanie v príkladoch
Príklad 1 program sčíta celé čísla v súbore ceny. txt. Čísla v súbore predchádza vždy niekoľko znakov '$' (bez medzery). Príklad je na vrátenie znaku na vstup.
#include<stdio. h> if((fr = fopen("ceny. txt", "r")) == NULL) { printf("Nepodarilo sa otvorit subor. n"); return; } int main() { FILE *fr; int c; float cena, suma = 0. 0; fr = fopen("ceny. txt", "r"); while(!feof(fr)) { while((c = getc(fr)) == '$') ; ungetc(c, fr); fscanf(fr, "%f", &cena); printf("%fn", cena); suma += cena; while(!feof(fr) && (c = getc(fr)) != '$') ; ungetc(c, fr); } printf("suma: %. 2 fn", suma); fclose(fr); return 0; } if(fclose(fr) == EOF) printf("Nepodarilo sa zatvorit suobor. n");
Príklad 2 program načíta rozmer n a nakreslí do súboru sach. txt sachovnicu n x n, kde čierne políčka bude reprezentovať znak # a biele políčka medzera
#include<stdio. h> int main() { int i, j, n; FILE *fw; if ((fw = fopen("sach. txt", "w")) == NULL) { printf("Subor sa nepodarilo vytvorit. n"); return 0; } printf("Zadajte rozmer sachovnice: "); scanf("%d", &n); for (i=1; i<=n; i++) { for (j=1; j<=n; j++) if ((i%2 && !(j%2)) || (!(i%2) && j%2)) putc('#', fw); else putc(' ', fw); putc('n', fw); } if (fclose(fw) == EOF) printf("Subor sa nepodarilo zatvorit. n"); return 0; }
Príklad 3 Kontrola otvorenia dvoch súborov. . . FILE *fr, *fw; if ((fr = fopen("data. txt", "r")) == NULL) { printf("Subor data. txt sa nepodarilo vytvorit. n"); return 0; } if ((fw = fopen("vystup. txt", "w")) == NULL) { printf("Subor vystup. txt sa nepodarilo vytvorit. n"); if(fclose(fr) == EOF) printf("Subor data. txt sa nepodarilo zatvorit. n"); return 0; }. . . Pred ukončením programu treba zatvoriť všetky otvorené súbory
Príklad 4 Kontrola zatvorenia dvoch súborov. . . FILE *fr, *fw; . . . if(fclose(fr) == EOF || fclose(fw) == EOF) printf("Niektory subor sa nepodarilo zatvorit. n"); . . . Skrátené vyhodnocovanie podmienok: ak sa podarí zatvoriť prvý súbor, už je zrejmé, že OR má hodnotu 1 a už sa druhá časť podmienky nevyhodnocuje, teda druhý súbor sa nezatvorí
Procedurálne programovanie: Preprocesor
Činnosť preprocesora • spracováva zdrojový text PRED kompilátorom • zamieňa text, napr. identifikátory konštánt za číselné hodnoty • vypustí zo zdrojového textu všetky komentáre • prevádza podmienený preklad • nekontroluje syntakticú správnosť programu • riadok, ktorý má spracovávať preprocesor sa začína znakom #
Konštrukcie preprocesor • definovanie makra #define meno_makra text • zrušenie definície makra #undef meno_makra • podmienený preklad v závislosti na konštante konst #if konst #elif #else #endif
Konštrukcie preprocesor • vloženie textu zo špecifikovaného súbora zo systémového adresára #include <filename> • vloženie textu zo špecifikovaného súbora v adresári používateľa #include "filename" • výpis chybových správ vo fáze predspracovania #error text
Konštrukcie preprocesor • podmienený preklad v závislosti od toho, či je makro definované, alebo nedefinované #ifdef meno_makra #elif #else #endif • podmienený preklad v závislosti od toho, či je makro nedefinované, alebo definované #ifndef meno_makra #elif #else #endif
Konštanty - makrá bez parametrov • • • symbolické konštanty používajú sa často (zbavujú program "magických čísel") väčšinou definované na začiatku modulu platnosť konštánt je do konca modulu náhrada konštanty hodnotou - rovoj (expanzia) makra
Pravidlá pre písanie konštánt • mená konštánt - veľkými písmenami • meno konštanty je od hodnoty oddelené apsoň jednou medzerou • za hodnotou by mal byť vysvetľujúci komentár • nové konštanty môžu využívať skôr definované konštanty • ak je hodnota konštanty dlhšia ako riadok, musí byť na konci riadku znak (nie je súčasťou makra)
Príklady defninovania konštánt #define #define MAX 1000 PI 3. 14 DVE_PI (2 * PI) MOD % AND && MENO_SUBORU "list. txt" DLHA_KONSTANTA Toto je dlha konstanta, ktora sa nezmesti do jednoho riadku. • za hodnotou nie je ; • medzi menom konštanty a jej hodnotou nie je =
Príklad požitia konštanty: výpočet obsahu kruhu #include <stdio. h> #define PI 3. 14 int main(){ double r; printf("Zadajte polomer: "); scanf("%lf" &r); printf("Obvod kruhu s polomerom %f je %fn", r, 2 * r * PI); return 0; }
Príklad použitia konštanty: malé písmená zmení na veľké #include <stdio. h> #define POSUN ('a' - 'A') #define EOLN 'n' #define PRED_MALE '*' int main() { int c; ak je symbolickou konštantou výraz, vhodné je uzavrieť ho do zátvoriek while((c = getchar()) ! = EOLN) { if (c >= 'a' && c <= 'z') { putchar(PRED_MALE); putchar(c - POSUN); } else malé písmeno zmení na putchar(c); veľké a pred neho vypíše } '*', inak vypíše načítaný return 0; } znak
Kedy sa nerozvinie makro • makro sa nerozvinie, ak je uzatvorené v úvodzovkách #define MENO "Katka" . . . printf("Volam sa MENO"); printf("Volam sa %s", MENO); vypíše sa: Volam sa MENO vypíše sa: Volam sa Katka
Prekrývanie definícií • nová definícia prekrýva starú, pokiaľ je rovnaká (to ani nemá zmysel) • ak nie je rovnaká: – zrušiť starú definíciu: #undef meno_makra – definovať meno_makra #define POCET 10 #undef POCET #define POCET 20
Makro ako skrytá časť programu #define ERROR { printf("Chyba v datach. n"); } • pri použití nie je makro ukončené bodkočiarkou: if (x == 0) ERROR else y = y / x;
Makrá s parametrami • krátka a často používaná funkcia vykonávajúca jednoduchý výpočet – problém s efektivitou (prenášanie parametrov a úschova návratovej hodnoty je časovo náročnejšia ako výpočet) – preto namiesto funkcie - makro (to sa pri preprocessingu rozvinie) • je potrebné sa rozhodnúť medzi – funkcia: kratší ale pomalší program – makro: rýchlejší ale dlhší program
Makrá s parametrami • nazývajú sa vkladané funkcie - rozvitie makra znamená, že sa meno makra nahradí jeho telom definícia makra #define je_velke(c) ((c) >= 'A' && (c) <= 'Z') • zátvorka, v ktorej sú argumenty funkcie - hneď za názvom makra (bez medzery) v zdrojovom súbore ch = je_velke(ch) ? ch + ('a' - 'A') : ch; rozvinie sa ch = ((ch) >= 'A' && (ch) <= 'Z') ? ch + ('a'-'A') : ch;
Makrá s parametrami • telo makra - uzavrieť do zátvoriek, inak môžu nastať chyby, napr. : #define sqrt(x) x * x. . . sqrt(f f + g *+ fg); + g; po rozvinutí makra • správne #define sqrt(x) ((x) * (x)). . . sqrt(f + * g); ((f + g)); po rozvinutí makra
Preddefinované makrá • getchar() a putchar() (v stdio. h) #define getchar() getc(stdin) #define putchar(c) putc(c, stdout) • makrá v ctype. h - makrá na určenie typu znaku – – – isalnum - vráti 1, ak je znak číslica alebo malé písmeno isalpha - vráti 1, ak je znak malé alebo veľké písmeno isascii - vráti 1, ak je znak ASCII znak (0 až 127) iscntrl - vráti 1, ak je znak Ctrl znak (1 až 26). . . viac v Herout: Učebnice jazyka C
Preddefinované makrá • makrá v ctype. h - makrá na konverziu znaku – tolower - konverzia na malé písmeno – toupper - konverzia na veľké písmeno – toascii - prevod na ASCII - len najnižších 7 bitov je významných
Vkladanie súborov • vkladanie systémových súborov < > • vkladanie súborov v aktuálnom adresári " " #include <stdio. h> #include <ctype. h> #include "KONSTANTY. H"
Podmienený preklad • u väčších programov – ladiace časti - napr. pomocné výpisy • program – trvalá časť – voliteľná časť (napr. pri ladení, alebo ak je argumentom programu nejaký prepínač)
Riadenie prekladu hodnotou konštantného výrazu #if konstantny_vyraz cast_1 #else cast_2 #endif ak je hodnota konštantného výrazu nenulová, vykoná sa časť 1, inak časť 2 #if 0 cast programu, co ma byt vynechana #endif ak pri testovaní nechcete prekladať časť programu, namiesto /* */ (problém by robili vhniezdené komentáre)
Riadenie prekladu hodnotou konštantného makra #define PCAT 1 #if PCAT #include <conio. h> #else #include <stdio. h> #endif • ak je program závislý na konkrétnom počítači • ak na PC/AT - definujeme PCAT na 1, inak na 0
Riadenie prekladu definíciou makra #define PCAT #ifdef PCAT #include <conio. h> #else #include <stdio. h> #endif • ak je program závislý na konkrétnom počítači • ak na PC/AT - definujeme PCAT (bez hodnoty), • stačí, že je konštanta definovaná #ifndef PCAT • ak nie je definovaná konštanta #undef PCAT • zrušenie definície makra
Operátory defined, #elif a #error • #ifdef, alebo #ifndef zisťujú existenciu len jednoho symbolu, čo neumožňuje kombinovať viaceré • ak treba kombinovať viaceré podmienky: #if defined TEST #if !defined TEST • #elif - má význam else-if • #error - umožňuje výpis chybových správ (v priebehu preprocesingu - nespustí sa kompilácia)
Operátory defined, #elif a #error - príklad #if defined(ZAKLADNY) && defined(DEBUG) #define VERZIA_LADENIA 1 #elif defined(STREDNY) && defined(DEBUG) #define VERZIA_LADENIA 2 #elif !define(DEBUG) #error Ladiacu verziu nie je mozne pripravit! #else #define VERZIA_LADENIA 3 #endif
Oddelený preklad • program sa delí na menšie časti - moduly – – logicky sa program delí na časti je veľký pracuje na ňom viac programátorov aby bol prehľadný • moduly najprv musíme prebrať funkcie. . . – oddelené - zvlášť súbory – obsahujú premenné a funkcie, ktoré môžu povoliť alebo zakázať používať inými modulmi
Procedurálne programovanie: Príklady
Príklad 1 program vypíše súčet prvých N čísel, kde N je symbolická konštanta #include <stdio. h> #define N 5 int main() { int i, suma = 0; for (i = 1; i <= N; i++) sum += i; printf("Sucet prvych %d cisel je %dn", N, suma); return 0; }
Príklad 2 program použije makro na_tretiu(x), ktorá bude počítať tretiu mocninu a použije ho v rôznych výrazoch #include <stdio. h> 2*3+1*2*3+1 2+3*2+3 = 17 = 343) #define na_tretiu(x) (x * x* *(x) x) * (x)) 19, (nie 125) ((x) int main(void) { int i = 2, j = 3; printf("%d^3 return 0; } = = 3^3 = 9 %d", 2^3 = 8 3, na_tretiu(3)); i, na_tretiu(i)); 5^3 = 17 2+3, na_tretiu(2+3)); i*j+1, na_tretiu(i*j+1)); 7^3 = 19
Príklad 3 program zistí, či bola načítaná nula pomocou makra citaj_int(x) #include <stdio. h> #define citaj_int(i) (scanf("%d", &i), i) int main() { int j, k; printf("Zadajte cele cislo: "); if((j = citaj_int(k)) == 0) printf("Bola nacitana nula. n"); printf("Bolo nacitane cislo %d", k); return 0; }
Príklad 4 #include <stdio. h> #define LADENIE int main() { int x, y, nasobok = 0; program vynásobí dve čísla len pomocou sčitovania, v cykle použijeme ladiace výpisy printf("Zadajte dve cisla: "); scanf("%d %d", &x, &y); printf("%d * %d = ", x, y); for(; y>0; y--) { nasobok += x; #ifdef LADENIE printf("n(y: %d, nasobok: %d)n", y, nasobok); #endif } printf("%dn", nasobok); return 0; }
Procedurálne programovanie: Funkcie a práca s pamäťou
Funkcie a práca s pamäťou • lokálne a globálne premenné • pamäť • funkcie
Globálne a lokálne premenné • stanovenie kde bude premenná dostupná – globálne premenné • platnosť: od miesta definície po koniec súboru (nie programu program sa môže skladať z viac súborov) – lokálne premenné • definované vo funkciách • platnosť: od definície po koniec funkcie
Príklad: globálne definície #include <stdio. h> int i; void prva() {. . . } premenná i je platná pre všetky 3 funkcie int j; int druha() {. . . } void main() {. . . } premenná j je platná len pre funkcie: druha() a main()
Lokálne premenné #include <stdio. h> int i 1, i 2; void prva() { int i 1, j 1; . . . } globálna premenná i 1 je prekrytá lokálnou premennou i 1 (používať sa môžu premenné: i 1, j 1 (lokálne) a i 2 (globálna)) int j 1, j 2; int druha() { int i 1, j 1, k 1; . . . } dve globálne premenné: i 2, j 2 a tri lokálne premenné: i 1, j 1, k 1.
Inicializácia lokálnych a globálnych premenných • lokálne premenné: – nie sú automaticky inicializované • globálne premenné: – automaticky inicializované na 0 (0. 0, ) (lepšie - nespoliehať sa na to) – vyhnúť sa globálnym premenným - môžu vniesť zmätok do väčších programov!
Alokácia pamäte • každá premenná musí mať v čase svojej existencie pridelený pamäťový priestor • akcia na vyhradenie pamäťového priestoru sa nazýva alokácia, ktorá môže byť – statická – dynamická
Statická alokácia pamäte • keď vieme prekladaču vopred povedať, aké máme na premenné pamäťové nároky – napr. vieme, že budeme potrebovať dve prenenné typu double a jednu premennú typu char • prekladač sám určí požiadavky pre všetky definované premenné a pri spustení programu sa pre ne alokuje miesto • behom programu sa nemanipuluje s touto pamäťou • premenné majú alokované miesto od začiatku programu do jeho konca • ruší ich operačný systém
Statická alokácia pamäte • vymedzuje miesto v dátovej oblasti • globálne premenné - statické • nie vždy to stačí – napr. rekurzia alebo do pamäte potrebujeme načítať obsah súboru – použiť dynamickú alokáciu, alebo vymedzenie pamäte v zásobníku
Dynamická alokácia • vymedzenie pamäte v hromade (heap) • za behu programu dynamicky prideliť (alokovať) oblasť pamäte určitej veľkosti • pristupuje sa do nej prostredníctvom ukazovateľov
Vymedzenie pamäte v zásobníku • zaisťuje kompilátor pri volaní funkcie • väčšina lokálnych premenných definovaných vo funkciách • existencia týchto premenných začína pri vstupe do funkcie a končí pri výstupe z funkcie • ak chceme prenášať hodnotu premennej medzi jednotlivými volaniami funkcie - nemôže byť premenná alokovaná v zásobníku
Funkcie • jazyk C je založený na funkciách – kratšie programy majú jednu funkciu main() – väčšina má viac funkcií • spracovanie programu – začína volaním funkcie main() – končí opustením funkcie main() • funkcie nemôžu byť vhniezdené • nie procedúry - všetky funkcie vracajú hodnotu – dajú sa použiť aj ako procedúry (vrátia void)
Definícia funkcie • definícia: určuje hlavičku aj telo funkcie • deklarácia: len špecifikuje hlavičku funkcie (meno, fyp návratovej hodhoty, parametre) – hlavička funkcie: – definícia: return h; - funkcia vráti hodnotu h – volanie funkcie: int max(int a, int b) { return (a > b ? a : b); } x = max(10 * i, j - 15);
Funkcia bez parametrov – definícia funkcie: int scitaj() { int a, b; scanf("%d %d", &a, &b); return (a + b); } – volanie funkcie: j = scitaj();
Procedúry a dátový typ void • formálne procedúry neexistujú, dá sa to obísť: 1. funkcia návratovú hodnotu vracia, ale nepotrebujeme ju, napr. čakanie na stlačenie klávesy (bez toho, aby nás zaujímalo, aká klávesa bola stlačená) getchar(); (void) getchar(); čakanie na stlačenie klávesy čitateľnejšie, niektoré prekladače to vyžadujú
Procedúry a dátový typ void 2. funkcia sa definuje ako funkcia vracajúca typ void (nič), napr. void vypis_int(int i) { printf("%d", i); } - volanie procedúry (funkcie): vypis_int(a + b);
Príklad 1: použitie funkcie v programe #include <stdio. h> int max(int a, int b) { return (a > b ? a : b); } int main() { int x, y; printf("Zadajte 2 cisla: "); scanf("%d %d", &x, &y); printf("Maximum: %dn", max(x, y)); return 0; } maximum z dvoch čísel
Príklad 2: použitie funkcie v programe #include <stdio. h> #define N 5 int max(int a, int b) { return (a > b ? a : b); } maximum z dvoch čísel volanie funkcie viackrát int main() { int i, x, y; for (i=1; i<=N; i++) { printf("[%d] zadajte 2 cisla: ", i); scanf("%d %d", &x, &y); printf("Maximum: %dn", max(x, y)); } return 0; }
Rekurzia : -) • vysvetlenie slova rekurzia vo výkladovom slovníku: - rekurzia: viď rekurzia • funkcia, ktorá volá samu seba (väčšinou s inými parametrami)
Rekurzívne funkcie • funkcie v C môžu byť aj rekurzívne, napr. faktoriál: #include <stdio. h> intfakt(int n) n) {{ return 0) ? ? 11 : : nn* *fakt(n - 1)); return ((n <= <= 0) - 1)); }} int main() { int i; printf("Zadajte cele cislo: "); scanf("%d", &i); printf("Fakrotial je %dn", fakt(i); return 0; }
Rekurzívne funkcie • pre n: 3 int fakt(int n) { return ((n <= 0) ? 1 : n * fakt(n - 1)); } • fakt(3): (3 <= 0) neplatí return(n 3 ** fakt(n-1)) fakt(2)) 2 6 • fakt(2): (2 <= 0) neplatí return(n 2 ** fakt(n-1)) fakt(1)) 1 2 • fakt(1): (1 <= 0) neplatí return(n 1 ** fakt(n-1)) fakt(0)) 1 1 • fakt(0): (0 <= 0) platí return(1) 1
Fibonacciho čísla 0, 1, 1, 2, 3, 5, 8, 13, 25, . . . (čísla v postupnosti sú súčtom dvoch predošlých čísel) f(1) = 0 f(2) = 1 f(n) = f(n-1) + f(n-2) • Pôvodný Fibonnaciho problém (1202) - ako sa môžu králiky rozmnožovať v ideálnych podmienkach
Fibonacciho králiky • Predpoklady: – máme novorodených párik králikov (samca a samičku) – králiky sa pária, keď majú jeden mesiac - na konci ich druhého mesiaca sa samičke narodí pár králikov – králiky nezomierajú a samička vždy vyprodukuje nový pár (jedného samčeka a jednu samičku) každý mesiac od svojho druhého mesiaca veku ďalej • Hádanka, ktrorú Fibonacci položil: – koľko párov bude za jeden rok?
Fibonacciho králiky 1 2 3 4 5 konci štvrtého mesiaca sa nana konci prvého mesiaca sa pária, druhého mesiaca sa na konci tretieho samičke bielym chvostíkom a aj stále ešte len jeden párnarodí samičke s sbielym chvostíkom samičke s hnedým nový párchvostíkom narodí nový pár
Fibonacciho čísla lastúra štvorce špirály semienka kvetov
Fibonacciho čísla: rekurzívne long fib(long n) { if (n <= 2) return n-1; else return fib(n-2) + fib(n-1); } 6 5 4 2 3 3 1 21 22 4 3 1 2 neefektívne, pretože sa veľakrát vypočítavajú tie isté čísla - iteratívne s použitím poľa - efektívne
Rekurzia • silná (krátky kód) • neefektívna • pokiaľ sa jej dá vyhnúť, nepoužívať (opakujúce sa výpočty radšej ukladať do pamäte)
Fibonacciho čísla: iteratívne long fib(long n) { if (n <= 2) return n-1; else { int n_1, n_2, i, sucet; n_1 = 0; n_2 = 1; for(i=3; i<=n; i++) { sucet = n_1 + n_2; n_1 = n_2; n_2 = sucet; } return sucet; } } iteratívne: nerekruzívne, s použitím cyklov
Funkcie vracajúce int a iné typy • funkcie vracajúce int – int môžeme vynechať int max(int a, int b) • funkcie vracajúce iný typ ako int – typ je potrebné uviesť double max(double a, double b)
Problémy s umiestnením definícií funkcií • funkcia nemôže byť definovaná vo vnútri inej funkcie • problém: – ak nejaká funkcia A() volá inú fuknkciu B(), ktorá je definovaná za A(), (A() nemá žiadne informácie o B()) int A(int x) {. . . y = B((float) x); . . . } float B(float f) {. . . }
Problémy s umiestnením definícií funkcií • menší problém, ak volaná funkcia (B()) vracia typ int • ak nevracia typ int, je potrebné prekladaču určiť aspoň návratový typ a meno volanej funkcie pred jej volaním dvoma spôsobmi: 1. deklaráciou návratového typu a mena 2. pomocou funkčného prototypu
Deklarácia návratového typu a mena • umiestnená kdekoľvek (pred volaním) – vo vnútri volajúcej funkce (A()) – na globálnej úrovni • starší spôsob: nie veľmi vhodné
Deklarácia návratového typu a mena #include <stdio. h> int A(int x) { int y; float B(); y = B(x); return y; } float B(float f) { return (f * 3. 14); }. . . vo vnútri funkcie
Deklarácia návratového typu a mena #include <stdio. h> float B(); int A(int x) { int y; y = B(x); return y; } float B(float f) { return (f * 3. 14); }. . . na globálnej úrovni
Použitie funkčného protorypu • ANSI verzia jazyka C • umožňuje prekladaču naviac aj kontrolu počtu a typov parametrov volanej funkcie (B()) • odporúča sa používať tento spôsob
Použitie funkčného prototypu #include <stdio. h> float B(float r); int A(int x) { int y; funkčný prototyp na globálnej úrovni y = B(x); return y; } float B(float r) { return (r * 2* 3. 14); }. . . funkčný prototyp sa dá použiť aj na lokálnej úrovni
Konverzia návratovej hodnoty funkcie • ak nie je návratový typ funkcie zhodný s návratovým typom výrazu - implicitná konverzia – napr. int konverzia(double d) { return (d); } – volanie: int k; k = konverzia(4. 5); hodnota 4. 5 bude pretypovaná na int oreže sa a k bude mať hodnotu 4
Parametre funkcií - volanie hodnotou • predávanie parametrov hodnotou – parametre sú vo funkcii len čítané – každá zmena parametra je dočasná, je len v rámci funkcie a po jej ukončení sa stratí • ako funguje: – vytvorí sa lokálna kópia premennej v zásobníku a vo funkcii sa pracuje len s ňou – na konci funkcie sa lokálna kópia stráca príklad: volanie funkcie int A(. . . ) s parametrom 3, ktorý sa vo funkcii zmení na 4
Parametre funkcií - volanie hodnotou dátová oblasť spustenie programu, volanie main() 3 vytvorí sa kópia volanie A() návrat do main() koniec programu, main() spustenie A(3) koniec A() 3 4 zásobník
Parametre funkcií - volanie odkazom • predávanie parametrov odkazom neexistuje v C – volanie odkazom by umožnilo meniť parametre v rámci funkcie – rieši sa pomocou ukazovateľov – ukazovateľ určuje, na ktorom mieste v dátovej pamäti sa má premenná zmeniť (nemení sa ukazovateľ - adresa) príklad: volanie funkcie int A(. . . ) s adresou premennej, ktorej hodnota je 3, Vo funkcii sa zmení hodnota premennej na 4
Parametre funkcií - volanie odkazom dátová oblasť spustenie programu, volanie main() adresa: 15 4 3 adresa premennej volanie A() návrat do main() koniec programu, main() spustenie A(15) koniec A() 15 zásobník
Procedurálne programovanie: Príklady
Príklad 1 program načíta celé číslo, potom umožní používateľovi v cykle číslo násobiť dvoma, deliť troma, vypísať číslo - pokým používateľ program neukončí
#include <stdio. h> int nasob_2(int x); int del_3(int x); int main() { int i, c; printf("Zadajte cele cislo: "); scanf("%d", &i); do { printf("ncislo printf("stlacte c = getch(); ma hodnotu: %dnn", i); N na vynasobie cisla dvoma. n"); D na vydelenie cisla troma. n"); K na ukoncenie programu. n"); if (c == 'n' || c == 'N') i = nasob_2(i); else if (c == 'd' || c == 'D') i = del_3(i); } while (c != 'k' && c != 'K'); return 0; } int nasob_2(int x) { return x * 2; } int del_3(int x) { return x / 3; }
Príklad 2 program vypočíta hodnotu funkcií p(x) a q(x) pre dané x. p(x) = p(x-1) + q(x/2) ak x > 1 2 q(x) = ak x <= 1 q(x-3) + p(x-5) ak x > 3 x/3 ak x <= 3
#include <stdio. h> float q(float x); float p(float x) { if (x <= 1) return 2. 0; return (p(x-1) + q(x/2)); } float q(float x) { if (x <= 3) return x / (float) 3. 0; return (q(x-3) * p(x-5)); } int main() { float x; do { printf("Zadajte realne cislo (konec pri zadani -1. 0)n"); scanf("%f", &x); if (x == -1. 0) break; printf("np(%. 3 f) = %. 3 fn", x, p(x)); printf("q(%. 3 f) = %. 3 fnn", x, q(x)); } while (1); }
Príklad 3 Faktoriál iteratívne #include <stdio. h> long faktorial(long n) { if (n <= 0) return 1; else { int i, f=1; for(i=1; i<=n; i++) f *= i; return f; . . . /* definicia funkcie faktorial */ void main () { int n; } } printf("Zadajte cele cislo: "); scanf("%d", &n); printf("%d! = %dn", n, faktorial(n)); }
Príklad 4 program opisuje text zo súboru subor. txt na obrazovku s tým, že po vypísaní jednej stránky čaká na stlačenie klávesy <Enter>
Príklad 4 #include <stdio. h> #define RIADKY_OBR 20 #define MENO "subor. txt" void vypis(FILE *fr); Úplný funkčný prototyp int main(void) { FILE *fr; if ((fr = fopen(MENO, "r")) == NULL) { printf("Subor %s nebol otevoreny. n", MENO); return 1; } vypis(fr); if (fclose(fr) == EOF) printf("Subor %s nebol zatvoreny. n", MENO); return 0; }
Príklad 4 pokračovanie: void vypis(FILE *fr) { int c, pocet = 0; while ((c = getc(fr)) != EOF) { putchar(c); if (c == 'n') { if (++pocet >= RIADKY_OBR) { pocet = 0; while (getchar() != 'n') ; } } Čaká na odriadkovanie, až potom vypisuje ďalšiu stránku
Všetky okná mi zase zamrzli! Deti, poponáhľajte sa pomôcť otcovi stlačiť Ctrl-Alt-Del!
- Slides: 91