Info |
---|
Ciele cvičeniaCvičenie je zamerané na prácu so smerníkmi, ktoré sú v programovaní C veľmi silným a užitočným nástrojom. Po osvojení si problematiky študent dokáže efektívne adresovať údaje v pamäti. Rozlišuje medzi adresou premennej a jej obsahom.
|
Info |
---|
Odporúčaná literatúra a dôležité odkazy[1] KPI-FEI-TUKE: Prednáška č. 1 [2] KPI-FEI-TUKE: Cvičenie č. 2 - *Pointers [3] Horovčák P.: Úvod do programovania v jazyku C- Smerníky |
NULL vs 0 vs VOID
V jazyku C void znamená absenciu dátového typu, poznáme to napríklad z funkcii bez návratovej hodnoty. Aj smerníky môžu byť typu void a taký smerník môže obsahovať adresu premennej ľubovoľného typu. Môžeme ho použiť vtedy ak do neho počas behu programu, v rôznom čase, potrebujeme uložiť referenciu na rôzne údajové typy. Napr. najprv int a niekedy neskôr zasa char... Smerník typu void má v jazyku C svoj význam, ale pre bežné potreby ho používať nebudeme.
Smerník, ktorý obsahuje hodnotu NULL neukazuje nikam do pamäte. Občas budete tento smerník používať a overovať ako návratovú hodnotu funkcie. Napríklad vtedy ak sa nepodarí otvoriť súbor pre zápis alebo čítanie. V takom prípade vhodným testom predídeme chybe programu. Tiež je možné smerník inicializovať hodnotou NULL, teda vytvorená premenná je definovaná, ale neukazuje nikam do pamäte.
Pri smerníkoch je možné inicializovať aj hodnotou 0 to sa tiež považuje za NULL. Je potrebné mať na pamäti, že pri normálnej premennej napr. int 0 znamená hodnotu 0. Pre lepšiu predstavu si to môžete zapamätať pomocou obr. vpravo.
Ak hodnotu premennej alebo smerníka nedefinujeme (napr. int a), nevieme čo sa v nej nachádza alebo kam smerník ukazuje. Je to náhodná hodnota, ktorá sa v daný moment na danom pamäťovom mieste nachádzala. Na toto je potrebné dávať pozor!
Smerník ako argument funkcie
Na ZAP sme sa naučili, že výsledok vykonania ľubovoľnej funkcie môže byť vrátený pomocou jej návratovej hodnoty. K tomuto účelu slúži príkaz retrun, ktorý je spravidla posledným príkazom vykonaným volanou funkciou. Mnoho funkcií ale je typu void, teda bez návratovej hodnoty a stále dokážu "vrátiť" výsledok, napr. tak ako už spomínaná funkcia scanf.
Funkciu bez návratovej hodnoty, ktorej výsledky potrebujeme ďalej používať musí teda pracovať s premennými v pamäti presne tam, kde ich používa aj funkcia (napr. main), ktorá danú funkciu zavolala. Toto zabezpečíme tak, že vstupnými argumentom funkcie bude priamo adresa premennej, do ktorej sa má výsledok uložiť.
V nasledujúcom príklade si ukážeme jednoduchú funkciu, ktorá vynásobí číslo, ktoré jej bude zaslané hodnotou "-1". Teda v prípade kladného čísla dostaneme číslo záporné a naopak v prípade záporného čísla zasa vo výsledku dostaneme číslo kladné. Takúto funkciu si ukážeme v dvoch prevedeniach - s návratovou hodnotou a bez nej.
Funkcia invertovania s návratovou hodnotou
Code Block | ||
---|---|---|
| ||
#include <stdio.h> int invert(int cislo); // funkcia s návratovou hodnotou int a vstup. argumentom int int main() { int a = 5; int b = invert(a); // Do b je uložená návratová hodnota funkcie. printf(" >> b = -1 x a = -1 x %d = %d\n", a, b); return 0; } int invert(int cislo) { return -1*cislo; } |
Funkcia invertovania bez návratovej hodnoty (s použitím smerníka)
Code Block | ||
---|---|---|
| ||
#include <stdio.h> void invert(int* cislo); // funkcia bez návratovej hodnoty a // so vstup. argumentom smerník na int int main() { int a = 5; int b = a; // Do b je skopíprovanáskopírovaná hodnota z premennej a invert(&b); // Funkcii invert sa pošle iba adresa premennej b printf(" >> b = -1 x a = -1 x %d = %d\n", a, b); return 0; } void invert(int* cislo) { *cislo = *cislo * (-1); // Cez * pred premenou cislo sa dostaneme na obsah, // ktorý sa nachádza na adrese, ktorú funkcia dostala. } |
V oboch prípadoch bude po spustení programu výsledok rovnaký:
Code Block | ||
---|---|---|
| ||
ab123cd@zapfei:CV1$ gcc invert.c -o INV ab123cd@zapfei:CV1$ ./INV >> b = -1 x a = -1 x 5 = -5 |
Úloha 1.
Napíšte program (aritmetika.c) pre výpočet základných aritmetických operácií "+", "-", "*" a "/"
- Operácia bude zadaná ako argument príkazového riadku! Zopakovať si [6].
- Vstupné čísla a, b budú vyžiadané od používateľa programom. (printf → scanf)
- Všetky funkcie okrem main budú typu void.
- Kostra kódu je zobrazená v bloku vpravo.
- Odporúčaný postup je taký, že
- najprv si sfunkčnite funkcie,
- potom si spravíte zadávanie čísel,
- nakoniec vyriešite zadávanie operácie z príkazového riadku!
- Odporúčaný postup je taký, že
- Úloha je postavená tak, že musíte doplniť kostru a nesmiete nič čo je v nej uvedené zmeniť alebo vymazať!
Code Block | ||
---|---|---|
| ||
ab123cd@zapfei:CV1$ gcc aritmetika.c -o ARITMETIKA ab123cd@zapfei:CV1$ ./ARITMETIKA + >> Zadaj čslo a = 5 >> Zadaj čislo b = 3 >> c = a + b = 5 + 3 = 8 |
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <string.h> // Tu sú deklarácie funkcii void sucet(int* cislo1, int* cislo2, int* ans); void rozdiel(int* cislo1, int* cislo2, int* ans); void sucin(int* cislo1, int* cislo2, int* ans); void podiel(int* cislo1, int* cislo2, int* ans); int main(int argc, char *argv[]) { // Nezabudnúť na overenie toho či používateľ zadal správny počet argumentov // Nezabudnuť na deklarácie premenných // Tu bude kód pre zadávanie hodnoty vstupných premenných if( strcmp(argv[1],"+") == 0 ) { sucet(&a, &b, &c); printf("\n >> c = a + b = %d + %d = %d\n", a,b,c); } // ... tu budú ďalšie možnosti return 0; } // Tu by mali byť definície funkcií |
Úloha 2.
Vytvorte vlastnú funkciu pre porovnávanie dvoch reťazcov.
- Reťazce budú funkcii odovzdané cez smerník (teda adresa ako to je v príklade vyššie).
- Funkcia vráti hodnotu 1 ak budú reťazce zhodné a hodnotu 0 v opačnom prípade.
- Funkcia bude mať názov StrCmp.
- Kostra programu je vpravo.
- Okrem stdio.h sa zakazuje použitie iných .h súborov
Úloha 3.
Vypracujte úlohu 2 (2.1 - 2.3) z oficiálnej stránky predmetu [2]. Môžete si tiež zopakovať prácu s nástrojom cgdb.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> void StrCmp(char*, char*); int main() { char Retazec1[10], Retazec2[10]; // tu bude rutina pre zadávanie vstupných reťazcov printf("\n>> Vstupny retazec --> %s\n",Retazec); int ans = StrCmp(Retazec1,Retazec2) // tu bude vyhodnotenie a opoznamenia použivateľa o výsledku } // Tu by mala byť definícia funkcie |