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.