Wstęp do programowania w języku C/Tablice

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania

Tablice jednowymiarowe

W C tablice można inicjować podczas deklaracji.

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Jeśli liczba elementów początkowych jest mniejsza od długości tablicy, wówczas pozostałe elemnty tablicy inicjowane są na 0. Oto przykład inicjacji tablicy zerami.

int a[10] = {0};

Liczba elementów początkowych nie może być większa od rozmiaru tablicy.

Przykład

Należy wczytać liczbę całkowitą dodatnią typu long int i sprawdzić, czy w jej zapisie wszystkie cyfry są różne.

#include <stdio.h>

#define TRUE 1
#define FALSE 0

typedef int Bool;

main()
{
  Bool widziane_cyfry[10] = { 0 };
  int cyfra;
  long int n;

  printf("Podaj liczbe: ");
  scanf("%ld", &n);

  while (n > 0) {
    cyfra = n % 10;
    if ( widziane_cyfry[cyfra] )
      break;
    widziane_cyfry[cyfra] = TRUE;
    n /= 10;
  }

  if ( n > 0 )
    printf("Cyfry sie powatrzaja.\n\n");
  else
    printf("Cyfry nie powtarzaja sie\n\n");
  return 0;
}

Rozważmy teraz następujące zadanie. Niech R będzie dwuargumentową relacją na zbiorze (n jest parametrem zadania). Domknięciem przechodnim relacji R nazywamy relację taką, że para wtedy i tylko wtedy, gdy a = b lub dla pewnego istnieje ciąg elementów z X taki, że . Napisz program, który dla danej relacji R oblicza jej domknięcie przechodnie.

#include <stdio.h>
#define Max_n 10
#define TRUE 1
#define FALSE 0
typedef int Bool;
main()
{
  Bool R[Max_n][Max_n] = { FALSE };
  int i, j, k, n;

  printf("Podaj rozmiar zbioru X (1 <= . <= %d) : ",
                                          Max_n);
  scanf("%d%", &n);

  /* Wczytanie relacji R */
  printf("Podawaj kolejne pary relacji R.\n");
  printf("Para -1 -1 konczy ciag wejsciowy\n");
  printf("Pamietaj, ze relacja jest zdefiniowana\n");
  printf("na zbiorze {0,...,%d\n", n-1);

  scanf("%d %d", &i , &j);
  while ( i != -1 ){
    R[i][j] = TRUE;
    scanf("%d %d", &i , &j);
  }

  /* Wypisanie poczatkowej relacji. */
  printf("\n\nRelacja R\n\n");
  for ( i = 0; i < n; i++){
    for ( j = 0; j < n; j++)
      printf("%d", R[i][j]);
    printf("\n");
  }

  /*Obliczanie domkniecia relacji R*/
  for ( i = 0; i < n; i++ )
    R[i][i] = TRUE;

  for ( k = 0; k < n; k++ )
  /*Nzm.: R[a][b] = TRUE wiw, gdy a=b lub 
          istnieje ciag
          elementow a_0, a_1, ...,a_l taki, ze 
          a_0 = a, a_l = b,
          a_1,...,a_{l-1} naleza do {0,...,k-1} oraz
          R[a_0][a_1] = TRUE,
          R[a_1,a_2] = TRUE,..., 
          R[a_{l-1}][a_l] = TRUE.
  */
    for ( i = 0; i < n; i++ )
      for ( j = 0; j < n; j++ )
        R[i][j] = R[i][j] || ( R[i][k] && R[k][j] );

  /* Wypisanie domkniecia relacji. */
  printf("\n\nDomkniecie relacji R\n\n");
  for ( i = 0; i < n; i++){
    for ( j = 0; j < n; j++)
      printf("%d", R[i][j]);
    printf("\n");
  }

  return 0;
}

Funkcje

Rozważmy program, który wczytuje dwie liczby rzeczywiste i liczy ich średnią.

#include <stdio.h>

main()
{
  double x, y;

  printf("podaj dwie liczby rzeczywiste: ");
  scanf("%lf %lf", &x, &y);

  printf("(%5.2f+%5.2f)/2 = %5.2f\n\n",x,y,(x+y)/2);

  return 0;
}

Oto ten sam program zapisany z użyciem funcji obliczającej średnią.

#include <stdio.h>
double srednia(double x, double y)
{
  return (x+y)/2;
}

main()
{
  double x, y;

  printf("podaj dwie liczby rzeczywiste: ");
  scanf("%lf %lf", &x, &y);

  printf("(%5.2f+%5.2f)/2=%5.2f\n",x,y,srednia(x,y));

  return 0;
}

C nie wymaga definiowania funkcji przed jej wywołaniem. Dobrym zwyczajem jest jednak deklarować funkcję przed miejscem jej wywołania. Tym razem deklaracja funkcji została oddzielona od jej definicji.

#include <stdio.h>
double srednia(double x, double y); 
/* Deklaracja funkcji */
main()
{
  double x, y;

  printf("podaj dwie liczby rzeczywiste: ");
  scanf("%lf %lf", &x, &y);

  printf("(%5.2f+%5.2f)/2=%5.2f\n",x,y,srednia(x,y));

  return 0;
}

double srednia(double x, double y) 
/* Definicja funkcji */
{
  return (x+y)/2;
}

Funkcja w C nie musi zwracać żadnej wartości. Oto funkcja tab, która dostaje na wejściu liczbę całkowitą $n\in [1..10]$ i wypisuje tabliczkę możenia przez $n$. Zwróć uwagę na słówko kluczowe void które oznacza, że funkcja nie zwraca wartości. Taka funkcja nie może być wywoływana jako część wyrażenia. Wywołanie funkcji tab musi mieć postać:\\ tab({\it parametr});\\

void tab(int n)
{
  int i;

  for ( i = 1; i <= 10; i++ )
    printf("%d * %d = %d\n", n, i, n*i);
}

Funkcja też może nie mieć żadnych parametrów, np.

void gwiazdki(void)
{
  printf("*********************");
}

Tak'a funkcję wywułujemy:\\ gwiazdki();\\ Ogólnie definicja funkcji ma postać:\\ {\it typ wartości} nazwa--funkcji ( parametry )\\ \{\\ \hspace{0.5cm}deklaracje\\ \hspace{0.5cm}instrukcje\\ \}\\[0.3cm] Zwróćmy uwagę na różnicę między parametrami i argumentami funkcji. {\it Prametry} występują na poziomie definicji funkcji. Są one ``zmiennymi, którym muszą być przypisane rzeczywiste {\it argumenty} (wyrażenia) podczas wywołania funkcji. W C argumenty są przekazywane {\it przez wartość}: podczas wywołania funkcji obliczana jest wartość każdego argumentu (wyrażenia) i ta wartość jest przypisywane do odpowiedniego parametru. Zmiany wartości parametru podczas obliczeń nie mają wpływu na wartość argumentu. Parametrami mogą być także tablice. W deklaracji funkcji możemy nie specyfikować rozmiaru tablicy. Oto przykład parametru-tablicy:

int sum_tab(int a[], int n)
{
  int i, sum = 0;

  for (i = 0; i < n; i++)
    sum += a[i];

  return sum;
}

Gdy chcemy parametrem uczynić tablicę dwuwymiarową musimy podać liczbę kolumn tablicy.

#define L_kol 10

int sum_tab(int a[][L_kol], int n)
{
  int i, j, sum = 0;

  for (i = 0; i < n; i++)
    for (j = 0; j < n; j++)
      sum += a[i][j];

  return sum;
}

Pamiętajmy, że każda funkcja {\it nie}-void musi zwracać wartość. Instrukcja return ma postać:\\ return {\it wyrażenie};