Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lekt. Tomas G. Lipnevičius

Similar presentations


Presentation on theme: "Lekt. Tomas G. Lipnevičius"— Presentation transcript:

1 Lekt. Tomas G. Lipnevičius
Programavimo ir IT pagrindai 6 paskaita Lekt. Tomas G. Lipnevičius

2 Programavimo pagrindai
Programavimas

3 Funkcijos //funkcija grazina rezultatą int input_integer(void); //prototipas void main() { int x, y, z; x = input_integer(); y = input_integer(); printf(“Dvieju skaiciu suma: %d\n", z=x+y); } int input_integer(void) int a; do printf(“Iveskite sveika skaiciu: "); scanf("%d", &a); } while (a <= 0); return a; }

4 Funkcijos //funkcija gauna parametra ir grazina rezultata void main() { int x, y, z=100; int funkcija(int n); //prototipas x = funkcija(z); y = funkcija(z); printf(“Skaiciu suma: %d\n", x+y); } int funkcija(int n) int a; do printf(“Iveskite sveika teigiama skaiciu mazesni nei %d: ", n); scanf("%d", &a); } while (a<=0 || a>n); return a; }

5 Funkcijos Norint naudoti funkcijas C kalboje reikia suvokti tris sąvokas: funkcijos apibrėžimas, funkcijos prototipas ir funkcijos kvietimas. Funkcijos apibrėžimas nurodo funkcijos pavadinimą, formaliųjų parametrų skaičių bei tipus, apibrėžimus ir operatorius, kurie nusako funkcijos veikimą. Tam tikra apibrėžimų ir operatorių seka yra vadinama funkcijos kūnu. Funkcijos apibrėžimui dar gali priklausyti rezultato, kurį įgauna funkcija, tipas ir atminties klasė. C kalboje nėra reikalavimo, kad funkcijos apibrėžimas eitų būtinai prieš funkcijos kvietimą, t.y. funkciją galima apibrėžti prieš ar po funkcijos main(), galima ją apibrėžti ir kitame faile. Norint, kad kompiliatorius galėtų atlikti tipų atitikimo patikrinimą perduodamų funkcijai parametrų (faktinių argumentų) su formaliais parametrais esančiai funkcijos apibrėžime, prieš funkcijos kvietimą turėtų būti bent funkcijos prototipas. Funkcijos prototipas turi tokį pat formatą kaip ir funkcijos apibrėžimas. Skirtumas tik tame, kad funkcijos prototipas arba aprašymas neturi kūno ir baigiasi kabliataškiu.

6 Funkcijos Funkcijos prototipas nusako funkcijos pavadinimą, formaliųjų parametrų skaičių ir jų tipus, gražinamo rezultato tipą ir atminties klasę. Formalieji parametrai gali turėti pavadinimus, bet jie kompiliatoriui nėra reikalingi, kadangi jis tikrintina tik tipų atitikimą. C kalbos standartinių bibliotekų funkcijų prototipai randasi atitinkamose antraščių (header) failuose.

7 Funkcijos apibrėžimas
Funkcijos apibrėžimas: [atminties klasė] [tipas] funkcijos_pavadinimas ([formaliųjų parametrų sąrašas]) { Funkcijos kūnas } Atminties klase gali būti: extern arba static Tipas: Čia nurodomas funkcijos rezultato tipas. Šiuo tipu gali būti bet kuris iš bazinių tipų, struktūros ar išvardijimas (enum). Jei tipas nenurodomas pagal nutylėjimą yra manoma, kad tai bus int tipas.

8 Funkcijos apibrėžimas
Funkcijos pavadinimas gali būti su simboliu *. Tai reiškia, kad funkcija grąžina rodyklę. Funkcijos negali grąžinti masyvų ar funkcijų, bet gali grąžinti rodyklę į bet kokį tipą įskaitant masyvus ir funkcijas. Funkcijos rezultato tipas būtinai turi atitikti tipą funkcijos prototipe. Funkcija grąžina rezultatą, jei jos įvykdymas pasibaigia operatoriumi return: return išraiška;

9 Funkcijos Išraiška gali būti skaičiuojama (pvz. return a + b;), konvertuojama (pvz. return (int) a;) jei būtina į funkcijos rezultato tipą aprašyto funkcijos prototipe ar apibrėžime, ir perduodama į funkcijos kvietimo vietą. Jei operatorius return nenurodomas ar neturi jokios išraiškos – funkcija negrąžina rezultato. Šiuo atveju būtina vietoje funkcijos rezultato tipo naudoti void.

10 Funkcijos parametrai Formaliųjų parametrų sąrašas: tai tam tikra tvarka surašyti formaliųjų parametrų aprašai. Iš tikrųjų tai yra kintamieji, kurie įgauna reikšmes, kurios yra perduodamos kviečiant funkciją. Formalieji parametrai yra atskiriami kableliais. Parametrų sąrašas gali baigtis ir daugtaškiu (,...). Tai reiškia, kad funkcijos parametrų sąrašas yra kintamas (pvz. funkcijos printf ir scanf). Bet manoma, kad funkcija gali turėti mažiausiai tiek parametrų, kiek jų yra aprašyta iki paskutinio kablelio. Funkcijai galime perduoti daugiau argumentų nei yra aprašyta parametrų iki paskutinio kablelio. Tokiems argumentams nebus daroma tipų patikrinimo kontrolė. Jei funkcijai parametrai nėra perduodami tada naudojame void. Formaliųjų parametrų tvarka ir tipai turi atitikti vienodi ir funkcijos apibrėžime ir prototipe. Faktinių argumentų tipai kviečiant funkciją turi atitikti formaliųjų parametrų tipus. Formalusis parametras gali būti bet kokio bazinio tipo, struktūra, sąrašo, išvardinimo, rodykle ar masyvu.

11 Funkcijos kūnas Funkcijos kūnas tai sudėtinis funkcijos operatorius, kurį sudaro operatoriai, nusakantys funkcijos veikimą. Jį gali sudaryti ir reikalingų kintamųjų apibrėžimai, kurie naudojami funkcijos kūne. Visi kintamieji apibrėžti funkcijoje yra lokalieji. Tuo metu kai kviečiama funkcija, lokaliems kintamiesiems yra išskiriama atmintis ir įvykdoma jų inicializacija (jei ji nurodyta). Funkcijoje valdymas yra perduodamas pirmam operatoriui ir prasideda funkcijos vykdymas, kuris tęsiasi tol kol nebus pasiektas operatorius return ar funkcijos kūno pabaiga. Valdymas tada yra perduodamas į tą programos vietą kurioje funkcija buvo kviečiama. Jei funkcija turi grąžinti rezultatą – reikia įvykdyti operatorių return ir nurodyti jam grąžinamą reikšmę.

12 Funkcijos parametrai C kalboje funkcijos parametrai yra perduodami pagal reikšmę ir funkcijoje yra traktuojami kaip lokalieji kintamieji, kuriems yra išskiriama atmintis prieš pradedant vykdyti funkciją, jie yra inicializuojami funkcijai perduodamomis reikšmėmis ir yra prarandami išėjus iš funkcijos kūno. Todėl funkcijoje negalima pakeisti parametro, nes funkcija dirba su argumentų kopijomis. Bet jei vietoje reikšmių funkcijai perduosime rodyklę, funkcijoje pasinaudojus išadresavimo funkcija galima pakeisti parametro reikšmę.

13 Funkcijos Reikšmių keitimo funkcija: //blogas pavyzdys void mainai (int x, int y) { int temp = x; x = y; y = temp; } //geras pavyzdys void mainai (int *ptr_x, int *ptr_y) int temp = *ptr_x; *ptr_x = *ptr_y; *ptr_y = temp;

14 Funkcijos prototipas Jei reikia iškviesti funkciją iki jos panaudojimo viename faile arba funkcijos apibrėžimas yra kitame faile, prieš kviečiant tokią funkciją reikia ją aprašyti, t.y. sukurti jai prototipą. Prototipas leis kompiliatoriui atlikti argumentų ir rezultato patikrinimą. Prototipas aprašomas tokiu būdu: [atminties klasė] [tipas] funkcijos_pavadinimas ([formaliųjų parametrų sąrašas]); Skirtingai nei funkcijos apibrėžimas, prototipas yra užbaigiamas kabliataškiu.

15 Funkcijos_pavadinimas ([išraiškų sąrašas]);
Funkcijos kvietimas Funkcija kviečiama taip: Funkcijos_pavadinimas ([išraiškų sąrašas]); Išraiškų sąrašas tai faktiniai argumentai, kurie yra perduodami funkcijai. Funkcijos kvietimas atrodo sekančiu būdu: Pirmiausią yra atliekami skaičiavimai išraiškų sąraše. Pvz. kviečiame funkciją ir perduodame jai parametrus (a+b, c, d-e). Toliau, jei yra žinomas funkcijos prototipas, rezultato tipas yra lyginamas su formaliuoju rezultato tipu, t.y. žiūrima kokio tipo reikšmė yra return operatoriuje ir koks yra rezultato tipas prototipe. Jei jie neatitinka yra arba bandoma suvienodinti tipus arba yra gaunamas atitinkamas pranešimas (pvz. klaida). Toliau tikrinama ar faktinių parametrų skaičius sutampa su formaliųjų parametrų skaičiumi, išskyrus tą atvejį kai turime kintamą kiekį parametrų. Tokiu atveju kompiliatorius patikrina tiek argumentų kiek tipų yra formaliųjų parametrų sąraše ir esant reikalui bando juos suvienodinti. Jei funkcijos prototipe vietoje formaliųjų parametrų turime void, tai reiškia kad funkcijai nėra perduodami argumentai ir funkcijos prototipe neturi būti parametrų. Jei tai ne taip – duodamas atitinkamas pranešimas. Vykdomas formaliųjų parametrų keitimas faktiniais argumentai. Pirmas formalusis atitinka pirmąjį faktinį argumentą ir t.t. Valdymas perduodamas pirmam funkcijos operatoriui. Operatoriaus return vykdymas funkcijos kūne grąžina valdymą ir galimai rezultatą kviečiančiai funkcijai. Jei operatoriaus return nėra, valdymas bus gražintas įvykdžius paskutinį funkcijos operatorių.

16 Rekursiniai funkcijų kvietimai
Bet kuri funkcija C kalboje gali būti išviesta rekursyviai, t.y. gali kviesti pati save. Kompiliatorius leidžia bet kokį skaičių rekursinių kvietimų, bet tą kiekį gali riboti operacinė sistema. Kiekvieno funkcijos kvietimo metu yra išskiriama nauja atmintis, tokiu būdu reikšmės iš prieš tai neužbaigtų kvietimų nedingsta, bet parametrai iš prieš tai neužbaigtų kvietimų nėra pasiekiami. Rekursijos pavydžiu gali būti faktorialo skaičiavimas: n! = 1, kai n=0 ir n!= n* (n-1)!, kai n>1. long faktorialas (int n) { return (n<=1) ? 1 : n * faktorialas (n-1); }

17 Rekursiniai funkcijų kvietimai
//Faktorialo n!= 1* 2 *...* n skaiciavimas 0!=1, Vn>0, n!=n *(n -1)! #include<stdio.h> long Faktorialas(long); int main() { int n; printf("Iveskite sveika skaciu: "); scanf("%d", &n); printf ("%d! = %d\n", n, Faktorialas(n)); return 0; } long Faktorialas(long skaicius) if ( skaicius <=1 ) return 1; else return (skaicius * Faktorialas(skaicius - 1));

18 ctype.h <ctype.h> - simbolių tikrinimų funkcijos.
int isalnum(int c); grąžina 1 jei tai didžioji raidė, 2 – jei mažoji, 0 – jei skaičius. Analogais gali būti isalpha(c) ar isdigit(c); isalpha(c) or isdigit(c) grąžina 1 jei tai didžioji raidė, 2 – jei mažoji, 0 – jei skaičius. Analogais gali būti isupper(c) ar islower(c); int isalpha(int c); isupper(c) or islower(c) int iscntrl(int c); //is control character. In ASCII, control characters are 0x00 (NUL) to 0x1F (US), and 0x7F (DEL) int isdigit(int c); //is decimal digit

19 ctype.h int isgraph(int c); //is printing character other than space
int islower(int c); //is lower-case letter int isprint(int c); //is printing character (including space). In ASCII, printing characters are 0x20 (' ') to 0x7E ('~') int ispunct(int c); //is printing character other than space, letter, digit int isspace(int c);/ /is space, formfeed, newline, carriage return, tab, vertical tab int isupper(int c); //is upper-case letter int isxdigit(int c); //is hexadecimal digit int tolower(int c); //return lower-case equivalent int toupper(int c);

20 math.h double exp(double x); exponential of x
double log(double x); natural logarithm of x double log10(double x); base-10 logarithm of x double pow(double x, double y); x raised to power y double sqrt(double x); square root of x double ceil(double x); smallest integer not less than x double floor(double x); largest integer not greater than x double fabs(double x); absolute value of x double modf(double x, double* ip); returns fractional part and assigns to *ip integral part of x, both with same sign as x double fmod(double x, double y); if y non-zero, floating-point remainder of x/y, with same sign as x; if y zero, result is implementation-defined

21 math.h double sin(double x); sine of x
double cos(double x); cosine of x double tan(double x); tangent of x double asin(double x); arc-sine of x double acos(double x);arc-cosine of x double atan(double x); arc-tangent of x double atan2(double y, double x); arc-tangent of y/x

22 stdio.h EOF Value used to indicate end-of-stream or to report an error. NULL Null pointer constant. SEEK_CUR Value for origin argument to fseek specifying current file position. SEEK_END Value for origin argument to fseek specifying end of file. SEEK_END Value for origin argument to fseek specifying beginning of file. stdin File pointer for standard input stream. Automatically opened when program execution begins. stdout File pointer for standard output stream. Automatically opened when program execution begins. stderr File pointer for standard error stream. Automatically opened when program execution begins.

23 stdio.h FILE Type of object holding information necessary to control a stream. FILE* fopen(const char* filename, const char* mode); Opens file named filename and returns a stream, or NULL on failure. mode may be one of the following for text files: "r“ text reading "w“ text writing "a“ text append "r+”text update (reading and writing) "w+”text update, discarding previous content (if any) "a+“ text append, reading, and writing at end or one of those strings with b included (after the first character), for binary files. FILE* freopen(const char* filename, const char* mode, FILE* stream); Closes file associated with stream, then opens file filename with specified mode and associates it with stream. Returns stream or NULL on error.

24 stdio.h int fflush(FILE* stream);
Flushes stream stream and returns zero on success or EOF on error. Effect undefined for input stream. fflush(NULL) flushes all output streams. int fclose(FILE* stream); Closes stream stream (after flushing, if output stream). Returns EOF on error, zero otherwise. int remove(const char* filename); Removes specified file. Returns non-zero on failure. int rename(const char* oldname, const char* newname); Changes name of file oldname to newname. Returns non-zero on failure. int fprintf(FILE* stream, const char* format, ...); Converts (according to format format) and writes output to stream stream. Number of characters written, or negative value on error, is returned. Conversion specifications consist int printf(const char* format, ...); printf(f, ...) is equivalent to fprintf(stdout, f, ...) int fscanf(FILE* stream, const char* format, ...); Performs formatted input conversion, reading from stream stream according to format format. The function returns when format is fully processed. Returns number of items converted and assigned, or EOF if end-of-file or error occurs before any conversion. Each of the arguments following format must be a pointer.

25 stdio.h int scanf(const char* format, ...);
scanf(f, ...) is equivalent to fscanf(stdin, f, ...) int fputc(int c, FILE* stream); Writes c, to stream stream. Returns c, or EOF on error. int getc(FILE* stream); Equivalent to fgetc except that it may be a macro. int getchar(void); Equivalent to getc(stdin). char* gets(char* s); Copies characters from stdin into s until newline encountered, end-of-file reached, or error occurs. Does not copy newline. NUL- terminates s. Returns s, or NULL on end-of-file or error. Should not be used because of the potential for buffer overflow. int putc(int c, FILE* stream); Equivalent to fputc except that it may be a macro. int putchar(int c); putchar(c) is equivalent to putc(c, stdout). int puts(const char* s); Writes s (excluding terminating NUL) and a newline to stdout. Returns non-negative on success, EOF on error. int feof(FILE* stream); Returns non-zero if end-of-file indicator is set for stream stream

26 stdlib.h RAND_MAX Maximum value returned by rand(). NULL
Null pointer constant. int abs(int n); long labs(long n); Returns absolute value of n. double atof(const char* s); ir double strtod(const char* s, char** endp); Converts initial characters (ignoring leading white space) of s to type double. If endp non-null, stores pointer to unconverted suffix in *endp. long atol(const char* s); ir long strtol(const char* s, char** endp, int base); Converts initial characters (ignoring leading white space) of s to type long. void* calloc(size_t nobj, size_t size); Returns pointer to zero-initialised newly-allocated space for an array of nobj objects each of size size, or NULL on error.

27 stdlib.h void* malloc(size_t size);
Returns pointer to uninitialised newly-allocated space for an object of size size, or NULL on error. void* realloc(void* p, size_t size); Returns pointer to newly-allocated space for an object of size size, initialised, to minimum of old and new sizes, to existing contents of p (if non-null), or NULL on error. On success, old object deallocated, otherwise unchanged. void free(void* p); If p non-null, deallocates space to which it points. void exit(int status); Terminates program normally. int rand(void); Returns pseudo-random number in range 0 to RAND_MAX

28 string.h NULL Null pointer constant.
char* strcpy(char* s, const char* ct); Copies ct to s including terminating NUL and returns s. char* strcat(char* s, const char* ct); Concatenate ct to s and return s. int strcmp(const char* cs, const char* ct); Compares cs with ct, returning negative value if cs<ct, zero if cs==ct, positive value if cs>ct.

29 time.h struct tm Represents the components of calendar time:
int tm_sec; seconds after the minute int tm_min; minutes after the hour int tm_hour; hours since midnight int tm_mday; day of the month int tm_mon; months since January int tm_year; years since 1900 int tm_wday; days since Sunday int tm_yday; days since January 1 int tm_isdst;

30 limits.h CHAR_BIT number of bits in a char CHAR_MAX
maximum value of type char CHAR_MIN minimum value of type char SCHAR_MAX maximum value of type signed char SCHAR_MIN minimum value of type signed char UCHAR_MAX maximum value of type unsigned char SHRT_MAX maximum value of type short

31 limits.h SHRT_MIN minimum value of type short USHRT_MAX
maximum value of type unsigned short INT_MAX maximum value of type int INT_MIN minimum value of type int UINT_MAX maximum value of type unsigned int LONG_MAX maximum value of type long LONG_MIN minimum value of type long ULONG_MAX maximum value of type unsigned long

32 Masyvai C kalboje perduodant masyvus funkcijoms yra perduodama ne pati duomenų struktūra, o tik rodyklė į ją, t.y. nurodant masyvo pavadinimą iš tikrųjų turime omeny rodyklę į pirmą masyvo elementą. Dėl šios priežasties visi pakeitimai daromi kitose funkcijose su reikalingo masyvo elementais yra “matomi” funkcijose kurioje masyvas buvo apibrėžtas ar kuriai masyvas yra perduodamas. Išvada – masyvo grąžinti iš funkcijos nereikia.

33 Masyvai Perduodant masyvą funkcijai kartu prasminga perduoti ir jo elementų kiekį: int suma (int masyvas[], int kiekis) { int i, suma; for (i=0; i<kiekis; i++) suma+=masyvas[i]; return suma; } int main() int mas[10], kiekis=10; printf (“Masyvo elementų suma lygi %d”, suma(mas, 10));

34 duomenu_tipas *vardas;
Rodyklės – kas tai? Kintamasis tai objektas turintis vardą ir kintančią reikšmę. Kintamajam išskiriama atmintis, kurios dydis priklauso nuo tipo. Kintamojo reikšme gali būti adresas. Rodyklės tipo kintamasis apinrėžiamas taip: duomenu_tipas *vardas; pvz.: int *ptr; char *eilute; Teoriškai rodyklė galėtų “rodyti” į bet kokią atminties vietą, bet praktiškai rodyklė “rodo” į adresą kuriuo saugomas nurodyto tipo objektas.

35 duomenu_tipas *vardas;
Rodyklės – kas tai? Kintamasis tai objektas turintis vardą ir kintančią reikšmę. Kintamajam išskiriama atmintis, kurios dydis priklauso nuo tipo. Kintamojo reikšme gali būti adresas. Rodyklės tipo kintamasis apibrėžiamas taip: duomenu_tipas *vardas; pvz.: int *ptr; char *eilute; Teoriškai rodyklė galėtų “rodyti” į bet kokią atminties vietą, bet praktiškai rodyklė “rodo” į adresą kuriuo saugomas nurodyto tipo objektas.

36 Rodyklės – kas tai? Rodyklė tai kintamasis kurios reikšme yra kito kintamojo adresas (eng. pointer). Sakome, kad jei vienas kintamas saugo kito kintamojo adresą, tai pirmas kintamasis “rodo” į antrą.

37 Rodyklės – kas tai? Kaip ir kito tipo objektams saugoti, rodyklės reikšmei saugoti reikalingas tam tikras baitų kiekis. Šis kiekis priklauso nuo naudojamos platformos. (Pvz. 32 bitų platformoje adresui saugoti reikia 4 baitų).

38 Pagrindiniai operatoriai
Pagrindiniais operatoriais kurie operuoja rodyklės tipo operandais yra: * - išadresavimo operatorius. Šis unarinis operatorius “paima” tikrąją reikšmę pagal operando adresą. Šio operatoriaus operandais gali būti tik rodyklės tipo kintamieji. & - adreso operatorius. Šio unarinio operatoriaus rezultatas yra nurodyto kintamojo adresas. Šio operatoriaus rezultatas gali būti priskiriamas tik rodyklės tipo kintamiesiems. Šio operatoriaus operandais gali būti tik kintamieji arba masyvo elementai.

39 Pavyzdys #include <stdio.h> void main() { int num; int *p; num = 10; p=&num; printf(“Adreso operatoriaus panaudojimas: %p”, p); printf(“Išadresavimo operatoriaus panaudojimas: %d”, *p); }

40 Pavyzdys #include <stdio.h> void main(void) { int num, q; int *p; num = 100; p = &num; q = *p; printf("%d", q); }

41 Pavyzdys #include <stdio.h> int j, k; int *ptr; void main(void) { j = 1; k = 2; ptr = &k; printf("j reiksme %d ir jos adresas %p\n", j, &j); printf("k reiksme %d ir jos adresas %p\n", k, &k); printf("ptr reiksme %p ir jos adresas %p\n", ptr, &ptr); printf("Reiksme i kuria rodo ptr yra %d\n", *ptr); }

42 Pavyzdys #include <stdio.h> void main() { int num; num = 10; //Kam bus lygu *&num ? //O *&*&num ? //O *&*&*&*&*&*&*&num? }

43 Rodyklės tipo kintamųjų inicializavimas
Paprastieji globalieji kintamieji, juos apibrėžiant bet nepriskiriant jiems reikšmės, įgauna reikšmę 0 (pagal ANSI standartą). Rodyklės tipo kintamasis nėra inicializuojamas pagal nutylėjimą, jei jam reikšmė nėra priskiriama apibrėžimo metu. Sakome, kad rodyklė rodys į jokį objektą, t.y. jos reikšmė bus NULL. NULL yra makrosas kuris leidžia, nepriklausomai nuo naudojamos platformos, realizuoti tuščią rodyklę. Šį makrosą galima naudoti priskyrime arba palyginimo sakiniuose, pvz.: if (ptr == NULL) ...

44 Rodyklių priskyrimas Reikšmės rodyklės tipo kintamiesiems priskiriami įprasta tvarka. #include <stdio.h> void main (void) { int x; int *p1, *p2; p1 = &x; p2 = p1; printf ("%р %р", p1, р2); }

45 Rodiklių aritmetika Unarinės operacijos * ir & turi aukščiausią prioritetą. Kuo skiriasi *ptr++; ir *(ptr++);? Rodyklės tipo kintamiesiems gali būti taikomos operacijos: galima pridėti integer tipo skaičių prie rodyklės tipo kintamojo reikšmės; pvz. ptr1++, ptr1 + i galima atimti integer tipo skaičių nuo rodyklės tipo kintamojo reikšmės; pvz. ptr1--, ptr1-i galima atimti vienos rodyklės tipo kintamojo reikšmę nuo kitos rodyklės tipo kintamojo reikšmės; pvz. ptr2-ptr1 – gausime elementų kiekį tarp ptr1 ir ptr2. Tas skaičius gali būti neigiamas. Adresų negalima dauginti, dalinti, iš jų negalima atimti ar pridėti float ar double tipo reikšmių. Rodyklės tipo kitamiesiems negalima taikyti postūmio operacijų. Tarkime turime int *ptr kur ptr adresas yra Jei atliksim operaciją ptr++; kokia bus ptr reikšmė? Int atveju Atitinkamai ptr— Adresą galime apskaičiuoti pagal formulę: Pradinis_adresas + n*sizeof(duomenu_tipas), kur n elementų kiekis.

46 Rodiklių aritmetika #include <stdio.h> int const N = 10; void Spausdinti(int *); int main() { int masyvas[N], i; for (i=0;i<N; i++) masyvas[i]=(i+1)*10; } Spausdinti(masyvas); return 0; void Spausdinti(int *p) int i; printf("%2d-asis masyvo elementas yra: %d\n", i+1, *(p+i)); printf("Masyvo elemntu kiekis: %d", (p+N) - p);

47 Rodyklių palyginimas Rodyklės tipo kintamiesiems gali būti taikomos palyginimo operacijos: == palyginti ar du rodyklės tipo kintamieji turi vienodas reikšmes; pvz ptr1 == ptr2 teisybė jei ptr1 ir ptr2 rodo į tą patį elementą != palyginti ar du rodyklės tipo kintamieji turi nevienodas reikšmes; pvz ptr1 != ptr2 teisybė jei ptr1 ir ptr2 rodo į skirtingus elementus >, <, >=, <= palyginti rodyklių reikšmes. ptr1<ptr2 arba ptr1<=ptr2 gausime teisybę jei ptr1 rodo į masyvo elementą su mažesniu ar lygiu indeksu nei ptr2

48 Rodyklių palyginimas #include <stdio.h> int const N = 10; int main() { int masyvas[N], i; int *p, *k; for (i=0;i<N; i++) masyvas[i]=(i+1)*10; } p = masyvas + 5; k = masyvas + 6; printf ("p reiksme: %d\n", *p); printf ("k reiksme: %d\n", *k); if (p == k) printf("rodykles p ir k rodo i ta pati objekta"); else printf("rodykles p ir k rodo i skirtingus objektus"); return 0;

49 Rodyklių palyginimas #include <stdio.h> int const N = 10; int main() { int masyvas[N], i; int *p, *k; for (i=0;i<N; i++) masyvas[i]=(i+1)*10; } p = masyvas + 5; k = masyvas + 6; printf ("p reiksme: %d\n", *p); printf ("k reiksme: %d\n", *k); if (p < k) printf("rodykles p rodo i masyvo elementa su mazesniu indeksu nei k"); return 0;

50 Rodyklės ir masyvai int main(void) { int my_array[] = {1,23,17,4,-5,100}; int *ptr; int i; ptr = &my_array[0]; // ptr rodys i pirma masyvo elementa //ptr = my_array; printf("\n"); for (i = 0; i < 6; i++) printf("my_array[%d] = %3d\t",i,my_array[i]); //eilute A: paimam masyvo reiksme naudojantis indeksu printf("ptr + %d = %3d\n",i, *(ptr + i)); //eilute B: paimam masyvo reiksme taikydami rodykliu postumius } return 0;

51 Rodyklės ir masyvai ptr = &my_array[0]; ir ptr = my_array; yra tas pats. Bet my_array = ptr rašyti negalima, nes ptr yra kintamasis o my_array yra konstanta, todėl pirmo masyvo elemento adreso pakeisti negalima, nes atmintis visiems masyvo elementams buvo jau išskirta masyvo apibrėžimo metu.

52 Pavyzdys #include <stdio.h> #define DYDIS 10 main() { int masyvas[DYDIS]; int suma = 0; int i; int *p; for (i=0;i<DYDIS;i++) {masyvas[i] = i+1;} //skaiciuojame masyvo elementu suma //1 budas {suma = suma + masyvas[i];} printf ("Masyvo elementu suma yra %d\n", suma);

53 Pavyzdys //2 budas suma = 0; p = &masyvas[0]; for (i=0;i<DYDIS;i++) { suma = suma + (*p); p++; } printf ("Masyvo elementu suma yra %d\n", suma); //3 budas suma = 0; {suma = suma + *(p + i);} printf ("Masyvo elementu suma yra %d\n", suma);

54 Daugiamačiai masyvai #define ROWS 5 #define COLS 10
int multi[ROWS][COLS]; Norint pasiekti konkretų elementą rašysime multi [row][col] arba *(*(multi + row) + col). Pakeiskime reiškinį *(multi + row) reikšme X – tada aukščiau parašytą reiškinį parašytume *(X + col). X šiuo atveju yra rodyklė o col yra integer tipo skaičius, t.y. matome paprastą aritmetinę operaciją kuriai pritaikyta išadresavimo operacija. Žiūrint į šiuos pertvarkymus galime pasakyti kad iš tikrųjų turime tik vienmatį masyvą kuriame eilutės eina viena po kitos, t.y. bet kurį daugiamatį masyvą galime pertvarkyti į vienmatį masyvą.

55 Daugiamačiai masyvai Trimatis masyvas int arr[L][M][N].
Kadangi šį masyvą galime interpretuoti kaip masyvą kurio elementais yra dvimačiai masyvai MxN tai norint gauti tam tikrus elementus masyve galime taikyti šias operacijas: ptr – masyvo L pirmo elemento adresas, t.y. šiuo atveju pirmas elementas yra pirmas masyvas MxN ptr + i *(M*N) - masyvo L i-tojo elemento adresas ptr + i*(M*N) + j *N - masyvo L j-tojo elemento adresas ptr + i*(M*N) + j *N + k - masyvo L k-tojo elemento adresas *(ptr + i*(M*N) + j *N + k) - masyvo L k-tojo elemento reikšmė

56 Rodyklės į neapibrėžtą tipą
void * rodykles_vardas; Žodis void leidžia mums konkretizuoti tipą vėliau, t.y. programos vykdymo metu. Tokio tipo rodyklė gali rodyti į bet kokio objekto tipą. Bet norint operuoti su neapibrėžto tipo rodyklėmis reikia pirmiausia atlikti konvertavimo operaciją: #include <stdio.h> main() { int a = 10; double d = 5.236; void *vp; vp = &a; printf ("a=%d\n", *((int *) vp)); vp = &d; printf ("d=%f\n", *((double *) vp)); }

57 Rodyklių taikymas Duomenų perdavimas pagal adresą (byref) main() {
int x,y; …. x = 5; y = 10; swap (x,y); } void swap (int a, int b) int temp; temp = a; a = b; b = temp;

58 Rodyklių taikymas void swap (int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } main() int x, y; … swap ( &x, &y);

59 Galimos klaidos #include <stdio.h> void main() { int x = 65000, y; short *ptr; ptr = &x; y = *ptr; printf ("x=%d\n", x); printf ("y=%d\n", y); // kodel gausime kita skaiciu??? }

60 Galimos klaidos void main (void) { int х, *р; х = 10; *р = х; // klaida, kodėl??? }

61 Galimos klaidos #include <stdio.h> void main(void) { int x, *p; x = 10; p = x; // klaida, kodel??? printf ("%d", *p); }


Download ppt "Lekt. Tomas G. Lipnevičius"

Similar presentations


Ads by Google