procedur álne programovanie: 9 . prednáška
DESCRIPTION
Procedur álne programovanie: 9 . prednáška. Gabriela Kosková. Obsah. príklady k štruktúram a ukazovateľom (2) oddelen ý preklad b itov é operácie a polia. Príklad: simulácia pokladní v obchode. N pokladní v obchode Pri každej pokladni – rad zákazníkov. ZAKAZNIK *pokladne[N];. - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/1.jpg)
Procedurálne programovanie:9. prednáška
Gabriela Kosková
![Page 2: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/2.jpg)
Obsah
• príklady k štruktúram a ukazovateľom (2)
• oddelený preklad
• bitové operácie a polia
![Page 3: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/3.jpg)
Príklad: simulácia pokladní v obchode
• N pokladní v obchode
• Pri každej pokladni – rad zákazníkov
typedef struct zakaznik { int cislo; struct zakaznik *dalsi;} ZAKAZNIK;
ZAKAZNIK *pokladne[N];
• funkcie:– Výpis všetkých zákazníkov– Pridanie zákazníka– Vybavenie zákazníka (ten odíde)
![Page 4: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/4.jpg)
Príklad: simulácia pokladní v obchode
void vypis_vsetkych_zakaznikov(ZAKAZNIK *pokladne[N]);void pridaj_zakaznika(ZAKAZNIK *pokladne[N]);ZAKAZNIK *vyrob_zakaznika(int z);int najkratsi_rad(ZAKAZNIK *pokladne[N]);void vybaveny_zakaznik(int p, ZAKAZNIK *pokladne[N]);
void odchod_zakaznika(int cislo, ZAKAZNIK *pokladne[N]);int main();
• Námety na zamyslenie
• Uzatvorenie pokladne (potrebné zmeny aj v iných funkciách)
![Page 5: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/5.jpg)
void vypis_vsetkych_zakaznikov(ZAKAZNIK *pokladne[N]) { int i; ZAKAZNIK *akt; for(i=0; i<N; i++) { akt = pokladne[i]; printf("Pokladna %d: ", i); while(akt != NULL) { printf("%d ", akt->cislo); akt = akt->dalsi; } printf("\n"); }}
ZAKAZNIK *vyrob_zakaznika(int z) { ZAKAZNIK *zak = (ZAKAZNIK *) malloc(sizeof(ZAKAZNIK)); zak->cislo = z; zak->dalsi = NULL; return zak;}
![Page 6: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/6.jpg)
void pridaj_zakaznika(ZAKAZNIK *pokladne[N], int z) {
int min = najkratsi_rad(pokladne); ZAKAZNIK *akt = pokladne[min]; if(akt == NULL) pokladne[min] = vyrob_zakaznika(z); else { akt = pokladne[min]; while(akt->dalsi != NULL) akt = akt->dalsi; akt->dalsi = vyrob_zakaznika(z); } }
![Page 7: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/7.jpg)
int najkratsi_rad(ZAKAZNIK *pokladne[N]) { int min_dlzka, najkratsi, i, dlzka; ZAKAZNIK *akt; for(i=0; i<N; i++) { dlzka = 0; akt = pokladne[i]; while(akt != NULL) { dlzka++; akt = akt->dalsi; } if(i==0 || dlzka < min_dlzka) { min_dlzka = dlzka; najkratsi = i; } } return najkratsi; }
![Page 8: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/8.jpg)
void vybaveny_zakaznik(int p, ZAKAZNIK *pokladne[N]) { ZAKAZNIK *zrus;
if(pokladne[p] != NULL) { printf("Vybaveny zakaznik c. %d\n", pokladne[p]->cislo); zrus = pokladne[p]; pokladne[p] = pokladne[p]->dalsi; free(zrus); } }
![Page 9: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/9.jpg)
Rodostrom• Záznam o človeku:
– Meno– Priezvisko– Ukazovateľ na záznam o matke– Ukazovateľ na záznam o otcovi– Počet detí– Pole ukazovateľov na záznamy o ďeťoch
typedef struct clovek { char meno[20]; char priezvisko[20]; struct clovek *matka; struct clovek *otec; int pocet_deti; struct clovek **deti;} CLOVEK;
![Page 10: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/10.jpg)
CLOVEK **tety_a_strykovia(CLOVEK *clovek) { int pocet, i, j; CLOVEK **tetystr; pocet = clovek->matka->matka->pocet_deti -1; pocet += clovek->otec->matka->pocet_deti -1; tetystr = (CLOVEK **) malloc(pocet * sizeof(CLOVEK *)); j = 0; for(i=0; i<clovek->matka->matka->pocet_deti; i++) if(clovek->matka->matka->deti[i] != clovek->matka) { tetystr[j] = clovek->matka->matka->deti[i]; j++; } for(i=0; i<clovek->otec->matka->pocet_deti; i++) if(clovek->otec->matka->deti[i] != clovek->otec) { tetystr[j] = clovek->otec->matka->deti[i]; j++; } return tetystr; }
![Page 11: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/11.jpg)
Rodostrom• Skúste premyslieť
– Nájdenie všetkých bratrancov a sesterníc– Čo ak pripustíme aj nevlastných súrodencov (treba kontroľovať aj cez otca aj
matku)
![Page 12: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/12.jpg)
Procedurálne programovanie: Oddelený preklad
![Page 13: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/13.jpg)
Oddelený preklad
• vkladanie súborov – #include vznikne jeden .OBJ súbor
• oddelený preklad– každý súbor sa preloží zvlášť (vznikne viac .OBJ súborov) a potom
sa spoja pomocou linkeru
![Page 14: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/14.jpg)
Príklad oddeleného prekladu
s2.cs1.c s3.c s1.c s2.c s3.c
s.c
#include "s1.c"
#include "s2.c"
#include "s3.c"
s.obj
s1.obj s2.obj s3.obj
link s link s1, s2, s3
vkladanie súborov: oddelený preklad:
![Page 15: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/15.jpg)
Oblasť platnosti identifikátorov
• jazyk C umožňuje rôzne spôsoby ako stanoviť kde, kedy a aký identifikátor bude komu dostupný:– globálne a lokálne premenné
– pamäťové triedy
– typové modifikátory
![Page 16: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/16.jpg)
Globálne premenné
• organizácia v programe: globálne definície a deklarácie
definície funkcií
globálne definície: definujú premenné, rozsah ich platnosti: od miesta definície po koniec súboru (nie programu - program sa môže skladať z viac súborov)
globálne deklarácie: deklarácie premenných, ktoré sú definované v inom súbore. často sú špecifikované slovom extern - externé deklarácie
![Page 17: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/17.jpg)
Príklad: globálne definície
int i;
void prva(){...}
int j;
int druha(){...}
char *tretia(){...}
premenná i je platná pre všetky 3 funkcie
premenná j je platná len pre funkcie:druha() a tretia()
![Page 18: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/18.jpg)
Lokálne premenné
• definované vo funkciách
• platnosť lokálnych premenných: od definície po koniec funkcie
int i1, i2;
void prva() {int i1, j1;...}
int j1, j2;
int druha(){int i1, j1, k1;...}
globálna premenná i1 je prekrytá lokálnou premennou i1 (používať sa môžu premenné: i1, j1 (lokálne) a i2 (globálna))
dve globálne premenné: i2, j2 a tri lokálne premenné: i1, j1, k1.
![Page 19: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/19.jpg)
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, \0)
(lepšie - nespoliehať sa na to)
![Page 20: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/20.jpg)
Pamäťové triedy
• určujú v ktorej časti pamäte bude premenná umiestnená a kde bude viditeľná– auto– extern– static– register
![Page 21: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/21.jpg)
Trieda auto
• automatické premenné– implicitne pre lokálne premenné
– uložená v zásobníku (stacku)
– existuje od vstupu do funkcie do jej konca
– nie je inicializovaná
void func(){ auto int i; auto int j = 5;}
je ekvivalentné
void func(){ int i; int j = 5;}
![Page 22: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/22.jpg)
Trieda extern
• implicitne pre globálne premenné
• uložená v dátovej oblasti
• používa sa pri oddelenom preklade súborov, kde viac súborov zdiela jednu premennú– v jednom súbore je táto premenná definovaná bez kľúčového slova extern, v ostatných súboroch musí byť použité extern
int suma;
v súbore s1.c
definícia
extern int suma;
v súbore s2.c
deklarácia
![Page 23: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/23.jpg)
Trieda static
• neexistuje žiadna implicitná definícia
• najčastejšie lokálne premenné (definované vo funkcii), ktoré si nechávajú svoju hodnotu medzi jednotlivými volaniami funkcie
• premenná existuje od prvého volania funkcie do konca programu
int f() { int x = 2; static int i = 0; printf("i: %d, x: %d \n", i, x); i++; x++;}
for(j = 0; j < 3; j++) f();
i: 0, x: 2i: 1, x: 2i: 2, x: 2
![Page 24: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/24.jpg)
Trieda static
• globálne premenné: tiež static - viditeľné len v module, kde sú definované
• ak viac static premenných, radšej každú na zvlášť riadku
static int i, j; static int i;static int j;
![Page 25: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/25.jpg)
Trieda register
• jazyk C - nízkoúrovňový a preto umožňuje, aby premenná bola zapísaná v registri– ak sa dá
– do ktorého registra - vyberá si prekladač
– len lokálne premenné
– tie, ku ktorým je vhodné pristupovať rýchlo
register int i;
register int i;register int j;
ak je viac premenných, označenie triedy register vyznačiť pre každú premennú zvlášť
![Page 26: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/26.jpg)
Prílad použitia triedy register
void nasobilka(register int k){ register int i;
for (i = 1; i <= 10; i++) printf("%2d x %2d = %2d \n", i, k, i * k);}
násobky čísla k
![Page 27: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/27.jpg)
Typové modifikátory
• ľubovoľná premenná nejakého dátového typu (int i) zaradená do nejakej pamäťovej triedy (napr. static) môže byť modifikovaná typovým modifikátorom:– const– volatile
static const unsigned int j = 5;
napríklad:
![Page 28: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/28.jpg)
Modifikátor const
• v ANSI C
• po inicializácii už nemôže byť menená hodnota premennej
• podobne ako konštanta (#define), len má určený typ, čo konštanta nemá (dá sa využiť ku kontrolám prekladača (napr. typ skutočných parametrov funkcie))
• najčastejšie: pri definícii formálnych parametrov funkcie - parameter označený ako const je len vstupným parametrom (vo funkcii sa nemení)
int hladaj(const char *str, char co)
napríklad:
![Page 29: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/29.jpg)
Modifikátor const
const float pi = 3.14159;const int max = 100;
int pole[max];
pi = 3.14;
• časté chyby:
chyba: pi sa už nedá meniť
chyba: max nie je konštanta
![Page 30: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/30.jpg)
Modifikátor volatile
• v ANSI C
• málo časté
• upozorňuje prekladač, že premenná môže byť modifikovaná nejakou bližšie nešpecifikovanou asynchrónnou udalosťou (napr. pomocou prerušenia)– napr. cyklus (neobsahujúci premennú pocet), ktorý je závislý na
premennej pocet a tá je menená hardverovým prerušením
– ak by nebola označená modifikátorom volatile - prekladač by to mohol optimalizovať tak, že by premennú pocet nahradil jej hodnotou, akú mala pred cyklom
![Page 31: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/31.jpg)
Príklad: modifikátor volatile
volatile int pocet;
void wait(int maximum) { pocet = 0; while (pocet < maximum) ;}
cyklus skončí po zmene premennej pocet nejakým hardverovým prerušením
![Page 32: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/32.jpg)
Bloky
• blok programu - uzatvorený v { } môže obsahovať definície premenných– lokálne premenné (auto, alebo static)
– viditeľné sú len v bloku
if (i > 0) { int i; ...}else { double f; ...}
![Page 33: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/33.jpg)
Príklad oddeleného prekladu
s2.cs1.c s3.c s1.c s2.c s3.c
s.c
#include "s1.c"
#include "s2.c"
#include "s3.c"
s.obj
s1.obj s2.obj s3.obj
link s link s1, s2, s3
vkladanie súborov: oddelený preklad:
![Page 34: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/34.jpg)
Oblasť platnosti identifikátorov: zhrnutie
• globálne a lokálne premenné
• pamäťové triedy: – auto (implicitne lokálne premenné, v stacku)– extern (implicitne globálne premenné, v dátovej oblasti)– static (lokálne premenné: zachovávajú hodnotu medzi volaniami
funkie, globálne premenné: platnosť v rámci jedného súboru)– register (lokálne premenné, zapísané v registri)
• typové modifikátory:– const (konštantné premenné, nemenia hodnotu)– volatile (lokálne premenné, zmena hardverovým prerušením)
![Page 35: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/35.jpg)
Oddelený preklad súborov
• rozdeliť program na viac čo najmenej závislých častí• definovať rozhranie - spôsob komunikácie medzi
oddelenými časťami (.h súbory)– pomocou funkcií (lepšie ako pomocou globálnych premenných
viditeľných vo všetkých súboroch)
![Page 36: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/36.jpg)
Rozšírenie platnosti globálnej premennej
• globálna premenná:– definovaná v jednom súbore– deklarovaná pomocou extern v ostatných súboroch
![Page 37: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/37.jpg)
Príklad: rozšírenie platnosti globálnej premennej
int x;extern double f;
int fun(void) { return (x + (int) f);}
#include <stdio.h>
extern int x;extern int fun(void);
double f;
void main(){ x = 3; f = 3.5; printf("%d \n", fun());}
A.c: B.c:
definície
deklarácie
![Page 38: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/38.jpg)
Statické globálne premenné a funkcie
• trieda static - viditeľné len v module, v ktorom boli definované– pre globálne premenné
– pre funkcie
![Page 39: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/39.jpg)
Príklad: statické globálne premenné a funkcie
static int x;extern double f;
static int fun(void) { return x;}static int funkcia(void) { return (x + (int) f);}
#include <stdio.h>
extern int x;extern int funkcia(void);double f;
static void fun(void) { prinftf("%d \n", funkcia());}
void main() { x = 3; f = 3.5; printf("%d \n", fun());}
A.c: B.c:
pri linkovaní chyba:x: v A.c static v B.c len deklarácia
![Page 40: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/40.jpg)
Zdrojové a hlavičkové súbory
• .c súbory - definície globálnych premenných a funkcií:– pre všetky moduly (žiadne označenie)
– len pre aktuálny modul (označenie static)
• .h súbory - definujú rozhranie, t.j. definujú globálne premenné a funkcie, ktoré sa používajú v iných moduloch (označenie extern)
• .c súbory include-ujú len .h súbory ktoré potrebujú (nikdy ne-include-ujú .c súbory)
![Page 41: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/41.jpg)
Ako udržať poriadok vo veľkom programe
1. definície funkcií a premenných v súbore program_1.c
2. v program_1.c - striktne rozlíšené, čo sa bude používať v rámci súboru a čo mimo neho (čo najmenej)
3. všetky ostatné globálne premenné a funkcie označiť static
4. funkčné prototypy zdielaných funkcií a premenných - do program_1.h, označíme ich extern
5. ak poskytujeme aj symbolické konštanty - dáme ich len do program_1.h
6. program_1.c začína: #include <stdio.h>#include "program_1.h"
![Page 42: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/42.jpg)
Ako udržať poriadok vo veľkom programe
7. súbor program_2.c obsahujúci ďalší modul programu a využíva premenné, funkcie alebo konštanty z modulu program_1, začína:
#include <stdio.h>#include "program_1.h"#include "program_2.h"
![Page 43: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/43.jpg)
Odporučený obsah .c súborov
1. dokumentačná časť
(meno súboru, verzie, stručný popis modulu, meno autora a dátum)
2. všetky potrebné #include len súbory .h, nie .c!
najprv systémové < > a potom vlastné " "
3. deklarácie importovaných objektov (extern)len ak nie sú v .h súbore spolupracujúceho modulu (čomu dávame prednosť) - v iných moduloch sú tieto objetky bez špecifikovanej triedy
4. definície globálnych premenných
premenné definované mimo funkcií zdielané inými modulmi (čo najmenej!)
![Page 44: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/44.jpg)
Odporučený obsah .c súborov
5. lokálne #definedefinícia konštánt a makier len pre aktuálny modul
len ak veľmi rozsiahle - do zvlášť .h
6. definície lokálnych typovtypedef len pre aktuálny modul
len ak veľmi rozsiahle - do zvlášť .h
7. definície premenných len pre aktuálny modulglobálne len pre aktuálny modul - static
8. úplné funkčné prototypy funkcií len pre aktuálny modul
9. funkcia main()
10. definície funkcií aj pre iné moduly
11. definície funkcií len pre aktuálny modul
![Page 45: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/45.jpg)
Odporučený obsah .h súborov
1. dokumentačná časť(meno súboru, verzie, stručný popis modulu, meno autora a dátum)
2. definície symbolických konštánt ktoré sa budú používať aj v iných moduloch
3. definície makier s parametrami, ktoré sa budú používať aj v iných moduloch
4. definície typov, ktoré sa budú používať aj v iných moduloch
5. deklarácie premenných aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
6. funkčné prototypy funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
![Page 46: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/46.jpg)
Príklad: oddelený preklad
globálne premenné a funkcie
lokálne premenné a funkcie
kruh_main double obvod
double
vyp_priemer(double
polomer)
double polomer, obsahvoid vyp_obsah(double polomer)doble vyp_obvod()void vypocet(void)
kruh_io double vstup_dat()double vystup_dat(double obsah)
double polomer
• program na výpočet obsahu a obvodu kruhu:
kruh_main.c, kruh_main.h, kruh_io.c, kruh_io.h
premenné a funkcie definované v jednom z modulov - môžu sa používať aj v rámci druhého modulu
![Page 47: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/47.jpg)
#include <stdio.h>#include "kruh_main.h"#include "kruh_io.h"
double obvod;#define pi 3.14;
static double polomer;static double obsah;
double vyp_priemer(double polomer);static void vyp_obsah (double polomer);static doble vyp_obvod();static void vypocet(void);
void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) printf("Chybny polomer."); else { vypocet(); vystup_dat(obsah); }}
static void vyp_obsah(double polomer) { obsah = PI * polomer *polomer;}
static doble vyp_obvod() { return(PI*vyp_priemer(polomer));}
static void vypocet(void) { obvod = vyp_obvod(); vyp_obsah(polomer);}
double vyp_priemer(double polomer) { return (2 * polomer);}
kruh_main.cglob. definície
![Page 48: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/48.jpg)
extern double obvod;
extern double vyp_priemer(double polomer);
kruh_main.h
Hlavičkový súbor modulu kruh_main
deklarácie premenných a funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
![Page 49: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/49.jpg)
#include <stdio.h>#include "kruh_io.h"#include "kruh_main.h"
#define kontrola(x) ((x >= 0.0) ? x : CHYBA_DAT)
static double polomer;
double vstup_dat(void) { printf("Zadaj polomer kruznice: "); scanf("%lf", &polomer); return kontrola(polomer);}
void vystup_dat(double obsah) { double priemer;
printf("Obsah kruhu s polomerom %6.2f je %.2f\n", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2f\n", polomer, obvod);}
glob. definície
kruh_io.c
![Page 50: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/50.jpg)
#define CHYBA_DAT -1
extern double vstup_dat();
extern double vystup_dat(double obsah);
Hlavičkový súbor modulu kruh_io
deklarácie premenných a funkcií aktuálneho modulu, ktoré sa budú používať v iných moduloch (tu označené extern)
kruh_io.h
![Page 51: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/51.jpg)
#include <stdio.h>
#include "kruh_io.h"#include "kruh_main.h"
#define kontrola(x) ((x >= 0.0) ? x : CHYBA_DAT)
static double polomer;
double vstup_dat(void) { printf("Zadaj polomer kruznice: "); scanf("%lf", &polomer); return kontrola(polomer);}
void vystup_dat(double obsah) { double priemer;
printf("Obsah kruhu s polomerom %6.2f je %.2f\n", polomer, obsah); priemer = vyp_priemer(polomer); printf("Obvod kruhu s polomerom %6.2f je %.2f\n", polomer, obvod);}
kruh_io.c
static void vyp_obsah(double polomer) { obsah = PI * polomer *polomer;}
static doble vyp_obvod() { return(PI*vyp_priemer(polomer));}
static void vypocet(void) { obvod = vyp_obvod(); vyp_obsah(polomer);}
double vyp_priemer(double polomer) { return (2 * polomer);}
#include <stdio.h>
#include "kruh_main.h"#include "kruh_io.h"
double obvod;#define pi 3.14;
static double polomer;static double obsah;
static void vyp_obsah (double polomer);static doble vyp_obvod();static void vypocet(void);
void main() { polomer = vstup_dat(); if (polomer == CHYBA_DAT) printf("Chybny polomer."); else { vypocet(); vystup_dat(obsah); }} kruh_main.c
extern double obvod;
extern double vyp_priemer(double polomer);
kruh_main.h
#define CHYBA_DAT -1
extern double vstup_dat();
extern double vystup_dat(double obsah); kruh_io.c
Oddelený preklad
![Page 52: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/52.jpg)
Visual C++ a oddelený preklad
• vytvorenie projektu
(Win32 Console Application)
• vloženie súboru– C++ Source File
– C/C++ Header File
• Menu Build1. Build program.exe
2. Compile program.exe
![Page 53: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/53.jpg)
Procedurálne programovanie:Bitové operácie
![Page 54: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/54.jpg)
Práca s bitmi
• práca s reprezentáciou čísla v dvojkovej sústave
• Príklady:– 1: 001– 2: 010– 3: 011– 4: 100
Prevod čísla do dvojkovej sústavy -
príklad prevod čísla 4:
4 / 2 = 2 zvyšok 0
2 / 2 = 1 zvyšok 0
1 / 2 = 0 zvyšok 1
Prevod čísla do dvojkovej sústavy (delenie dvomi)
Výsledok sa použije ako delenec v nasledujúcej časti
prevodu
Zvyšky prečítané zospodu hore
predstavujú číslo v dvojkovej sústave
![Page 55: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/55.jpg)
Oprácie s jednotlivými bitmi
• operátory:– & - bitový súčin (AND)– | - bitový súčet (OR)– ^ - bitový exkluzívny súčet (XOR)– << - posun doľava– >> - posun doprava– ~ - jednotkový doplnok (negácia bit po bite)
• argumenty nemôžu byť float, double ani long double
![Page 56: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/56.jpg)
Bitový súčin
• i-ty bit výsledku x & y bude 1 vtedy, ak i-ty bit x aj i-ty bit y sú 1, inak 0 (AND po bitoch)
#define je_neparne(x) (1 & (unsigned) (x))
0000 0000 0000 0001xxxx xxxx xxxx xxx?&
0000 0000 0000 000?0
01
1
• ak chceme premennú typu int použiť ako ASCII znak, teda potrebujeme najmenších 7 bitov
0000 0000 0111 1111 = 0x7F c &= 0x7F;c = c & 0x7F;
x y x&y0 0 00 1 01 0 01 1 1
![Page 57: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/57.jpg)
Rozdiel medzi bitovým a logickým súčin
• k: 1, pretože 1 a 2 sú kladné číla, teda majú logickú hodnotu true (pravda) a && je logický súčin
unsigned int i = 1, j = 2, k, l;k = i && j;l = i & j;
• l: 0, pretože 1 = 0000 0001
2 = 0000 0010
a & je bitový súčin
![Page 58: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/58.jpg)
Bitový súčet
• i-ty bit výsledku x | y bude 1 vtedy, ak i-ty bit x alebo i-ty bit y sú 1, inak 0 (OR po bitoch)
• používa sa na nastavenie niektorých bitov na jednotku, pričom nechá ostatné bity nezmenené
#define na_neparne(x) (1 | (unsigned) (x))
0000 0000 0000 0001xxxx xxxx xxxx xxx?|
xxxx xxxx xxxx xxx?1
01
1
makro vráti nepárne číslo nezmenené a párne zväčší o 1
x y x|y0 0 00 1 11 0 11 1 1
![Page 59: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/59.jpg)
Bitový exkluzívny súčet
• i-ty bit výsledku x ^ y bude 1 vtedy, ak sa i-ty bit x nerovná i-temu bitu y, inak 0 (XOR po bitoch)
if (x ^ y) /* cisla sú rozdielne */
x y x^y0 0 00 1 11 0 11 1 0
![Page 60: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/60.jpg)
Bitový posun doľava
• x << n posunie bity v x o n pozícií doľava
• bity zľava sa strácajú bity zprava sú dopĺňané nulami
x = x << 1;
x = 0001 1011 0010 0101
x << 1 = 0011 0110 0100 1010
= 6949
= 13898 = 2 * 6949
na rýchle násobenie dvomi
x = x << 3; vynásobesnie 23 = 8
![Page 61: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/61.jpg)
Bitový posun doprava
• x >> n posunie bity v x o n pozícií doprava
• bity zprava sa strácajú bity zľava sú dopĺňané nulami
x = x >> 1;
x = 0011 0110 0100 1010
x >> 1 = 0001 1011 0010 0101
= 13898
= 6949 = 13898 / 2
na rýchle celočíselné delenie dvomi
x = x >> 3; celočíselné delenie 23 = 8
![Page 62: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/62.jpg)
Príklad: delenie a násobenie
• bitové posuny sú rýchlejšie ako násobenie a delenie násobkami dvojky
i = j * 80;i = (j << 6) + (j << 4);
80 = 64 + 16 rýchlejšie
![Page 63: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/63.jpg)
0000 0000 1100 10011
Príklad: zistenie hodnoty konkrétneho bitu
#define ERROR -1#define CLEAR 1#define BIT_V_CHAR 8
int bit(unsigned x, unsigned i){ if (i >= sizeof(x) * BIT_V_CHAR) return (ERROR); else return ((x >> i) & CLEAR);}
0011 0010 0101 00101
0001 1001 0010 10011
0000 1100 1001 01001
0000 0110 0100 10101
0000 0011 0010 01011
0000 0001 1001 00101
0000 0000 1100 10011
& 0000 0000 0000 0001
0000 0000 0000 0001
vráti hodnotu i-teho bitu x
![Page 64: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/64.jpg)
Negácia po bitoch
• jednotkový doplnok ~x• prevráti nulové bity na jednotkové a naopak
• Použitie napr. ak sa chceme vyhnúť na počítači závislej dĺžke celého čísla:
x &= 0xFFF0;
x &= ~0xF;
nastavenie posledných 4 bitov na nulu - len ak platí
sizeof(int) == 2
nastavenie posledných 4 bitov na nulu - platí pre všade
![Page 65: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/65.jpg)
Príklad
#include <stdio.h>
int dlzka_int(){ unsigned int x, i = 0; x = ~0; /* negácia 0 -> same 1 */
while ((x >> 1) != 0) i++; return (++i);}
int main(){ printf("Dlzka typu int je %d bitov\n", dlzka_int()); return 0;}
Zistenie dĺžkyky typu int v bitoch
![Page 66: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/66.jpg)
Práca so skupinou bitov
#define READ 0x8#define WRITE 0x10#define DELETE 0x20
unsigned int stav;
stav |= READ | WRITE | DELETE;stav |= READ | WRITE;stav &= ~(READ | WRITE | DELETE);stav & = ~READ;if ( ! (stav & (WRITE | DELETE))) ...
• stavová premenná stav - definuje práva na prístup k súboru
READ: 23 = 0000 0100 WRITE: 24 = 0000 1000 DELETE: 25 = 0001 0000
nastaví 2., 3. a 4. bit na 1
nastaví 2., 3. bit na 1
nastaví 2., 3. a 4. bit na 0
nastaví 2. bit na 0
ak 2. a 3. bit sú nulové
![Page 67: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/67.jpg)
Bitové pole
• štruktúra, ktorej veľkosť je obmedzená veľkosťou typu int
• najmenšia dĺžka položky je 1 bit• definuje podobne ako štruktúra, ale každá položka
bitového poľa je určená menom a dĺžkou v bitoch• môže byť signed aj unsigned (preto vždy uviesť)• oblasti použitia:
– uloženie viac celých čísel v jednom (šetrenie pamäte)
– pre prístup k jednotlivým bitom (často)
![Page 68: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/68.jpg)
Príklad bitového poľa
typedef struct { unsigned den : 5; unsigned mesiac : 4; unsigned rok : 7;} DATUM;
DATUM dnes, zajtra;dnes.den = 29;dnes.mesiac = 11;dnes.rok = 2012 - 1980;zajtra.den = dnes.den + 1;
• uloženie dátumu do jednotho int-u:– deň - najmenších 5 bitov,
– mesiac - ďalšie 4 bity,
– rok - zvyšných 7 bitov (max. 127, preto rok - 1980)
bity 0-4
bity 5-8
bity 9-15
![Page 69: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/69.jpg)
Príklad bitového poľa
#include <stdio.h>
typedef struct { unsigned den : 5; /* bity 0 - 4 */ unsigned mesiac : 4; /* bity 5 - 8 */ unsigned rok : 7; /* bity 9 - 15 */} DATUM;
typedef union { DATUM datum; unsigned int cislo;} BITY;
Dátum ako bitové pole aj hexadecimálne číslo (union)
![Page 70: Procedur álne programovanie: 9 . prednáška](https://reader033.vdocuments.pub/reader033/viewer/2022061614/56813c8e550346895da63628/html5/thumbnails/70.jpg)
Príklad bitového poľa - pokračovanie
int main(void){ BITY dnes; int d, m, r;
printf("Zadaj dnesny datum [dd mm rrrr]: "); scanf("%d %d %d", &d, &m, &r); dnes.datum.den = d; dnes.datum.mesiac = m; dnes.datum.rok = r - 1980;
printf("datum: %2d.%2d.%4d - cislo: %X hexa\n", dnes.datum.den, dnes.datum.mesiac, dnes.datum.rok + 1980, dnes.cislo); return 0;}
#include <stdio.h>
typedef struct { unsigned den : 5; unsigned mesiac : 4; unsigned rok : 7;} DATUM;
typedef union { DATUM datum; unsigned int cislo;} BITY;