Wstęp do programowania w języku C/Tablice
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ą 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(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ą funkcję wywułujemy:
gwiazdki();
Ogólnie definicja funkcji ma postać:
typ wartości nazwa--funkcji ( parametry ) { deklaracje instrukcje }
Zwróćmy uwagę na różnicę między parametrami i argumentami funkcji. Prametry występują na poziomie definicji funkcji. Są one "zmiennymi", którym muszą być przypisane rzeczywiste argumenty (wyrażenia) podczas wywołania funkcji. W C argumenty są przekazywane 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 nie-void musi zwracać wartość. Instrukcja return ma postać:
return wyrażenie;