1 / 75

Procedur álne programovanie: 6 . prednáška

Procedur álne programovanie: 6 . prednáška. Gabriela Kosková. Obsah. príklady (defin ície + 1 príklad) jednorozmern é polia príklady (3) re ťazce. Procedur álne programovanie: Pr ác a s ukazovateľmi - príklad y. Pr íklady definícií. typu int. - x je. int x;. typ int.

Download Presentation

Procedur álne programovanie: 6 . 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:6. prednáška Gabriela Kosková

  2. Obsah • príklady (definície + 1 príklad) • jednorozmerné polia • príklady (3) • reťazce

  3. Procedurálne programovanie:Práca s ukazovateľmi - príklady

  4. Príklady definícií typu int -x je int x; typ int ukazovateľ na -y je int *y; ukazovateľ na int int *z(); funkcia vracajúca -z je funkciu vracajúcu ukazovateľ na int -v je int (*v)(); ukazovateľ na funkciu vracajúcu -w je int *(*w)(); ukazovateľ na int

  5. Príklad program načíta celé číslo n a alokuje blok pamäte pre n celých čísel. Od používateľa čísla načíta. Nakoniec vypočíta ich priemer.

  6. #include <stdio.h> #include <stdlib.h> int *alokuj(int pocet); void nacitaj(int *pole, int pocet); float priemer(int *pole, int pocet); void vypis(int *pole, int pocet); int main() { int *pole, n; printf("Zadajte pocet cisel: "); scanf("%d", &n); if ((pole = alokuj(n)) == NULL) { printf("Nepodarilo sa alokovat pole.\n"); return 1; } nacitaj(pole, n); printf("Priemer cisel: \n"); vypis(pole, n); printf("je %.3f.\n", priemer(pole, n)); free(pole); return 0; }

  7. int *alokuj(int pocet) { return (int *) malloc(pocet * sizeof(int)); } void nacitaj(int *pole, int pocet) { int i; for(i = 0; i < pocet; i++) { printf("%d-te cislo: ", i); scanf("%d", pole + i); } } float priemer(int *pole, int pocet) { int i, suma = 0; for(i = 0; i < pocet; i++) suma += *(pole + i); return (float) suma / (float) pocet; }

  8. void vypis(int *pole, int pocet) { int i; for(i = 0; i < pocet; i++) printf("%d, ", *(pole + i)); }

  9. Procedurálne programovanie: Jednorozmerné polia

  10. N: 3 TYP: int index: 5 0 6 1 7 2 Základy práce s poliami • pole je štruktúra zložená z niekoľkých prvkov rovnakého typu (blok prvkov) statická definícia poľa TYP x[N]; • pole obsahuje N prvkov • dolná hranica je vždy 0 •  horná hranica je N-1 • číslo N musí byť známe v čase prekladu • hodnoty nie sú inicializované na 0

  11. Príklady definícií statického poľa #define N 10 int x[N], y[N+1], z[N*2]; x má prvkov poľa, od indexu po index y má prvkov poľa, od indexu po index z má prvkov poľa, od indexu po index 10 0 9 11 0 10 0 20 19

  12. priradenie hodnoty do prvého prvku poľa v cykle priradenie hodnoty postupne všetkým prvkom poľa x[0] = 1; for (i = 0; i < N; i++) x[i] = i+1; výpis prvkov poľa for (i = 0; i < N; i++) pritnf("x[%d]: %d\n", i, x[i]); Prístup k prvkom poľa #define N 10 ... int x[N], i;

  13. pokračovanie Príklad statického poľa: histogram písmen v reťazci #include <stdio.h> #include <stdlib.h> #define N ('Z' - 'A' + 1) int main() { int i; char hist[N], slovo[100]; scanf("%s", slovo); /* nacitanie slova */ for (i = 0; i < N; i++) /* inicializacia hist */ hist[i] = 0; i = 0; /* naplnenie hist */ while (i < 100 && slovo[i] != '\0') { hist[toupper(slovo[i]) - 'A']++; i++; }

  14. Príklad statického poľa: histogram písmen v reťazci pokračovanie: for(i = 0; i < N; i++) /* vypis hist */ if(hist[i] != 0) printf("%c: %d\n", i+'A', hist[i]); return 0; }

  15. Inicializácia poľa v definícii ... int x[3] = { 1, 2, 3 }; int y[] = { 1, 2, 3 }; int z[5] = {1, 2, 3 }; ... int n = 5; int z[n]; Počet prvkov poľa je daný počtom hodnôt Hodnoty z[3] a z[4] sú inicializované na 0. Nie je povolené, keďže n je premenná a nie číslo alebo konštanta (t.j. hodnota nemusí byť známa v čase prekladu)

  16. Polia a ukazovatele • adresa i-teho prvku poľa x: &x[i] = bázová adresa x + i * sizeof(typ) • x je adresa v pamäti • platí: x + i == &x[i] *(x + i) == x[i]

  17. Polia a ukazovatele • platí: • p[0] == *p • p[1] == *(p + 1) • p[2] == *(p + 2) • p[3] == *(p + 3) int *p; p = (int *) malloc(4 * sizeof(int)); Rozdiel medzi statickými a dynamickými poliami je najmä v spôsobe prideľovania pamäte.

  18. Polia a ukazovatele • platí: • &x[0] == &*(x + 0) == x • &x[i] == &*(x + i) == (x + i) int x[4]; x je statický ukazovateľ, nemôžeme spraviťx = p_i; môžeme ale urobiť *x = 2; (to isté ako x[0] = 2;)

  19. i = 0; /* naplnenie pola */ while (i < N && (*(slovo +i) != '\0') { hist[toupper(*(slovo +i)) - 'A']++; i++; } Príkladprístupu k prvkom poľa pomocou ukazovateľa Prepísanie nasledujúcej časti programu tak, aby sa k poľu slovo pristupovalo prostredníctvom ukazovateľov. i = 0; /* naplnenie pola */ while (i < N && (slovo[i] != '\0'){ hist[toupper(slovo[i]) - 'A']++; i++; }

  20. Zistenie veľkosti poľa • po alokovaní pamäte pre p_x budú x aj p_x ukazovatele na pole 10 prvkov typu int, s rozdielom, že: • x je statický ukazovateľ • p_x je dynamický ukazovateľ • preto dáva sizeof() iné výsledky: sizeof(x) == 10 * sizeof(int) (napr. 20) sizeof(p_x) == sizeof(int *) (napr. 4) int x[10], *p_x; p_x = (int *) malloc (10 * sizeof(int));

  21. Pole meniace svoju veľkosť alokovanie poľa x int *x, n = 5, *p1, *p2, *p; x = (int *) malloc(n * sizeof(int)); x[0] = 10; x[4] = 3; ... /* potreba zvacsit pole*/ p = (int *) malloc (10 * n * sizof(int)); p1 = x; p2 = p; while(p1 < x + n) *p2++ = *p1++; n *= 10; free(x); x = p; alokovanie poľa p kopírovanie obsahu poľa uvoľnenie menšieho poľa x nastavenie x na p

  22. Pole meniace svoju veľkosť - pomocou realloc() • funkcia void *realloc(void *pole, unsigned int size) definovaná v stdlib.h • pole - ukazovateľ na pamäť • size - veľkosť • zväčší pole, alebo vytvorí nové a prekopíruje tam hodnoty z pôvodného poľa x = realloc(x, 10 * n * sizeof(int));

  23. vráti maximum z prvkov poľa pole Pole ako parameter funkcie • identifikátor nasledovaný zátvorkami: int pole[] int maximum(int pole[], int n) { int *p_max = pole, *p; for (p = pole + 1; p < pole + n; p++) { if (*p > *p_max) p_max = p; } return (*p_max); } nepozná veľkosť poľa, preto ju treba uviesť

  24. parameter sa dá vo funkcii meniť (lebo sa vytvorila jeho lokálna kópia (nezáleží na tom, či ide o statické alebo dynamické pole) Pole ako parameter funkcie: veľkosť poľa • vo funkcii sa nedá zistiť veľkosť poľa aj keď: int maximum(int pole[], int n) int maximum(int pole[10]) • parameter bude stále považovaný za pole[]

  25. Volanie funkcie s poľom ako parametrom: max = maximum(pole, 10); Pole ako parameter funkcie int *pole je ekvivalentné int pole[] Pri použití int pole[] je jasnejšie, že ide o pole a nie o ukazovateľ na int.

  26. int maximum(int *pole, int n) {...} int x[10]; max = maximum(x + 2, 5); int x[10]; max = maximum(&x[2], 5); Pole ako parameter funkcie • dá sa použiť aj na zistenie maxima napr. na zistenie maxima 3. až 7. prvku int maximum(int pole[], int n) {...}

  27. Pole ako parameter funkcie • prepísanie funkcie maximum()na procedúru void maximum(int pole[], int n, int *p_max) { int *p; *p_max = pole[0]; for (p = pole + 1; p < pole + n; p++) { if (*p > *p_max) *p_max = *p; } } ak by sme dali p_max = p; stratili by sme ukazovateľ na premennú, kam treba vrátiť maximum

  28. void main() { double *p_d; init(&p_d); } Pole ako parameter funkcie: vytváranie poľa vo funkcii void init(double **p_f) { double a[5]; int i; for(i = 0; i < 5; i++) { printf("Zadaj %d. cislo"); scanf("%lf", &a[i]); } *p_f = a; } double *a; int i; a = (double *) malloc(5 * sizeof(double); p_d bude ukazovať na pole 5 double prvkov, ale a bolo vyrobené v zásobníku, a tento zásobník sa pri ukončovaní funkcie zruší

  29. Pole ukazovateľov na funkcie • prvkami poľa môžu byť aj ukazovatele • na prvky  viacrozmerné polia • na funkcie (všetky funkcie musia byť toho istého typu) definícia ukazovateľa na funkciu vracajúcu typ void typedef void (* P_FNC)(); P_FNC funkcie[10]; pole 10 ukazovateľov

  30. funkcia[1](); Pole ukazovateľov na funkcie • pole ukazovateľov na funkcie pri riadení programu pomocou menu typedef void (* P_FNC)(); P_FNC funkcie[5] = {file, edit, search, compile, run}; ... • volanie funkcie:

  31. Ako čítať zložitejšie definície 2 • do čítania definícií treba začleniť polia • definície sa čítajú rovnako, len treba brať do úvahyaj []

  32. Príkady zložitejších definícií -f je pole ukazovateľov na funkcie vracajúce typ double double(*f[])(); -f je funkcia vracajúca ukazovateľ na pole prvkov typu double double(*f())[]; -f je polefunkcií vracajúce ukazovateľ na typ double double*(f[])(); -f je funkcia vracajúca pole ukazovateľov na typu double double*f()[];

  33. pole prvkov typu Ako čítať zložitejšie definície 2 • Nájdeme identifikátor - f je funkcia vracajúca double (* f())[]; (* f())[]; (* f()) (* f())[] f() f()) f double (* f())[]; ukazovateľ na double a hľadáme ) doprava • Nájdeme () a pokračujeme doprava • Nájdeme ) a k nej zodpovedajúcu ( a pokračujeme doprava • Nájdeme [] , pokračujeme doprava po ; , doľava • Nájdeme double

  34. Procedurálne programovanie:Príklady

  35. Príklad 1 Program vytvorí histogram výskytov písmen v súbore (pre každé písmeno - počet jeho výskytov)

  36. pokračovanie #include<stdio.h> #include<stdlib.h> #define SUBOR "pismena.txt" #define N 'Z' - 'A' + 1 int main() { int c, i, hist[N]; FILE *fr; if((fr = fopen(SUBOR, "r")) == NULL) { printf("Subor sa nepodarilo otvorit.\n"); return 1; } for (i=0; i<N; i++) hist[i] = 0; while ((c = toupper(getc(fr))) != EOF) { if(c >= 'A' && c <= 'Z') hist[c - 'A']++; }

  37. Príklad1 pokračovanie: for (i=0; i<N; i++) if (hist[i] != 0) printf("%c: %2d\n", 'A' + i, hist[i]); if(fclose(fr) == EOF) { printf("Subor sa nepodarilo zatvorit.\n"); return 1; } return 0; }

  38. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Príklad 2: Eratostenovo sito • algoritmus na nájdenie prvočísel v poli • vyškrtáva všetky násobky prvočísel, počnúc 2 (vyškrtnutie  prepísanie čísla na 0) 0 0 0 0 0 0 0 0 0 i: prv[i]: 2 1 0 2 3 0 v cykle, i od 0 do 2 poľa prv: v cykle, k od i+1 do 14: vyškrtneme všetky násobky čísla prv[i]

  39. pokračovanie Príklad 2: Eratostenovo sito #include <stdio.h> #include <stdlib.h> #include <math.h> void main() { int n, i, k, odm; int *prv; printf("Do ktoreho cisla hladat prvocisla? "); scanf("%d", &n); n--; /* znizime n o 1, nevyskrtavame nasobky jednotky */ prv = (int *) malloc(n * sizeof(int)); for(i = 0; i < n; i++) /* inicializacia */ prv[i] = i+2;

  40. pokračovanie: odm = (int) sqrt(n)-1; printf("odmocnina: %d\n", o); for(i = 0; i < odm; i++) { if(prv[i] != 0) { /* ak sme predtym cislo nevyskrtli */ for(k = i+1; k < n; k++) { /* vyskrtni vsetky nasobky */ if(prv[k] != 0) { /* ak este nie je vyskrtnute */ if(prv[k] % prv[i] == 0) /* ak je delitelne */ prv[k] = 0; } } } } printf("Prvocisla: "); /* vypisanie prvocisel */ for(i = 0; i < n; i++) if(prv[i] != 0) printf("%d, ", prv[i]); putchar('\n'); return 0; }

  41. Príklad 3 program na rýchle kopírovanie bloku pamäte z miesta, kam ukazuje p1 na miesto, kam ukazuje p2. Treba použiť pomocný ukazovasteľ p ... for (p = p1; p < p1 + N; *p2++ = *p++) ;

  42. Procedurálne programovanie:Reťazce

  43. Čo sú to reťazce • reťazce sú jednorozmerné polia typu char • dĺžka reťazca: ľubovoľná, obmedzená veľkosťou pamäte • z celkovej pamäte je aktívna len časť od začiatku poľa do znaku '\0' ukončovací znak • ak nie je reťazec ukončený znakom '\0', považuje sa za reťazec celá pamäť až do najbližšieho znaku '\0'

  44. char s[] = "abrakadabra"; char *s; s = (char *) malloc(6); Definícia a inicializácia reťazca • reťazec s najviac 6 znakmi: • staticky: • dynamicky: char s[6]; = "ahoj"; a s: 0 h 1 o 2 inicializuje sa miesta práve pre daný text j 3 \0 4 5

  45. Definícia a inicializácia reťazca pridá na koniec '\0' char s[15] = "abrakadabra"; v C nie je možné takto priradiť statickému reťazcu konštantu char s[10]; s = "ahoj"; tu s nepredstavuje dynamický reťazec, ale ukazovateľ na typ char a je inicializovaný adresou konštanty (pre ktorú je vyhradené miesto) char *s= "ahoj";

  46. Inicializácia dynamického reťazca? • dynamicky vytvorený reťazec sa nedá inicializovať! alokovanie 10 znakov do s char *s; s = (char *) malloc(10); s = "ahoj"; char c; int i=0; while ((c=getchar()) != '\n' && i < 9) s[i++] = c; s[i] = '\0'; načítanie aj pomocou scanf

  47. Poznámky k definícii a inicializácii reťazcov • definícia typu pre reťazce • treba rozlišovať: • nulový ukazovateľ NULL a nulový reťazec '\0': • nulový ukazovateľ neukazuje na žiadne miesto v pamäti, • nulový reťazec má v 0-tom prvku znak '\0' • "x" a 'x': • "x" je reťazec s jedným znakom ukončený '\0' (2 Byty) • 'x' je jeden znak (1 Byte) typedef char *STRING;

  48. Čítanie reťazca z klávesnice sem nepartrí &, pretože s je adresa • scanf() vynecháva biele znaky a číta po prvý biely znak • ak je na vstupe " ahoj Eva!", scanf() prečíta iba "ahoj" a zvyšok zostáva v bufferi klávesnice char s[10]; ... scanf("%s", s);

  49. Formátované čítanie: príklad Program vypočíta celkovú sumu peňazí zo súboru, kde jednotlivé sumy sú vždy uvedené znakom $ a znamienko + je pre príjem a - pre výdaj Príklad súboru: + $10 -$5- $8 +$20

  50. Formátované čítanie: príklad include <stdio.h> void main() { FILE *f; int kolko, suma = 0; char akcia[2]; f = fopen("peniaze.txt", "r"); while (fscanf(f, "%1s", akcia) != EOF) { fscanf(f, "$%d",&kolko); suma += (akcia[0] == '+') ? kolko : (-1*kolko); } printf("Spolu: %d\n", suma); fclose(f); } namiesto %1s nemôže byť %c, pretože by prečítal medzeru, nie prvý znak podobne $%d: $ zabezpečuje, že sa preskočia biele znaky

More Related