1 / 65

Pro cedurálne programovanie: 10 prednáška

Pro cedurálne programovanie: 10 prednáška. Gabriela Kosková. Obsah. Opakovanie v príkladoch. getchar() - na na čítavanie znakov, nie čísel!. int i ; char c ; ... c = getchar() ; scanf("%c", &c); scanf("%d", &i);. Na čítanie znaku aj pomocou getchar , aj pomocou scanf.

renata
Télécharger la présentation

Pro cedurálne programovanie: 10 prednáška

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Procedurálne programovanie:10 prednáška Gabriela Kosková

  2. Obsah • Opakovanie v príkladoch

  3. getchar() - na načítavanie znakov, nie čísel! int i; char c; ... c = getchar(); scanf("%c", &c); scanf("%d", &i); Načítanie znaku aj pomocou getchar, aj pomocou scanf getchar a scanf int i; ... i = getchar();

  4. scanf a & int i; char c, str[10], *r; r = (char *) malloc(5*sizeof(char)); scanf("%d", &i); scanf("%c", &c); scanf("%s", str); scanf("%s", r); scanf očakáva adresy premenných, do ktorých má zapísať načítanú hodnotu vo funkcii scanf sa vytvorí lokálna premenná ako kópia parametra - adresa, tam sa zapíše načítaná hodnota keď skončí funkcia, zabudne sa lokálna kópia, teda zabudne sa adresa, no na tej adrese zostane načítaná hodnota i - premenná, &i- adresa premennej, c - premenná, &c - adresa premennej, str - statická adresa poľa (reťazca znakov) r - adresa poľa (reťazca znakov)

  5. char str[10], pismeno; int pocet; ... pismeno = najcastejsie_pismeno(str, &pocet); Vrátenie hodnoty cez parameter funkcie char najcastejsie_pismeno(char *str, int *pocet) { int hist['Z'-'A'+1], i, i_max; for (i=0; i<'Z'-'A'+1; i++) hist[i] = 0; for (i=0; i<strlen(str); i++) hist[toupper(str[i])-'A']++; i_max = 0; for (i=0; i<'Z'-'A'+1; i++) if (hist[i]>hist[i_max]) i_max = i; *pocet = hist[i_max]; return (i_max + 'A'); }

  6. & a && Čo vypíše táto časť programu? Pomôcka: 11 = (1011)2 4 = (100)2 x = 11; y = 4; if (x && y) printf("*"); if (x & y) printf("+"); Logický súčin (&&): nenulové čísla sú PRAVDA, 11, 4 sú nenulové, preto výsledok je PRAVDA  vypíše sa * Bitový súčin (&): súčin po bitoch 0: NEPRAVDA  + sa nevypíše Vypíše sa *

  7. Typová konverzia Reálne delenie dvoch celých čísel. #include <stdio.h> int main(void) { int i = 5, j = 2; float f; f = (float) i / j; printf("Typova konverzia: 1. moznost: %lf\n", f); f = i / (float) j; printf("Typova konverzia: 2. moznost: %lf\n", f); f = (float) i / (float) j; printf("Typova konverzia: 3. moznost: %lf\n", f); f = (float) (i / j); printf("Explicitna typ. konverzia - chybne: %lf\n", f); f = i / j; printf("Implicitna typ. konverzia - chybne: %lf\n", f); return 0; }

  8. Čítanie čísel, ktoré predchádza niekoľko hviezdičiek Vrátenie znaku #include <stdio.h> int main(void){ FILE *fr; int c, cislo, suma = 0; if ((fr = fopen("cisla.txt", "r")) == NULL) { printf("Subor cisla.txt sa nepodarilo otvorit\n"); return 1; } while (1) { while ((c = getc(fr)) == '*')/* citanie znakov '*' */ ; if (c == EOF) break; ungetc(c, fr);/*vratenie znaku spat do suboru*/ fscanf(fr, "%d\n", &cislo); suma += cislo; } printf("Sucet cisel je: %d\n", suma); if (fclose(fr) == EOF) printf("Subor sa nepodarilo uzavriet.\n"); return 0; }

  9. Ukazovatele • Premenné obsahujúce adresy • Definícia ukazovateľa: int *p; • Nikdy nepracujte s ukazovateľom, ktorý ste predtým nenasmerovali na nejakú zmysluplnú adresu! • Ak potrebujeme zaistiť, aby ukazovateľ neukazoval na konkrétne miesto priradíme mu hodnotu NULL

  10. & - vráti adresu premennej Ukazovatele bez operátora - hodnota premennej (ak je hodnotou adresa, tak je to adresa) int **p, *q, r; p = &q; * - vráti hodnotu premennej vezme ako adresu a z tej adresy vráti hodnotu q = &r; r = 5; printf("%p %p %p %p %p %d %p %d %d", &p,&q,&r, p, q, r, *p,*q,**p); 17 51 67 51 67 5 67 5 5 p: ukazovateľ na ukazovateľ na int q: ukazovateľ na int r: int 51 67 5 17 51 67

  11. Ukazovatele a polia int *p, q[5], i=0; for (i=0; i<5; i++) q[i] = i; p = q; p = q+2; /* to iste ako p = &q[2] */ i = *(q+2); /* to iste ako i = q[2] */ q: statický ukazovateľ na int p: ukazovateľ na int q[0]:int i:int q[1]:int q[4]:int 5 2 57 61 0 1 2 3 4 57 59 61 63 65 103 19

  12. Ukazovatele Adresa začiatku poľa &pole[0] pole+0 pole &pole[i] pole+i pole[i] *(pole+i) pole[0]=10; *pole=10; pole[10]=70;*(pole+10)=70; Adresa i-teho prvku poľa Hodnota i-teho prvku poľa Priradenie do 1. prvku poľa Priradenie do 10. prvku poľa

  13. Názov knihy Meno autora Rok položky jednoho záznamu jeden záznam o jednej knihe (obsahujúci všetky položky) zoznam záznamov o knihách (pole) Kartotéka v knižnici Hlava XXII Joseph Heller 1961

  14. Príklad: Kartotéka v knižnici Program načíta celé číslo n, následne načíta n záznamov o knihách a uloží ich do poľa. Potom ponúkne používateľovi menu, kde môže pridávať záznam na koniec, zmazať ktorýkoľvek záznam a ukončiť program.

  15. Kartotéka v knižnici: implementácia #include <stdio.h> #include <stdlib.h> #include <conio.h> #define N 50 /* dlzka retazcov znakov */ #define K 50 /* max. pocet prvkov v kartoteke */ typedef struct { char meno[N]; char priezvisko[N]; } AUTOR; typedef struct { char nazov[N]; AUTOR autor; int rok; } KNIHA;

  16. /* nacitanie a pridanie zaznamu na koniec zoznamu*/ void pridaj(KNIHA kniznica[], int *n); /* nacitanie indexu zaznamu a jeho zmazanie */ int zmaz(KNIHA kniznica[], int n); /* vypis zoznamu */ void vypis(KNIHA kniznica[], int n); int main() { int i, n; char c; KNIHA kniznica[K]; printf("Zadajte pocet knih: "); scanf("%d", &n); if (n > K) return 1; i = 0; /* nacitanie zaznamov do zoznamu */ while (i < n) pridaj(kniznica, &i);

  17. do { vypis(kniznica, n); printf("p: pridanie\nz: zmazanie\nk: koniec\n"); c = tolower(getch()); switch(c) { case 'p': pridaj(kniznica, &n); break; case 'z': n = zmaz(kniznica, n); break; } } while (c != 'k'); return 0; }

  18. void pridaj(KNIHA kniznica[], int *n) { if ((*n+1) > K) { printf("Kniznica je plna.\n"); return; } else { printf("Zadajte nazov knihy, autora (meno, "); printf("priezvisko) a rok vydania:\n"); scanf("%s %s %s %d", kniznica[*n].nazov, kniznica[*n].autor.meno, kniznica[*n].autor.priezvisko, &kniznica[*n].rok); (*n)++; } }

  19. int zmaz(KNIHA kniznica[], int n) { int i; printf("Zadajte index zaznamu na zmazanie: "); scanf("%d", &i); if (i < 0 || i >= n-1) { printf("Prvok sa v poli nenachadza.\n"); return n; } while (i < n-2) { kniznica[i] = kniznica[i+1]; i++; } return n-1; }

  20. void vypis(KNIHA kniznica[], int n) { int i; printf("\nKNIZNICA\n\n"); for (i=0; i<n; i++) printf("%s %s: %s (%d)\n", kniznica[i].autor.meno, kniznica[i].autor.priezvisko, kniznica[i].nazov, kniznica[i].rok); printf("\n\n"); }

  21. Námety na precvičenie • kartotéka ako spájaný zoznam: typedef struct kniha{ char nazov[N]; AUTOR autor; int rok; struct kniha *dalsia; } KNIHA;

  22. Príklad: Zlomky • oddelený preklad: • modul zlomky: zlomky.c a zlomky.h • modul hlavny: hlavny.c

  23. zlomky.h typedef struct { int citatel; int menovatel; } ZLOMOK; extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b); extern void vypis(ZLOMOK a);

  24. zlomky.c #include <stdio.h> #include "zlomky.h" ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b) { int n; ZLOMOK *z = (ZLOMOK *) malloc(sizeof(ZLOMOK)); z->citatel = a->citatel* b->menovatel + b->citatel * a->menovatel; z->menovatel = a->menovatel * b->menovatel; n = nsd(z->citatel, z->menovatel); z->citatel /= n; z->menovatel /= n; return z; } void vypis(ZLOMOK *a) { printf("%d / %d\n", a->citatel, a->menovatel); } static int nsd(int a, int b) { /* o chvilu... */ }

  25. hlavny.c #include <stdio.h> #include "zlomky.h" int main() { ZLOMKY *x, *y, *z; x = (ZLOMOK *) malloc(sizeof(ZLOMOK)); y = (ZLOMOK *) malloc(sizeof(ZLOMOK)); printf("Zadajte dva zlomky: "); scanf("%d %d", &x->citatel, &x->menovatel); scanf("%d %d", &y->citatel, &y->menovatel); z = spocitaj(x, y); printf("Sucet zlomkov je: "): vypis(z); return 0; }

  26. typedef struct { int citatel; int menovatel; } ZLOMOK; extern ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b); extern void vypis(ZLOMOK a); zlomky.h #include <stdio.h> #include "zlomky.h" ZLOMOK *spocitaj(ZLOMOK *a, ZLOMOK *b) { int n; ZLOMOK *z = (ZLOMOK *) malloc(sizeof(ZLOMOK); z->citatel = a->citatel + b->citatel; z->menovatel = a->menovatel + b->menovatel; n = nsd(z->citatel, z->menovatel); z->citatel /= n; z->menovatel /= n; } void vypis(ZLOMOK *a) { printf("%d / %d\n", a->citatel, a->menovatel); } static int nsd(int a, int b) { } #include <stdio.h> #include "zlomky.h" int main() { ZLOMKY *x, *y, *z; x = (ZLOMOK *) malloc(sizeof(ZLOMOK)); y = (ZLOMOK *) malloc(sizeof(ZLOMOK)); printf("Zadajte dva zlomky: "); scanf("%d %d", &x->citatel, &x->menovatel); scanf("%d %d", &y->citatel, &y->menovatel); z = spocitaj(x, y); printf("Sucet zlomkov je: "): vypis(z); return 0; } hlavny.c zlomky.c

  27. NSD a NSN program načíta dve celé čísla a vypíše ich najväčší spoločný deliteľ (NSD) a najmenší spoločný násobok (NSN).

  28. NSD • platí • NSD(0,0)=0 • NSD(a, b)=NSD(b, a) • NSD(a, b)=NSD(-a, b) • NSD(a,0)=ABS(a)  budeme uvažovať len nezáporné čísla • algorimtus: • Eukleidos popísal tento algoritmus v knihe Základy (okolo r. 300 p.n.l.). Algoritmus je založený na platnosti rekurzívneho vzťahu: NSD(a, b)=NSD(b, a % b)

  29. Dôkaz algoritmu • Predpokladajme, že: • a, b - čísla, ktorých NSD chceme nájsť • zvyšok po delení a/b je t, teda a = qb + t • Potom • každý spoločný deliteľ a a b delí t bezo zvyšku (lebo t = a - qb) • podobne, každý spoločný deliteľ b a t tiež delí a • Potom aj najväčší spoločný deliteľ a a b je tiež najväčším spoločným deliteľom b a t • Potom sa dá ďalej pokračovať s b a t namiesto a a b. Keďže t je menšie v absolútnej hodnote, pokým t nedosiahne 0

  30. NSD int nsd(int a, int b) { int pom; do { if (a < b) { pom = a; a = b; b = pom; } a %= b; } while (a); return b; }

  31. NSN • najmenšie kladné číslo, ktoré je násobkom čísel a, b • algorimtus: • vychádza zo vzťahu: a * b =NSD(a, b)*NSN(a, b) int nsn(int a, int b) { return a * b / nsd(a, b); }

  32. NSD a NSN #include <stdio.h> int nsd(int a, int b); int nsn(int a, int b); void main(void) { int m, n; scanf("%d %d",&m,&n); printf("NSD(%d,%d) = %d\n",m, n, nsd(m, n)); printf("NSN(%d,%d) = %d\n",m, n, nsn(m, n)); }

  33. Po Ut St Št Pi So Ne Matematika Mrkvička 3 hodiny Príklad rozvrh Program načíta zo súboru údaje o hodinách v rozvrhu a vypíše rozvrh na obrazovku • dvojrozmerné pole • práca so súborom • štruktúra • parametre funkcie main

  34. vyuč. hodina: 4 riadne hodiny  4 záznamy: MAT Maly 0 MAT Maly 1 MAT Maly 1 MAT Maly 1 Vstupný súbor a štruktúra 1 1 MAT Maly 4 2 3 FYZ Velky 2 3 2 ANG Pekna 3 3 3 TEL Vesely 10 5 3 SJ Zeleny 1 • Súbor: • deň hodina • skratka predmetu • meno učiteľa • počet hodín • Štruktúra: • predmet • ucitel • cast: • -1: voľno • 0: začiatok vyuč. hodiny • 1: stred alebo koniec vyuč.hodiny • Námet na precvičenie: • Rozvrh ako pole spájaných zoznamov

  35. Rozvrh: príklad výstupu ROZVRH ----------------------------------------------------------------------- | Pondelok| MAT, Maly | | ----------------------------------------------------------------------- | Utorok| | | FYZ,Velky | | ----------------------------------------------------------------------- | Streda| | ANG,Pekna| TEL,Vesel | ----------------------------------------------------------------------- | Stvrtok| | | | | | ----------------------------------------------------------------------- | Piatok| | | SJ,Zelen| | | ----------------------------------------------------------------------- | Sobota| | | | | | ----------------------------------------------------------------------- | Nedela| | | | | | -----------------------------------------------------------------------

  36. #include <stdio.h> #include <string.h> #define N 6 /* pocet pismen v slove (5 znakov) */ #define ND 7 /* pocet dni */ #define NH 5 /* pocet hodin */ #define SUBOR "subor.txt" /* default nazov subora */ typedef enum { pondelok, utorok, streda, stvrtok, piatok, sobota, nedela }; typedef struct { char predmet[N]; char ucitel[N]; int cast; /* -1 volno, 0 zaciatok, 1 stred,koniec */ } HODINA; char *dni[] = {"Pondelok", "Utorok", "Streda", "Stvrtok", "Piatok", "Sobota", "Nedela"};

  37. void inicializuj(HODINA rozvrh[][NH]); int nacitaj(HODINA rozvrh[][NH], char subor[]); void vypis(HODINA rozvrh[][NH]); int main (int argc, char *argv[]) { HODINA rozvrh[ND][NH]; char subor[N]; if (argc == 2) strcpy(subor, argv[1]); else strcpy(subor, SUBOR); inicializuj(rozvrh); if (nacitaj(rozvrh, subor)) { return 1; } vypis(rozvrh); return 0; }

  38. void inicializuj(HODINA rozvrh[][NH]) { int i, j; for(i=0; i<ND; i++) for(j=0; j<NH; j++) rozvrh[i][j].cast = -1; }

  39. /* nacitanie rozvrhu zo subora */ int nacitaj(HODINA rozvrh[][NH], char subor[]) { int i, den, hodina, dlzka; FILE *f; if ((f = fopen(subor, "r")) == NULL) { printf("Nepodarilo sa otvorit subor %s.\n", subor); return 1; } while(!feof(f)) { fscanf(f, "%d %d", &den, &hodina); den--; hodina--; fscanf(f, "%s", rozvrh[den][hodina].predmet); if (strlen(rozvrh[den][hodina].predmet) > 5) rozvrh[den][hodina].predmet[5] = '\0'; /*5 zn.*/ fscanf(f, "%s", rozvrh[den][hodina].ucitel); if (strlen(rozvrh[den][hodina].ucitel) > 5) rozvrh[den][hodina].ucitel[5] = '\0'; /*5 zn.*/ fscanf(f, "%d", &dlzka); rozvrh[den][hodina].cast = 0; /*zaciatok vyuc. h.*/

  40. /* ak ma vyuc.hod. viac ako 1 hodinu, naplnia sa dalsie zaznamy */ if (dlzka > 1) { for (i=1; i<dlzka && hodina+i < NH; i++) { rozvrh[den][hodina+i] = rozvrh[den][hodina]; rozvrh[den][hodina+i].cast = 1; } } } if(fclose(f) == EOF) printf("Subor sa nepodarilo zatvorit.\n"); return 0; }

  41. void vypis(HODINA rozvrh[][NH]) { int i, j; printf("\nROZVRH\n\n"); for(i=0; i<ND; i++) { /* horna ciara + ciary oddelujuce dni */ for(j=0; j<NH*12+1+10; j++) putchar('-'); printf("\n|%9s", dni[i]); /* oznacenie dna */

  42. /* riadok */ for(j=0; j<NH; j++) { if (j == 0 || rozvrh[i][j].cast < 1) putchar('|'); /* ciara pred vyuc. hod. */ else putchar(' '); /* vo vnutri v.h. ' ' */ if (rozvrh[i][j].cast == 0) /* vypis udajov */ printf("%5s,%5s", rozvrh[i][j].predmet, rozvrh[i][j].ucitel); else printf(" "); /* medzery */ if (j == NH-1) putchar('|'); /* koniec dna */ } putchar('\n'); /* prechod na dalsi riadok-den */ } /* dolna ciara */ for(j=0; j<NH*12+1+10; j++) putchar('-'); printf("\n"); }

  43. Binárne operácie #include <stdio.h> int main(){ printf("1 << 1 = %d\t%x\n", 1 << 1, 1 << 1); printf("1 << 7 = %d\t%x\n", 1 << 7, 1 << 7); printf("1024 >> 9 = %d\t%x\n",1024 >> 9,1024 >>9); printf("13 & 6 = %d\t%x\n", 13 & 6, 13 & 6); printf("13 | 6 = %d\t%x\n", 13 | 6, 13 | 6); printf("13 ^ 6 = %d\t%x\n", 13 ^ 6, 13 ^ 6); printf("2 & 1 = %d\t%x\n", 2 & 1, 2 & 1); printf("2 | 1 = %d\t%x\n", 2 | 1, 2 | 1); printf("2 ^ 1 = %d\t%x\n", 2 ^ 1, 2 ^ 1); return 0; } 128 = 27 1024 = 210 13: 1101 6: 110 1: 01 2: 10 1 << 1 = 2 0x2 1 << 7 = 128 0x80 1024 >> 9 = 2 0x2 13 & 6 = 4 0x4 13 | 6 = 15 0xf 13 ^ 6 = 11 0xb 2 & 1 = 0 0 2 | 1 = 3 0x3 2 ^ 1 = 3 0x3

  44. Binárne operácie vytvoricislo s 1 napozíciii, ostatnesu 0 #include <stdio.h> #define vytvorit_cislo(i) (1<<(i)) #define rad(x,i) (((x)>>(i))&1) unsigned invert(unsigned x,int i, int n){ unsigned j; for (j=i;j<i+n;j++){ if (rad(x,j)==0) x=x|(vytvorit_cislo(j)); else x=x&(~(vytvorit_cislo(j))); } return x; } void vypis(unsigned x){ if (x>0) { vypis(x>>1); printf("%d",x&1); } } vraticislicui-tehoraducislax Rekurzívny výpis

  45. Vyhľadávanie v usporiadanom poli program načíta do poľa usporiadanú postupnosť čísel a hodontu, ktorú chce v postupnosti (v poli) vyhľadať (nájsť jej index): použije sekvenčné a binárne vyhľadávanie

  46. Sekvenčné vyhľadávanie • najjednoduchšie vyhľadávanie: • od začiatku poľa postupne zväčšuje index pokým nepríde na hodnotu, korá je väčšia alebo rovná alebo pokým nepríde na koniec poľa • neefektívne

  47. Sekvenčné vyhľadávanie int sekvencne(int pole[], int n, int x) { int i=0; while(i < n && pole[i] < x) i++; if(pole[i] == x) return i; return -1; }

  48. 0 1 2 3 4 5 6 7 8 9 10 11 12345 6 7 8 9 10 11 12 Binárne vyhľadávanie • nájdenie stredu intervalu - ak je hľadaná hodnota menšia ako hodnota stredného prvku  hľadanie v ľavej polovici, inak v pravej polovici hľadáme pozíciu hodnoty 7

  49. int binarne(int pole[], int n, int x) { int m, l = 0, r = n-1; while (l <= r) { m = (l + r) / 2; if (x == pole[m]) return m; if (x < pole[m]) r = m - 1; else l = m + 1; } if (pole[m] == x) return m; else return -1; }

  50. #include <stdio.h> #include <stdlib.h> int sekvencne(int pole[], int n, int x); int binarne(int pole[], int n, int x); int main() { int p[100], i, n, x, vysl; char c; printf("Zadaj pocet prvkov pola (<100): "); scanf("%d", &n); if (n >= 100) { printf("Prilis velky pocet prvkov...\n"); return 1; } for (i=0; i<n; i++) { printf("p[%d]: ", i); scanf("%d", &p[i]); }

More Related