Język C, tablice i funkcje (laboratorium)
Transkrypt
Język C, tablice i funkcje (laboratorium)
Język C, tablice i funkcje (laboratorium) Opracował: Tomasz Mączka ([email protected]) Wstęp (tablice) Tablica to uporządkowany ciąg elementów tego samego typu, zajmujących ciągły obszar pamięci. Tablica w języku C jest identyfikowana przez nazwę (identyfikator), a do konkretnych elementów można odwołać się poprzez indeks. Tablicę definiuje się w następujący sposób typ nazwa_tablicy[rozmiar_tablicy]; Typ jest typem (np. int, char, long) elementów przechowywanych w tablicy. Rozmiar tablicy to liczba całkowita określająca liczbę przechowywanych w tablicy elementów. Liczba ta musi być wartością stałą, znaną na etapie kompilacji. Przykłady definicji tablic int pomiary[10]; //10-elementowa tablica liczb calkowitych double fun[25]; //25-elementowa tablica liczb zmiennoprzecinkowych char imie[64]; //64-elementowa tablica znakow int wsp[3] = {34, 12, 99}; //definicja tablicy z inicjalizacja - nadaniem //wartosci poczatkowych kolejnym elementom Do elementów tablicy odwołujemy się najczęściej poprzez operator indeksowania [], podając numer elementu: nazwa_tablicy[nr_elementu]; na przykład a = pomiary[0]; //podstawienie do zmiennej a wartości pierwszego //elementu tablicy printf("%d",pomiary[5]); //wypisanie piątego elementu tablicy pomiary[7] = 11; //przypisanie do siódmego elementu tablicy wartosci 11 UWAGA! Tablice w języku C są indeksowane od 0 (pierwszy element) do ROZMIAR_TABLICY-1 (ostatni element), np. tablica pomiary, której definicję podano powyżej, zawiera elementy o indeksach 0,1,2,3,4,5,6,7,8,9. Należy zwracać uwagę na nieprzekraczanie zakresu tablicy, gdyż może to spowodować otrzymanie „dziwnych” danych lub wystąpienie błędu naruszenia ochrony pamięci. Do wykonywania operacji na elementach tablicy często używa się pętli. Przykłady (tablice) Wczytywanie elementów tablicy #include <stdio.h> void main(void) { int tab[10]; int i; //definicja tablicy, elementy 0..9 //licznik petli for (i=0; i<10; i++) scanf("%d",&tab[i]); } Wczytywanie określonej (podanej przez użytkownika) liczby elementów tablicy W tym i kolejnych przykładach rozmiar tablicy definiowany jest jako „stała” ROZMIAR_TAB. Jeżeli okaże się, że konieczne jest np. zwiększenie rozmiaru, wystarczy dokonać zmiany tylko w jednym miejscu – nie trzeba przeglądać wszystkich warunków w pętlach odwołujących się do tablicy itp. . #include <stdio.h> //'stala' – rozmiar tablicy #define ROZMIAR_TAB 10 void main(void) { int tab[ROZMIAR_TAB]; //definicja tablicy, elementy 0..9 int i; //licznik petli int N; //liczba elementow do wczytania – podaje uzytkownik printf("Ile elementow tablicy wczytac (max. 10): "); scanf("%d",&N); //sprawdzenie, czy N elementow zmiesci sie w tablicy if (N<=ROZMIAR_TAB) { for (i=0; i<N; i++) { printf("Podaj element nr %d:",i); scanf("%d",&tab[i]); } } else printf("Tablica może zawierac max. %d elementow!",ROZMIAR_TAB); } Dla zainteresowanych: #define NAZWA CZYM_ZASTAPIC jest dyrektywą preprocesora, tzw. makrodefinicją. Wystąpienie takiej dyrektywy powoduje, że przed kompilacją programu preprocesor podmienia w kodzie źródłowym (tym „przekazywanym” kompilatorowi, nie edytowanym przez programistę!) wszystkie wystąpienia NAZWA poprzez CZYM_ZASTAPIC. Obliczanie sumy elementów w tablicy liczb całkowitych #include <stdio.h> //'stala' – rozmiar tablicy #define ROZMIAR_TAB 5 void main(void) { //inicjalizacja tablicy przykladowymi wartosciami int tab[ROZMIAR_TAB] = {1, 33, 66, 77, 21}; int i; //licznik petli int suma = 0; //suma elementow tablicy for (i=0; i<ROZMIAR_TAB; i++) suma+=tab[i]; //odpowiednik suma=suma+tab[i] } printf("Suma elementow tablicy wynosi %d", suma); Tablice wielowymiarowe – przykład float macierz[10][10]; macierz[1][2]=3.0f; Wstęp (funkcje) Funkcja (podprogram) jest wydzieloną częścią programu, wykonująca określone instrukcje. Może przyjmować argumenty (parametry) i zwracać w wyniku działania wartość. Funkcja może zostać wywołana z poziomu innej funkcji (np. z poziomu „głównego programu” - funkcji main) lub wywoływać samą siebie (rekurencja). Dzięki funkcjom unika się powielania kodu, a tworzony program łatwiej jest modyfikować. Ogólny schemat definicji funkcji: typ_zwracany nazwa_funkcji(typ1 argument1, typ2 argument2, typ_n argument_n) { /* instrukcje */ } Funkcja może nie zwracać żadnej wartości, wtedy jako typ_zwracany podaje się void. Jeżeli funkcja nie przyjmuje żadnych parametrów, jej definicja wygląda następująco: typ_zwracany nazwa_funkcji(void) { /* instrukcje */ } Ogólny schemat wywołania funkcji: nazwa_funkcji(argument1, argument2, argumentn); //przypisanie wartosci zwroconej przez funkcje do zmiennej zmienna=nazwa_funkcji(argument1, argument2, argumentn); //jeżeli funkcja nie przyjmuje żadnych argumentów – puste nawiasy okragle nazwa_funkcji2(); Deklaracja funkcji Nazwa, parametry i wartość zwracana przez funkcję powinny być „znane” kompilatorowi w miejscu jej wywołania. W tym celu stosuje się deklarację (prototyp) funkcji, tj. „nagłówek” funkcji zakończony średnikiem. Przykład typ_zwracany nazwa_funkcji(void); Funkcja dla której podano deklarację, musi zostać zdefiniowana w obrębie programu. Uwaga: Deklaracja funkcji nie jest konieczna, jeżeli przed miejscem wywołania funkcja została już zdefiniowana. Częstą praktyką (w obrębie pojedynczego pliku źródłowego) jest umieszczanie deklaracji własnych funkcji przed definicją main, a definicji tychże funkcji po definicji funkcji main (przykład poniżej). Przykład deklaracji, definicji i wywołania funkcji #include <stdio.h> //deklaracja funkcji suma //funkcja przyjmuje 2 parametry calkowitoliczbowe //w wyniku jej dzialania zwracana jest liczba calkowita int suma(int x, int y); //uwaga: deklaracja nie jest konieczna, w tym miejscu mogłaby się pojawić //definicja void main(void) { int x=1; int rezultat = suma(x,3); printf("Rezultat funkcji: %d",rezultat); } //mozna tez tak, bez dodatkowej zmiennej pomocniczej printf("Rezultat funkcji: %d",suma(x,3)); //definicja funkcji suma int suma(int x, int y) { int s = x + y; //obliczenie sumy argumentow x i y return s; //i jej zwrocenie } Zdefiniowana została funkcja suma, przyjmująca 2 parametry całkowitoliczbowe x, y i zwracająca w wyniku działania liczbę całkowitą. Ciało funkcji (operacje które wykonuje) jest zawarte w nawiasach klamrowych { }. Instrukcja return w ciele powoduje zakończenie jej wykonywania ze zwróceniem wyrażenia podanego po return jako wyniku. Wywołanie funkcji odbywa się poprzez podanie jej nazwy i argumentów oddzielonych przecinkami. Jeżeli funkcja zwraca wynik, można go np. przypisać do zmiennej, jak w przykładzie powyżej. Uwaga! W języku C argumenty funkcji są przekazywane przez wartość. Przy wywołaniu funkcji tworzone są lokalne kopie przekazywanych argumentów i wewnątrz funkcji operuje się na tych kopiach. Oznacza to, że przekazywane argumenty nie ulegają zmianie. Przykład: #include <stdio.h> void dokwadratu(int x) { printf("Funkcja dokwadratu poczatek, x=%d",x); x*=x; //odpowiada x=x*x; printf("Funkcja dokwadratu po wykonaniu operacji, x=%d",x); } void main(void) { int liczba=5; printf("liczba przed wywolaniem dokwadratu: %d",liczba); //wywolanie funkcji dokwadratu, zmienna liczba jest kopiowana do argumentu x //funkcji! dokwadratu(liczba); //wartosc zmiennej liczba nie zostanie zmodyfikowana, funkcja pracuje na //kopii printf("liczba po wywolaniu dokwadratu: %d",liczba); } Przykład przekazywania do funkcji argumentów będących tablicami int sumuj(int tab[], int rozmiar) { int suma = 0; int i; for (i=0; i<rozmiar; ++i) suma += tab[i]; } return suma; void main(void) { int liczby[] = { 1, 3, 6, 7, 2 }; int suma = 0; } suma = sumuj(liczby, 5); Zadania 1. Napisz program, który wczyta N liczb całkowitych do tablicy i obliczy sumę liczb dodatnich i ujemnych. Przykładowe działanie programu (wartości wpisywane z klawiatury zostały pogrubione): Ile elementow tablicy wczytac? 5 Podaj kolejne elementy: 2 3 -5 -11 4 Suma dodatnich: 9 Suma ujemnych: -16 2. Napisz program, który wczyta ciąg N liczb, a następnie wypisze liczby, które się powtarzają. Ile elementow tablicy wczytac? 7 Podaj kolejne elementy: 11 55 11 22 34 22 11 Powtórzenia: 11 22 3. Napisz, a następnie wywołaj w programie funkcję wyznaczającą wartość bezwzględną liczby przekazanej jako parametr. 4. Napisz, a następnie wywołaj w programie funkcję wyznaczającą średnią dwóch liczb zmiennoprzecinkowych 5. Napisz, a następnie wywołaj w programie funkcję przyjmującą 2 parametry liczbowe (np. N i X), która obliczy N-tą potęgę liczby X (bez wykorzystania funkcji pow z biblioteki standardowej). 6. Wewnątrz funkcji z punktu 4 oblicz średnią wartości bezwzględnych argumentów (przy pomocy funkcji z punktu 3). Przykładowe działanie programu: Podaj X: -4 Podaj Y: 6 'Srednia': 5 7. Napisz a następnie wywołaj w programie funkcję sprawdzającą, czy liczba podana jako parametr jest liczbą pierwszą. Podpowiedź: wykorzystaj operator reszty z dzielenia (%). 8. Napisz funkcję przyjmującą jako argumenty tablicę liczb całkowitych i rozmiar tej tablicy. Funkcja ma modyfikować zawartość tablicy tak, że i-ty element będzie zsumowany z sumą poprzedzających go elementów. W programie głównym wywołaj funkcję, wypisz zawartość tablicy przed i po wywołaniu funkcji. Na przykład tablica: 2, 4, 12, 3, 5 powinna zostać przez funkcję zmodyfikowana do postaci: 2, 6 (=2+4), 18 (=6+12), 21 (=18+3), 26 (=21+5) 9. Napisz funkcję przyjmującą jako argumenty dwie tablice liczb zmiennoprzecinkowych (o takich samych rozmiarach) i rozmiar tych tablic. Funkcja powinna zwracać iloczyn skalarny wektorów, reprezentowanych przez te tablice. Wywołaj funkcję dla przykładowych danych w programie głównym. Na przykład dla tablic: A = { 1,2,3,4 }, B = { 5, 6, 7, 8 } funkcja powinna zwrócić wynik 70 (1*5+2*6+3*7+4*8). 10. Napisz funkcję przyjmującą jako argument tablicę dwuwymiarową o rozmiarach NxN i zwracającą sumę elementów na przekątnej. 11. Napisz funkcję przyjmującą jako argumenty 2 macierze (tablice dwuwymiarowe) o rozmiarach MxN, wykonującą operację dodawania macierzy i wypisującą wynik na ekran.