-
Notifications
You must be signed in to change notification settings - Fork 0
2. Programy modularne
Często zdarza się tak, że chcemy wykorzystać ten sam kawałek kodu w dwóch różnych programach (np. ten sam algorytm w dwóch zadaniach czy wspólną dla wszystkich programów funkcję). Duży program pisany jako jedna całość jest nieczytelny, przez co łatwiej w nim także popełnić błędy. Dlatego programy dzieli się na części (moduły). Modułem będziemy nazywać fragment programu kompilowany jako jeden plik. Dodatkową zaletą dzielenia programu na moduły jest fakt, że moduły mogą być kompilowane niezależnie. Jeśli zatem dokonamy zmian w jednym z modułów nie będziemy musieli rekompilować całości, a tylko ten jeden plik.
Załóżmy dla przykładu, że główny plik programu (zawierający funkcję main) nazywa się main.c
. Będzie wykorzystywał on funkcję foo()
, którą chcemy umieścić w module znajdującym się w pliku func.c
. Kompilator przy przetwarzaniu pliku main.c
musi wiedzieć jakie argumenty przyjmuje funkcja foo()
i jakiego typu wartość zwraca. Musimy więc gdzieś umieścić deklarację tej funkcji: najlepiej zrobić to w pliku nagłówkowym func.h
(o tej samej nazwie co plik źródłowy zawierający definicję tej funkcji).
Zawartość pliku main.c może być zatem następująca:
#include <stdio.h> // załączamy bibliotekę standardową, aby móc skorzystać z funkcji printf()
#include "func.h" // załączamy plik nagłówkowy dla funkcji foo() aby móc z niej skorzystać w dalszej części programu
int main(void)
{
float x = 0.5;
printf("Wartość funkcji foo w punkcie %f wynosi: %f\n", x, foo(x));
return 0;
}
Zauważmy, że nazwa pliku nagłówkowego z biblioteki standardowej został umieszczony w nawiasach trójkątnych co oznacza, że ma być poszukiwany na początku w "miejscach standardowych", zaś nazwa naszego (prywatnego) pliku nagłówkowego w cudzysłowach, co oznacza, że ma być poszukiwany najpierw w bieżącym katalogu (czyli w tym samym co plik main.c
).
Zobaczmy teraz jak wygląda zawartość pliku nagłówkowego (deklarującego) func.h
. Każdy plik nagłówkowy powinien być napisany tak, by można go było kilkakrotnie włączać do dowolnego modułu i w dowolnym miejscu. Można to osiągnąć stosując odpowiednie dyrektywy preprocesora, definiując odpowiednią stałą (najlepiej składającą się z nazwy pliku i rozszerzenia, rozdzielonych podkreśleniem) i sprawdzając na początku pliku czy została już ona zdefiniowana (czyli czy plik ten został już włączony).
#ifndef FUNC_H // jeśli zmienna FUNC_H nie została zdefiniowana
#define FUNC_H // zdefiniuj zmienną FUNC_H
float foo(float x);
#endif // FUNC_H_INCLUDED -> zamknięcie instrukcji warunkowej otwartej przez dyrektywę ifndef
Pozostaje przedstawić zawartość pliku źródłowego func.c
. Aby uniknąć sytuacji gdy deklaracja funkcji foo()
w pliku nagłówkowym func.h
jest niezgodna z jej definicją w pliku func.c
do każdego modułu włączamy jego plik definicyjny.
#include "func.h"
float foo(float x)
{
return 0.5*x*x;
}
W systemach Windows znajdziemy interpretator poleceń wpisywanych z klawiatury. Jest to program cmd.exe
znajdujący się w katalogu C:\WinNT\system32
. Korzystając z tego programu może wydawać polecenia systemu DOS/Windows jak również uruchamiać programy. Podobnie jest w systemach UNIX/Linux: mamy do dyspozycji okienko terminala, gdzie możemy wydawać polecenia systemu oraz uruchamiać programy.
Uruchamiając program z linii komend możemy podać parametry które zostaną przekazane do wykonywanego programu. Na przykład jeśli nasz program nazywający się WypiszArgumentyWierszaPolecen.c
ma wyświetlić dowolną liczbę znaków podanych w terminalu to wywołując polecenie
> suma.c 6 18 24
system operacyjny przekaże do programu WypiszArgumentyWierszaPolecen.c
parametry: 6, 18 i 24. Pozostaje pytanie, jak pobrać i odczytać te parametry w naszym programie pisanym w C? Czy można pobrać wszystkie parametry jakie są przekazywane do programu nie wiedząc ile tych parametrów jest?
Odpowiedź na te pytania możemy znaleźć w poniższym programie. Pobiera on wszystkie parametry przekazane do naszego programu i wyświetla je na ekranie. Główną role pełni tu funkcja WypiszArgumentyWierszaPolecen()
.
#include <stdio.h>
void WypiszArgumentyWierszaPolecen (int argc, char *argv[]);
int main (int argc, char *argv[]) {
WypiszArgumentyWierszaPolecen(argc, argv);
getchar(); //oczekiwanie na dowolny znak (wcisniecie klawisza) aby zakonczyc dzialanie programu
}
void WypiszArgumentyWierszaPolecen (int argc, char *argv[]) {
printf("Liczba argumentow w wierszu polecen: %d\n", argc);
int i;
for(i=0; i<argc; ++i){
printf("Element numer %d wiersza polecen ma wartosc: %c",i, argv[i]);
}
}