Laboratorium 8: Tablice (i funkcje)

Wprowadzenie

Zasadniczym tematem zajęć jest oskonalenie umiejętności operowania na tablicach (oraz używaniu ich jako parametrów funkcji).

Dodatkowym motywem jest tworzenie (w miarę) uniwersalnych funkcji (kiedy tylko istota tego co robią jest taka sama).

Statystyki tablicy

Stosunkowo prosty program, który pyta użytkownika o wymiary tablicy dwuwymiarowej (liczbę wierszy, na przykład $n$ i liczbę kolumn, na przykład $m$, a następnie wykonuje następujące czynności:

  • Organizuje miejsce na tablicę i tablice pomocnicze (czyli deklaruje wszystkie dane).

  • Wypełnia tablicę danymi Aby uprościć sobie życie zakładamy, że program wyposażony będzie w osobną funkcję wypełniającą tablicę losowymi danymi. Może ona wyglądać jakoś tak:

    #include <stdlib.h>
    #include <time.h>
    ...
    {
        ...
        srand( time(NULL) );
        for ( i = 0; i < m; i++ )
              for ( j = 0; j < m; j++ )
                  tablica[i][j] = rand() % M;
    }
    

    (oczywiście, trzeba uzupełnić wszystko co potrzebne!)

  • Następnie program wylicza średnią (osobna funkcja!) i wariancję (osobna funkcja!) dla każdego wiersza i każdej kolumny oraz dla całej tablicy i wyprowadza na terminal wszystkie wyniki.

Dostępne jest najprostsze ćwiczenie pozwalające przekazać tablicę dwuwymiarową do funkcji.

#include <stdio.h>
#include <stdlib.h>
void drukuj(int n, int m, int z[n][m])
{
    int i, j;
    for ( i = 0; i < n; i++ )
        for ( j = 0; j < m; j++ )
            printf("%d\n", z[i][j]);
}

int main(int argc, char **argv)
{
    int i, j;
    int N = 3;
    int M = 5;
    int a[N][M];
    for ( i = 0; i < N; i++ )
        for ( j = 0; j < M; j++ )
            a[i][j] = rand() % 20;
    for ( i = 0; i < N; i++ )
    {
        for ( j = 0; j < M; j++ )
            printf("%10d,", a[i][j]);
        printf("\n");
    }
    drukuj(N, M, a);
    return 0;
}

Zadanie może być wykonane na dwa sposoby: korzystając z deklaracji tablic (jak w powyższym ćwiczeniu) albo przydzielając na nie pamięć w sposób dynamiczny (korzystając z funkcji malloc1). Tu jest ściąga.

Jak się zabrać do problemu?

Jak się zabrać do problemu?

Tutaj kilka podpowiedzi jak ogarnąć ten problem.

  1. Zaczynamy od funkcji main() i deklarujemy w niej tablicę w, której przechowywać będziemy dane. Można to zrealizować definiując wcześniej zmienne N (liczba wierszy) i M (liczba kolumn), a tablicę zadeklarować jako:

    int A[N][M];
    

    albo użyć funkcji malloc (ściąga).

  2. Jednym z zadań programu jest wygenerowanie i wpisanie do tablicy danych. Powinno być to zrealizowane przez funkcję, niech nazywa się generuj_dane. Przykładowy jej kod znajduje się na początku podrozdziału Statystyki tablicy. Jest ona typu void, bo nie zwraca żadnych informacji.

  3. Ponieważ trzeba będzie wypisywać wartość tablicy (funkcja drukuj) potrzebna będzie funkcja, która to zrobi. Przykładowy kod znajduje się powyżej. Jest ona typu void, bo nie zwraca żadnych informacji.

  4. W funkcji main najpierw wywołujemy funkcję generuj_dane, a następnie drukuj.

  5. Teraz kolej na przygotowanie funkcji wyliczającej średnią z całej tablicy. Pamiętamy, żeby zmiennej, w której przechowywana będzie suma wszystkich elementów tablicy, wcześniej wyzerować. Podczas wyliczania średniej pamiętamy żeby dzielenie przez liczbę elementów (iloczyn liczby wierszy i liczby kolumn) wykonywany był w trybie zmiennoprzecinkowym.

    Główną częścią tej funkcji będą dwie zagnieżdżone pętle (podobnie jak w funkcjach generuj_dane i drukuj) przebiegające wszystkie elementy tablicy.

    Funkcja zwraca wartość typu double.

  6. Gdy powyższa funkcja jest gotowa dodajemy jej wywołanie do funkcji main() i sprawdzamy działanie (dla niewielkiej tablicy, na przykład 2 na 2, ale algorytm powinien też zadziałać dla tablicy 1 na 1!).

    Sprawdzenie polega na wydrukowaniu wartości średniej…

  7. Parametrami funkcji generuj_dane, drukuj i wyliczającej średnią całej tablicy powinny być:

    • liczba wierszy (N),

    • liczba kolumn (M),

    • oraz sama tablica (nazwałem ją w punkcie 1 A), czyli jakoś tak:

      ...(int N, int M, int A[N][M])
      

      lub

      ...(int N, int M, int A[][M])
      

      gdyż liczba wierszy może być pominięta.

      (Zamiast trzech kropek jest nazwa funkcji)

  8. Wywołanie tych funkcji będzie wyglądało, mniej więcej, tak:

    ...(N, M, A);
    
    • N — liczba wierszy,
    • M — liczba kolumn,
    • A — nazwa tablicy z danymi,
  9. Na koniec trzeba przygotować dwie funkcje, wyliczające wartość średniej wybranego wiersza/wybranej kolumny. Argumenty tych funkcji będą bardzo podobne jak w przypadku funkcji wyliczającej średnią całej tablicy, ale dodatkowym parametrem powinien być numer wiersza/kolumny:

    ...(int wiersz, int N, int M, int A[][M])
    

    lub

    ...(int kolumna, int N, int M, int A[][M])
    

    Natomiast na kod funkcji złoży się tylko jedna pętla przebiegająca wybrany wiersz lub kolumnę.

    Natomiast wywołanie funkcji musi uwzględniać ten dodatkowy parametr.

  10. Dodajemy wywołania funkcji do main() i sprawdzamy poprawność obliczeń.

  11. Caly czas należy pamiętać o tym, żeby parametry zadeklarowanej funkcji były zgodne z parametrami jej wywołania!


  1. Skorzystanie z funkcjiu malloc wymaga dodania wiersza #include <stdlib.h>↩︎

Poprzedni
Następny