Jazyk C (príklady) - Polia

Z Kiwiki
Verzia z 11:19, 30. apríl 2020, ktorú vytvoril PatrikC (diskusia | príspevky)
(rozdiel) ← Staršia verzia | Aktuálna úprava (rozdiel) | Novšia verzia → (rozdiel)
Skočit na navigaci Skočit na vyhledávání


Základy informatiky - jazyk C


Riešené príklady

Algoritmy

Prvé programy

Podmienky

Cykly

Polia

Funkcie

Súbor

Vzorové príklady

Neriešené príklady


zdroj: Juraj Ďuďák, Zbierka úloh z algoritmizácie pre predmet Základy informatiky

ISBN: 978-80-8075-199-9

Obsah

V tejto časti budú ukázané príklady v ktorých je nutné použiť polia. Sú tu príklady pre 1 rozmerné polia (pole čísel, polynóm, textový reťazec), 2 rozmerné polia (matice) a 3 rozmerné polia (kocka). Pre zvládnutie týchto príkladov sa predpokladá, že študent zvláda základy práce s n-rozmerným poľom v jazyku C.

n-rozmerné polia

Jazyk C nám dovoľuje definovať n-rozmerné polia. Definícia poľa môže vyzerať nasledovne:

1 rozmerné pole celých čísel: int pole1[100]; 1 rozmerné znakové pole: char text[100]; 2 rozmerné pole reálnych čísel: float pole2[100][100]; 3 rozmerné pole celých čísel: int pole3[100][100][100]; Vo všetkých prípadoch bola zvolená max. veľkosť jedného rozmeru 100.

Pravidlá pre prácu s poľami:

Pole sa indexuje vždy od 0. Polia sa nedajú porovnávať, ani priraďovať navzájom. Ale dajú sa porovnávať a priraďovať prvky poľa. S poľom ako celkom sa nedajú robiť žiadne operácie. Tieto operácie sa musia robiť s jednotlivými prvkami poľa. Pri definícii float pole2[100][100]: pole2 je 2 rozmerné pole pole2[i] je jednorozmerné pole; je to i-ty riadok matice pole2 pole2[i][j] je jeden prvok poľa (i-ty riadok a j-ty stĺpec) typu float

Priklady

Výpis čísel odzadu

Zadanie
Úlohou je načítať n čísel po sebe, a následne ich vypísať v opačnom poradí. Teda začne sa posledným načítaným, a ako posledné číslo sa vypíše prvé načítané. V programe najskôr načítajte informáciu o počte načítavaných čísel (n) a potom tieto čísla načítajte.
Analýza problému
Keďže dopredu nikdy nevieme koľko čísel budeme načítavať, (a teda nemôžeme si dopredu definovať určitý počet jednoduchých premenných) musíme použiť pole, do ktorého tieto údaje budeme ukladať. Pre pole si zvolíme maximálny rozmer 100 (predpokladáme, že nikdy nebudeme načítavať viac ako 100 čísel). Ako prvé načítame n – údaj hovoriaci o počte načítavaných čísel. Ďalej je našou úlohou načítať ďalších n čísel. Tieto čísla budeme ukladať do poľa. Keďže sa nedajú robiť operácie s celým poľom naraz, ale iba z jednou bunkou poľa, musíme vždy špecifikovať, s ktorou bunkou budeme pracovať. Údaje do poľa máme ukladať postupne (t.j. 1 číslo uložíme do bunky s indexom 0, 2 číslo do bunky s indexom 1, atď.). Na určenie indexu poľa, s ktorým aktuálne pracujeme nám pomôže cyklus.

Pri výpise prvkov použijeme tiež cyklus, avšak indexy poľa musia ísť od najväčšieho (n-1) po najmenší (0).

Program
 1 #include<stdio.h>
 2 void main()
 3 {
 4 
 5     int n,i,pole[100];
 6     printf(Zadaj pocet cisel, ktore sa budu nacitavat\n);
 7     scanf(%d,&n);
 8     for(i=0 ; i<n ; i++)
 9         scanf(%d,&pole[i]); // nacitavanie prvkov do pola
10 
11      for(i=n-1 ; i>=0 ; i--) // vypis prvkov odzadu
12          printf("%d “,pole[i]);
13 
14 }

Počet čísel väčších ako priemer

Zadanie
Vstupné dáta sú podobné ako v predchádzajúcom príklade. Teda prvé sa načíta n a následne n čísel, ktoré treba uložiť do poľa. Úlohou bude vypočítať priemer týchto prvkov a ďalej spočítať koľko je takých prvkov, ktoré sú väčšie ako priemer.
Analýza problému
Princíp načítavania prvkov do poľa je vysvetlený v predchádzajúcom príklade. Prvou úlohou je vypočítať priemer načítavaných čísel. Toto dokážeme aj bez použitia poľa. Stačí priamo pri načítavaní čísel tieto spočítať a na koniec ich vydeliť číslom n (ich počtom). Na druhú časť úlohy už pole potrebujeme. V tomto prípade musíme prehľadať celé pole (teda postupne prvok po prvku) a zistiť koľko je prvkov väčších ako aritmetický priemer. Ako bolo povedané, nedajú sa robiť operácie s celým poľom, ale iba s prvkami poľa. Preto musíme každý jeden prvok poľa porovnať či je väčší ako priemer. Ak áno, tak zvýšime počítadlo, ktoré nám bude spočítavať prvky väčšie ako je priemer.

Pre premennú suma bol zvolený typ float, aby pri delení suma/n vyšlo reálne číslo.

 1 #include<stdio.h>
 2 void main()
 3 { 
 4 
 5     int n,i,pole[100];
 6     float suma=0,priemer;
 7         printf(Zadaj pocet cisel, ktore sa budu nacitavat\n);
 8         scanf(%d,&n);
 9     for(i=0 ; i<n ; i++)
10     {    scanf(%d,&pole[i]);  // nacitavanie prvkov do pola
11          suma+=pole[i];
12     }
13 
14     priemer=suma/n;
15     int vacsi_ako_pr=0; // pocitadlo cisel vacsich ako priemer
16     for(i=0 ; i<n ; i++)
17     {    if(pole[i]>priemer)
18              vacsi_ako_pr++;
19     }
20     
21     printf(Pocet prvkov vacsich ako priemer je %d\n,vacsi_ako_pr);
22 
23 }

Hodnota polynómu

Zadanie
Majme polynóm v tvare: anxn+an-1xn-1+...+a1x1+a0x0. Úlohou je vypočítať hodnotu polynómu v dvoch rôznych bodoch. V programe najskôr načítajte rád polynómu n, a následne jednotlivé koeficienty (a0 až an). Posledné dva údaje budú x1 a x2, teda body, v ktorých je treba vypočítať hodnotu polynómu. Koeficienty a0 až an uvažujte celé čísla.
Analýza problému
Prvý údaj (n) nám hovorí o stupni polynómu, teda o počte koeficientov polynómu. Keďže polynóm má mať stupeň n, je potrebné načítať n+1 položiek (a0 až an) a nie len n položiek. Tieto položky budeme postupne ukladať do jednorozmerného poľa polynom. Na záver načítame ešte dve hodnoty x1 a x2 – body, v ktorých budeme rátať hodnotu polynómu. Dáta v poli polynom budú uložené tak, že polynom[i] predstavuje prvok koeficient a[i]. Na výpočet hodnoty xi použijeme funkciu (definovanú v knižnici math.h) pow(x,i).
Program
 1 #include<stdio.h>
 2 #include<math.h>
 3 void main()
 4 {
 5 
 6     int n,i,polynom[100],x1,x2;
 7     printf("Zadaj stupen polynomu\n");
 8     scanf("%d",&n);
 9     for(i=0 ; i<=n ; i++)
10     {    printf("\nZadaj koeficient a[%d]",i);
11          scanf("%d",&polynom[i]);  // nacitavanie prvkov do pola
12     }
13 
14     printf("Zadaj 2 body, v ktorych sa bude pocitat hodnota polynomu\n");
15     scanf("%d %d",&x1, &x2);  // body x1 a x2
16 
17  
18 
19     int hodnota1=0,hodnota2=0; // funkcne hodnoty polynomu v x1 a x2
20     for(i=0 ; i<=n ; i++)     // vypocet hodnoty polynomu v x1 a x2
21     {    hodnota1+= polynom[i]*pow(x1,i);  // ai*xi
22          hodnota2+= polynom[i]*pow(x2,i);
23     }
24     printf("Polynom ma v bode %d hodnotu %d\n",x1,hodnota1);
25     printf("Polynom ma v bode %d hodnotu %d\n",x2,hodnota2);
26 
27 }

Textové reťazce

Zadanie
Z klávesnice načítajte textový reťazec (max. 500 znakov). Reťazec je ukončený medzerou. Následne načítajte jeden znak. Zaujíma nás počet výskytov tohoto znaku v už načítanom texte. Výstup programu bude počet výskytov zvoleného znaku. Teda najskôr sa načíta textový reťazec text a následne zvolený znak c. Výsledok bude počet výskytov znaku c v reťazci text.
Analýza problému
Pre uloženie poľa si vytvoríme pole znakov text o veľkosti 501 (pretože posledný znak je ukončovacia nula). Ďalej budeme potrebovať zistiť skutočnú veľkosť načítaného textu. Na to nám poslúži funkcia strlen (je definovaná v knižnici string.h). Na obmedzenie 500 znakov pri načítavaní nám poslúži formát %500s, ktorý zoberie ako platné znaky len prvých 500 znakov. Ak chceme zistiť počet výskytov znaku v texte musíme tento znak porovnávať s každým znakom v poli text . Na spočítanie výskytov znaku v texte nám poslúži počítadlo pocet.
Program
 1 #include<stdio.h>
 2 #include<string.h>
 3 #define MAX 501
 4 
 5 void main()
 6 {
 7 
 8 
 9     char znak, retazec[MAX];
10     int dlzka,pocet=0,i;
11     printf("Zadaj textovy retazec a jeden znak\n");
12     scanf("%500s %c",retazec,&znak);
13     dlzka=strlen(retazec);
14 
15     for(i=0; i<dlzka; i++)
16     {
17         if(znak==retazec[i])
18             pocet++;
19     }
20     printf("V retazci %s sa znak %c vyskytuje %d krat",retazec,znak,pocet);
21 
22 }

Sčítanie 2 matíc

Zadanie
Pre uľahčenie počítania s maticami treba vytvoriť program, ktorý sčíta 2 matice. Program najskôr načíta rozmery matice: r a s. r je počet riadkov a s je počet stĺpcov matice. Následne sa načítajú 2 matice (A a B) s rozmermi r×s.
Analýza problému
Matice je najvýhodnejšie reprezentovať ako dvojrozmerné pole. Na rozdiel od jednorozmerného poľa, pri dvojrozmernom poli treba pre daný prvok matice špecifikovať index riadku a index stĺpca matice. Na toto nám poslúžia dva (vnorené) cykly, z ktorých jeden slúži na indexovanie riadku (vonkajší) a jeden na indexovanie stĺpca (vnútorný) matice. Samotné sčítavanie matíc je jednoduché, stačí sčítať prislúchajúce prvky matice. V programe budeme potrebovať 3 matice: A, B, C (C=A+B). Zvolíme pre ne maximálny rozmer 100 (teda musí platiť, že r,s<100 ).
Program
 1 #include<stdio.h>
 2 #define MAX 100
 3 
 4 void main()
 5 {
 6 
 7 
 8     int A[MAX][MAX], B[MAX][MAX], C[MAX][MAX];
 9     int r,s,i,j;
10     printf("Zadaj rozmery matice (r,s)\n");
11     scanf("%d %d",&r,&s);
12     for(i=0; i<r; i++) // nacitavanie matice A
13         for(j=0; j<s; j++)
14         {  
15             printf(“\nZadaj prvok A[%d][%d],i,j);
16             scanf(%d,&A[i][j]); // nacitavanie prvku Ai,j
17        }
18 
19     for(i=0; i<r; i++) // nacitavanie matice B
20        for(j=0; j<s; j++)
21        {  
22             printf(“\nZadaj prvok B[%d][%d],i,j);
23             scanf(%d,&B[i][j]); // nacitavanie prvku Bi,j
24        }
25 
26      // C=A+B
27      for(i=0; i<r; i++)
28          for(j=0; j<s; j++)
29               C[i][j]= A[i][j]+ B[i][j];
30 
31      for(i=0; i<r; i++) // Vypis matice C
32      {  
33           for(j=0; j<s; j++)
34              printf(%5d,C[i][j]);
35           printf(“\n);
36       }
37 
38 }

Násobenie 2 matíc

Zadanie
Rozšírme našu maticovú kalkulačku o funkciu násobenia matíc. Program načíta 2 matice A(r1×s1),B(r2×s2) a vypočíta C=A*B. Maticu C potom vypíše na monitor.
Analýza problému
Pri násobení matíc, treba najskôr skontrolovať, či sa dajú matice násobiť. Dve matice sa dajú násobiť ako počet stĺpcov prvej matice (s1) je rovný počtu riadkov druhej matice (r2). Výsledná matica má rozmery r1×s2. Problematika načítania matíc a princípu práce s nimi je vysvetlená v predchádzajúcom príklade. Problém násobenia matíc je trochu zložitejší ako Matica A má rozmery 2×3, matica B rozmery 3×4. Výsledná matica C bude mať rozmery 2×4. Pri výpočte jedného prvku matice C, treba vynásobiť vždy jeden riadok z matice A s jedným stĺpcom matice B - podľa vzťahu M.1. Pre C[0][2] platí : C[0][2]=A[0][0]*B[0][2]+ A[0][1]*B[1][2]+ A[0][2]*B[2][2] Takýto (podobný) vzorec platí pre každú bunku matice C. Ak si všimneme na pravej strane toho výrazu, tak index stĺpca matice A je vždy zhodný s indexom riadku matice B. Index riadku matice A je zhodný s indexom riadku matice C. Index stĺpca matice B je vždy zhodný s indexom stĺpca matice B. Pri samotnom výpočte C[i][j] si pomôžeme tretím cyklom, ktorý bude plniť úlohu zvyšujúceho sa indexu stĺpca A a riadku B.
Program
 1 #include<stdio.h>
 2 #define MAX 100
 3 void main()
 4 {
 5 
 6 
 7     int A[MAX][MAX], B[MAX][MAX], C[MAX][MAX];
 8     int r1,s1,r2,s2,i,j,k;
 9     printf("Zadaj rozmery matice A(r,s)\n");
10     scanf("%d %d",&r1,&s1);
11 
12     for(i=0; i<r1; i++) // nacitavanie matice A
13         for(j=0; j<s1; j++)
14         {  
15             printf(“\nZadaj prvok A[%d][%d],i,j);
16             scanf(%d,&A[i][j]); // nacitavanie prvku Ai,j
17         }
18 
19      printf("Zadaj rozmery matice B(r,s)\n");
20      scanf("%d %d",&r2,&s2);
21      for(i=0; i<r2; i++) // nacitavanie matice B
22          for(j=0; j<s2; j++)
23          {  
24              printf(“\nZadaj prvok B[%d][%d],i,j);
25              scanf(%d,&B[i][j]); // nacitavanie prvku Bi,j
26          }
27 
28      // C=A*B
29      for(i=0; i<r1; i++)
30      for(j=0; j<s2; j++)
31      {    C[i][j]=0;
32           for(k=0; k<s1; k++)
33               C[i][j]+= A[i][k]* B[k][j];
34      }
35 
36      for(i=0; i<r1; i++) // Vypis matice C
37      {  
38          for(j=0; j<s2; j++)
39          printf(%5d,C[i][j]);
40          printf(“\n);
41      }
42 
43 }

Počet nulových prvkov matice

Zadanie
Po načítaní rozmerov r×s máme určiť, koľko prvkov v matici má nulovú hodnotu. Vstup do programu bude r, s a matica A(r×s), výstup bude počet nulových prvkov matice A.
Analýza problému
Problém je jednoduchý, po načítaní matice A treba zistiť, koľko prvkov má hodnotu 0. To zistíme tak, že každý prvok matice budeme porovnávať s hodnotou 0.
Program
 1 #include<stdio.h>
 2 #define MAX 100
 3 
 4 void main()
 5 {
 6 
 7     int A[MAX][MAX];
 8     int r,s,i,j,pocet=0;
 9     printf("Zadaj rozmery matice (r,s)\n");
10     scanf("%d %d ",&r, &s);
11     for(i=0; i<r; i++) // nacitavanie matice A
12         for(j=0; j<s; j++)
13         {  
14             printf(“\nZadaj prvok A[%d][%d],i,j);
15             scanf(%d,&A[i][j]); // nacitavanie prvku Ai,j
16         }
17 
18     // zistujeme, kolko prvkov je nulovych
19     for(i=0; i<r; i++)
20         for(j=0; j<s; j++) 
21             if(A[i][j]==0) // ak je prvok nulovy
22             pocet++;  // zapocitaj ho
23 
24     printf(“\nV matici A je %d nulovych prvkov,pocet);
25 
26 }

Suma prvkov na vedľajšej diagonále

Zadanie
Vstup do programu bude štvorcová matica A. Teda prvý údaj načítaný do programu bude rozmer matice n a následne sa načíta matica A(n×n). Úlohou bude zistiť
  • Sumu prvkov na vedľajšej diagonále (suma_v)
  • Sumu prvkov na hlavnej diagonále (suma_h)
  • Sumu prvkov pod hlavnou diagonálou (suma_p)
  • Sumu prvkov nad hlavnou diagonálou (suma_n)
Analýza problému
Prácu s maticami sme zvládli v predchádzajúcich príkladoch. Teraz je úlohou pracovať len s niektorými prvkami matice. Jednotlivé prvky matice sa líšia (okrem svojej hodnoty) iba svojimi indexmi. Pomocou týchto indexov dokážeme povedať, kde sa prvok nachádza. Pre úlohy v zadaní platí že indexy prvkov v matici sú:
  • Prvky na vedlajšej diagonále : i + j = = n-1 (pretože prvky sa indexujú od 0)
  • Prvky na hlavnej diagonále : i = = j
  • Prvky pod hlavnou diagonálou: i > j
  • Prvky nad hlavnou diagonálou: i < j
Program
 1 #include<stdio.h>
 2 #define MAX 100
 3 void main()
 4 {
 5 
 6     int A[MAX][MAX];
 7     int n,i,j,suma_v=0, suma_h=0, suma_p=0, suma_n=0;
 8     printf("Zadaj rozmer matice (n)\n");
 9     scanf("%d",&n);
10     for(i=0; i<n; i++) // nacitavanie matice A
11         for(j=0; j<n; j++)
12         {  
13             printf(“\nZadaj prvok A[%d][%d],i,j);
14             scanf(%d,&A[i][j]); // nacitavanie prvku Ai,j
15         }
16 
17     for(i=0; i<n; i++) // vypocet jednotlivych sum
18         for(j=0; j<n; j++)
19         {
20           if(i+j == n-1 )
21                 suma_v+= A[i][j];
22           if(i==j)
23                 suma_h+= A[i][j];
24           if(i>j)
25                 suma_p+= A[i][j];
26           if(i<j)
27                 suma_n+= A[i][j];
28         }
29 
30     printf(“\nSuma prvkov na vedlajsej diagonale = %d,suma_v);
31     printf(“\nSuma prvkov na hlavnej diagonale = %d,suma_h);
32     printf(“\nSuma prvkov pod hlavnou diagonalou = %d,suma_p);
33     printf(“\nSuma prvkov nad hlavnou diagonalou = %d,suma_n);
34 }

Priemer hladín v kocke

Zadanie
Meracie stanovisko čistoty ovzdušia meralo znečistenie na oblasti n×n×n metrov. Meracia oblasť tvorí akúsi imaginárnu kocku. Meranie sa uskutočnilo v pravidelnej mriežke na tejto oblasti. Namerané údaje sú uložené v trojrozmernom poli, kde súradnice (indexy) poľa sú zhodné (v určitej mierke) so skutočnými súradnicami v teréne. Pre potreby analýzy tohto merania je úlohou vypočítať priemerné znečistenie ovzdušia v závislosti od výšky nameraných dát. V programe najskôr načítajte rozmery oblasti n a následne 3 rozmerné pole A(n×n×n). Namerané údaje sú v 3D kocke uložené od najnižšej vrstvy až po najvyššiu (od zemského povrchu) vrstvu.
Analýza problému
Našou úlohou je vypočítať aritmetický priemer jednotlivých rovín 3D kocky. Čiže jedná sa o výpočet priemeru n 2-rozmerných matíc. Význam jednotlivých indexov ilustruje nasledujúci obrázok.
Program
 1 #include<stdio.h>
 2 
 3 #define MAX 20
 4 void main()
 5 {
 6 
 7     int K[MAX][MAX][MAX];
 8     int n,i,j,k;
 9     float suma;
10     printf("Zadaj rozmer kocky (n)\n");
11     scanf("%d",&n);
12     for(i=0; i<n; i++) // nacitavanie matice A
13         for(j=0; j<n; j++)
14              for(k=0; k<n; k++)
15              {  
16                   printf(“\nZadaj prvok K[%d][%d][%d],i,j,k);
17                   scanf(%d,&K[i][j][k]); // nacitavanie prvku Ki,j,k
18              }
19 
20      // vypocet priemeru jednotlivych rovin
21     for(i=0; i<n; i++) //urcuje nam jednotlive roviny
22     {
23         suma=0;
24         for(j=0; j<n; j++)        //j a k su indexy
25             for(k=0; k<n; k++)   //2D matice, kde pocitame priemer
26                 suma+= K[i][j][k];
27         printf(Priemer %d. roviny = %.3f\n,i+1,suma/n);
28     }
29 
30 }