Przykład podziału na pliki

Podział na pliki

Wyobraźmy sobie sytuację, że mamy duuuży program… duuużo większy niż ten poniżej…
Tak więc wyobraźmy sobie, że program poniżej jest duuużo większy :]

#include <stdio.h>
typedef struct {
	char nazwisko[20];
	int wiek;
} Osoba;
 
void wczytaj(Osoba* s) {
	printf("Podaj nazwisko: ");
	scanf("%s", s->nazwisko);
	printf("Podaj wiek: ");
	scanf("%d", &s->wiek);
}
 
void wyswietl(const Osoba* s) {
	printf("%s ma lat: %d\n", s->nazwisko, s->wiek);
}
 
int main(void) {
	Osoba osoba;
	int klawisz;
	do {
		printf("\n Menu:\n");
		printf("-> 1 - wczytaj dane\n");
		printf("-> 2 - wyswietl dane\n");
		printf("-> 3 - zakoncz program\n");
		printf("Wybieram -> ");
		scanf("%d", &klawisz);
		switch(klawisz)
		{		 
			case 1: wczytaj(&osoba); break;
			case 2: wyswietl(&osoba); break;
		}
	} while(klawisz != 3);
	return 0;
}

W takim przypadku zachodzi potrzeba podzielenia go na pliki. Jak to zrobić? Na przykład tak:

  • plik osoba.h
#ifndef _OSOBA_H
#define _OSOBA_H
	typedef struct {
		char nazwisko[20];
		int wiek;
	} Osoba;
 
	void wczytaj(Osoba* s);
	void wyswietl(const Osoba* s);
#endif
  • plik osoba.c
#include <stdio.h>
#include "osoba.h"
 
void wczytaj(Osoba* s) {
	printf("Podaj nazwisko: ");
	scanf("%s", s->nazwisko);
	printf("Podaj wiek: ");
	scanf("%d", &s->wiek);
}
 
void wyswietl(const Osoba* s) {
	printf("%s ma lat: %d\n", s->nazwisko, s->wiek);
}
  • plik main.c
#include <stdio.h>
#include "osoba.h"
 
int main(void) {
	Osoba osoba;
	int klawisz;
	do {
		printf("\n Menu:\n");
		printf("-> 1 - wczytaj dane\n");
		printf("-> 2 - wyswietl dane\n");
		printf("-> 3 - zakoncz program\n");
		printf("Wybieram -> ");
		scanf("%d", &klawisz);
		switch(klawisz)
		{		 
			case 1: wczytaj(&osoba); break;
			case 2: wyswietl(&osoba); break;
		}
	} while(klawisz != 3);
	return 0;
}

Kompilacja programu podzielonego na pliki

Powyższy program wielomodułowy możemy skompilować:

gcc main.c osoba.c

Jednak w ogólnym przypadku lepsza jest kompilacja równoległa, a potem linkowanie modułów:

gcc osoba.c -o osoba.o
gcc main.c -o main.o
gcc main.o osoba.o -o program

Więcej informacji o procesie kompilacji można znaleźć na stronie laboratorium GCC - proces kompilacji.

Zamiast pisać pojedynczo poszczególne komendy, warto zapoznać się z narzędziem Make, które wspomaga proces budowania wielomodułowego kodu. Make obsługuje złożone zależności pomiędzy plikami źródłowymi, w szczególności gdy zmiany w jednych pociągają rekurencyjnie zmiany w kolejnych.

Make działa zawsze w obrębie katalogu bieżącego i potrzebuje pliku konfiguracyjnego Makefile. Plik ten składa się z szeregu reguł postaci (–> oznacza tabulator!):

cel: prerekwizyty
-->-->polecenia
-->-->polecenia

Legenda:

  • cel - nazwa pliku,
  • prerekwizyty - lista nazw plików,
  • polecenia - polecenia do wykonania

Jak to działa?

  1. make uruchamia tylko pierwszą regułę.
  2. Reguła jest odpalana, gdy data modyfikacji choć jednego prerekwizytu jest późniejsza niż data modyfikacji celu.
  3. Dla każdego prerekwizytu, którego data modyfikacji jest późniejsza niż data modyfikacji celu, rekurencyjnie uruchamiana jest reguła która go definiuje (o ile istnieje).
  4. Po spełnieniu prerekwizytów uruchamiane są polecenia.

Można również wymusić uruchomienie dowolnego celu z pliku Makefile wywołując: make cel.

Niektóre z reguł nie muszą być związane z samą kompilacją, ale czynnościami pomocniczymi np.

clean:
-->-->rm -f *.o program

usuwa pliki powstałe w trakcie kompilacji wraz ze skompilowaną wersją programu.

Przykładowy plik Makefile dla naszego programu może wyglądać następująco:

program: osoba.o osoba.h
		gcc -Wall -ansi -pedantic -lm main.c osoba.o -o program
		@echo program: zbudowane!

osoba.o: osoba.c
		gcc -c -Wall -ansi -pedantic osoba.c

clean:
		rm -f *.o program

Teraz, aby skompilować program wystarczy wydać polecenie make.

Make posiada również zaawansowane mechanizmy, jak np. wzorce reguł. Więcej o tym i innych rzeczach związanych z programem GNU Make można się dowiedzieć na stronie laboratorium dot. GNU Make.

Program z poprzednich zajęć (słownik krzyżówkowy) rozdziel na kilka plików. Stwórz bibliotekę wyszukującą w słowniku (więcej informacji: jak stworzyć bibliotekę).

przyklad_podzialu_na_pliki.txt · ostatnio zmienione: 2011/12/12 16:47 przez krzysiek