Lekcja 4 - Zróbmy sobie prostą bazę danych
Źródła programów zamieszczonych w tej lekcji

Na tej lekcji dowiesz się jak zmieniać kolory w trybie tekstowym, poznasz jakie są operacje logiczne i po co one nam, oraz jak zapisać na dysk plik z tekstem i jak go później wczytać. Prowadzić to będzie do tematu tej lekcji: prostej bazy danych - ulubionego tematu znęcających się na studentach profesorów :)


Procedura TextColor

Składnia: TextColor(kolor:byte); CRT

Zmienia kolor wyświetlania tekstu, możliwe do wybrania jest 16 kolorów:

Black         =  0  - czarny
Blue          =  1  - niebieski
Green         =  2  - zielony
Cyan          =  3  - turkusowy
Red           =  4  - czerwony
Magenta       =  5  - karmazynowy
Brown         =  6  - brązowy
LightGray     =  7  - jasnoszary
DarkGray      =  8  - ciemnoszary
LightBlue     =  9  - jasnoniebieski
LightGreen    = 10  - jasnozielony
LightCyan     = 11  - jasnoturkusowy
LightRed      = 12  - jasnoczerwony
LightMagenta  = 13  - jasnokarmazynowy
Yellow        = 14  - żółty
White         = 15  - biały
Można wykonać również kolor migoczący, uzyskuje się poprzez dodanie do wybranego koloru liczby 128 ( Blink ) np.
Uses CRT;

Begin
  TextColor(Blue);
  Write('Napis Niebieski');
  TextColor(8);
  Write('Napis Ciemnoszary');
  TextColor(Red+Blink);
  Write('Napis Czerwony mrugajacy');
  TextColor(15+128);            { TextColor(143); }
  Write('Napis Biały mrugający');
End.


Procedura TextBackGround

Składnia: TextBackGround(kolor:byte); CRT

Zmienia kolor tła wyświetlanego tekstu, możliwe do wybrania jest 8 kolorów:

Black         =  0  - czarny
Blue          =  1  - niebieski
Green         =  2  - zielony
Cyan          =  3  - turkusowy
Red           =  4  - czerwony
Magenta       =  5  - karmazynowy
Brown         =  6  - brązowy
LightGray     =  7  - jasnoszary
Przykład:
Uses CRT;

Begin
  TextBackGround(Blue);
  Write('Napis na niebieskim tle');
  TextBackGround(4);
  Write('Napis na czerwonym tle');
End.
Aby zmienić kolor podkładu dla całego ekranu należy wykonać tą procedurę i wyczyścić ekran np.
Uses CRT;

Begin
  TextBackGround(Green);
  ClrScr;
  Write('Oto napis na całym zielonym ekranie :)');
End.


Operator AND

Mówiąc po polsku jest to operator "I" i stosuje się tam gdzie są potrzebne spełnione dwa lub więcej warunków np. w IF..THEN.. albo w pętli REPEAT..UNTIL, warunki muszą być podane w nawiasach np.

Var
  a1,a2,a3:byte;

Begin
  Write('Podaj 1 liczbe : ');
  ReadLn(a1);
  Write('Podaj 2 liczbe : ');
  ReadLn(a2);
  Write('Podaj 3 liczbe : ');
  ReadLn(a3);
  If (a1>a2) AND (a1>a3) Then WriteLn('Liczba ',a1,' jest najwieksza z podanych');
  If (a2>a1) AND (a2>a3) Then WriteLn('Liczba ',a2,' jest najwieksza z podanych');
  If (a3>a1) AND (a3>a2) Then WriteLn('Liczba ',a3,' jest najwieksza z podanych');
End.
Program sprawdza która z podanych trzech liczb jest największa i wyświetla ją na ekranie.


Operator OR

Zanim dalej zaczniesz czytać, zaznajom się z nieopisaną wcześniej funkcją: ReadKey.
Mówiąc po polsku jest to operator "LUB" i stosuje się tam gdzie jest potrzebny spełniony co najmniej jeden z dwóch lub więcej warunków, stosuje się go np. w IF..THEN.. albo w pętli REPEAT..UNTIL, warunki te muszą być podane w nawiasach np.

Uses CRT;

Var
  c:char;

Begin
  Write('Czy na pewno ? (T/N) :');
  Repeat
    c:=ReadKey;
  Until (c='t') or (c='n');
End.
Program ten czeka na wciśnięcie klawisza "t" lub "n", ale jest niedoskonały ponieważ gdy wciśniemy duży klawisz "T" lub "N" to wtedy nie zadziała. Rozwiązaniem tego jest dodanie obsługi tych klawiszy, poprawiony program wygląda więc tak:
Uses CRT;

Var
  c:char;

Begin
  Write('Czy na pewno ? (T/N) :');
  Repeat
    c:=ReadKey;
  Until (c='t') or (c='T') or (c='n') or (c='N');
End.


Funkcja UpCase

Składnia: duza:=UpCase(literka:char):char;

Funkcja zamienia małą literkę na dużą, w przypadku podania już dużej litery lub cyfry nie następuje zamiana. np: UpCase('a') = 'A', UpCase('B') = 'B', UpCase('6') = '6'. Tak więc program z opisanego operatora OR można zapisać tak:

Uses CRT;

Var
  c:char;

Begin
  Write('Czy na pewno ? (T/N) :');
  Repeat
    c:=UpCase(ReadKey);                 {1}
  Until (c='T') or (c='N');             {2}
End.
{1} Po wciśnięciu jakiegokolwiek znaku jest on zamieniany na dużą literę i podstawiany do zmiennej C
{2} Sprawdzenie czy zmienna C zawiera dużą literę T lub N


Procedura Assign

Składnia: Assign(var Plik:text; nazwapliku:string);

Procedura kojarzy identyfikator "Plik" z plikiem dyskowym o nazwie "nazwapliku" w której może mieścić się jeszcze ścieżka dostępu. Bardziej jasne stanie to się przy następnych procedurach "Reset" i "Rewrite".


Procedura Close

Składnia: Close(var Plik:text);

Zamyka plik otwarty uprzednio przez "Reset", "Append" lub "Rewrite". Zaraz zobaczysz jak to się stosuje.


Procedura Reset

Składnia: Reset(var Plik:text);

Otwiera plik "Plik" skojarzony uprzednio przez "Assign". Od tego momentu poprzez identyfikator "Plik" będzie można czytać dane poprzez Read i ReadLn z dysku np.

Var
 przyklad:text;                         {1}
 linia:string;

Begin
  Assign(przyklad,'C:\AUTOEXEC.BAT');   {2}
  Reset(przyklad);                      {3}
  ReadLn(przyklad,linia);               {4}
  WriteLn(linia);                       {5}
  Close(przyklad);                      {6}
End.
Program otwiera plik "C:\AUTOEXEC.BAT" i wyświetla z niego pierwszą linię. W kolejnych linijkach program wykonuje:
{1} Deklarujemy zmienną "przyklad" jako typ TEXT (plik textowy)
{2} Kojarzymy zmienną "przyklad" z plikiem "C:\AUTOEXEC.BAT"
{3} Otwieramy plik "przyklad" do odczytu
{4} Wczytujemy kolejną linię ( ponieważ nie czytaliśmy z niego wcześniej czyta pierwszą ) z pliku "przyklad" i wstawiamy ją do zmiennej "linia" typu String
{5} Wyświetlamy zmienną "linia"
{6} Zamykamy plik


Funkcja EOF

Składnia: EOF(var Plik:text):boolean

Jest to funkcja zwracająca dwie wartości: prawdę (TRUE) lub fałsz (FALSE) i określa czy plik "PLIK" znajduje się w pozycji końcowej ( FALSE - są w nim jeszcze jakieś nieprzeczytane dane, TRUE - tak to koniec pliku nic więcej w nim nie ma ). np:

Var
 przyklad:text;
 linia:string;

Begin
  Assign(przyklad,'C:\AUTOEXEC.BAT');
  Reset(przyklad);
  REPEAT                        {1}
    ReadLn(przyklad,linia);     {2}
    WriteLn(linia);             {3}
  UNTIL EOF(przyklad);          {4}
  Close(przyklad);
End.
Program podobnie jak poprzednio otwiera plik ale odczytuje z niego wszystkie linie zaczynając od pierwszej a kończąc na ostatniej.
{1} zacznij pętlę
{2} odczytaj kolejną linię z pliku "przyklad"
{3} wyświetl ją na ekranie
{4} sprawdź czy to już koniec pliku, jeśli nie to powróć do {2} i wyświetl kolejną linię, a jeśli tak to opuść pętlę.


Procedura Rewrite

Składnia: Rewrite(var Plik:text);

Procedura ta tworzy nowy plik o nazwie skojarzonej ze zmienną "Plik" i udostępnia go do zapisu w nim danych ( poprzez Write i WriteLn ). UWAGA ! Jeżeli użyjesz tej procedury na istniejącym już pliku zostanie on usunięty i na jego miejsce utworzony nowy np.

Var
 przyklad:text;                                                         {1}

Begin
  Assign(przyklad,'C:\PLIKTEST.TXT');                                   {2}
  Rewrite(przyklad);                                                    {3}
  WriteLn(przyklad,'Taki sobie głupi napis zapiszemy w pliku :)');      {4}
  Close(przyklad);                                                      {5}
End.
{1} definiujemy zmienną "przyklad" jako typ TEXT
{2} kojarzymy zmienną "przyklad" z plikiem "C:\PLIKTEST.TXT" ale nie musi on wcale istnieć ponieważ:
{3} tworzymy plik i otwieramy go do zapisu
{4} wpisujemy do pliku linię z tekstem
{5} zamykamy plik

UWAGA ! Jeżeli nie zamkniesz pliku i opuścisz program to jakiś fragment ostatnio zapisywanych danych ulegnie skasowaniu !!!!! Czasami może się zdarzyć że plik nie został do końca zapisany więc w pierwszej kolejności sprawdź czy został on prawidłowo zamknięty !


Zaczynamy pisać prostą bazę danych

Napiszemy sobie prostą bazę osobową czyli wystarczy: imię, nazwisko i telefon. Zaczniemy pisanie krok po kroku od podstaw, tak abyś wiedział skąd i dlaczego się biorą te dziwne rzeczy, a potem z czasem będziemy ją modyfikować.

Oki zrobimy najpierw program na jedną osobę tak aby ją można wprowadzić i wyświetlić:

Uses CRT;

Var
  Imie,nazwisko,telefon:string;
  c,c2:char;

PROCEDURE Wprowadz;
Begin
  ClrScr;
  Write('Imie : ');
  ReadLn(imie);
  Write('Nazwisko : ');
  ReadLn(nazwisko);
  Write('Telefon : ');
  ReadLn(telefon);
End;

PROCEDURE Wyswietl;
Begin
  ClrScr;
  WriteLn('Imie     : ',imie);
  WriteLn('Nazwisko : ',nazwisko);
  WriteLn('Telefon  : ',telefon);
  WriteLn;
  Write('Wcisnij jakis klawisz...');
  c2:=readkey;
End;

Begin
  Repeat
  ClrScr;
  Write('1. Nowy wpis    2. Wyswietlenie wpisu     3.Koniec programu    : ');
    Repeat
      c:=readkey;
    Until (c='1') OR (c='2') OR (c='3');
  If c='1' Then Wprowadz;
  If c='2' Then Wyswietl;
  Until c='3';
End.
To już powinieneś rozumieć więc nie będę tłumaczył prosty program do wprowadzenia i wyświetlenia tylko 3 zmiennych, tylko co to za baza danych na jedną osobę ? Właśnie teraz przychodzą nam z pomocą tablice które tak wałkowałem na poprzedniej lekcji zobacz teraz jak zmienił się nasz program:
Uses CRT;

Var
  Imie,nazwisko,telefon:array[1..30] of string;                 {1}
  c,c2:char;
  iloscosob:byte;                                               {2}
  t1:byte;                                                      {3}

PROCEDURE Wprowadz;
Begin
  ClrScr;
  Iloscosob:=iloscosob+1;                                       {4}
  Write('Imie : ');
  ReadLn( imie[iloscosob] );                                    {5}
  Write('Nazwisko : ');
  ReadLn( nazwisko[iloscosob] );                                {6}
  Write('Telefon : ');
  ReadLn( telefon[iloscosob] );                                 {7}
End;

PROCEDURE Wyswietl;
Begin
  ClrScr;
  Write('Numer wpisu ? (1..', iloscosob ,') :');                {8}
  ReadLn(t1);                                                   {9}
  WriteLn('Imie     : ',imie[t1] );                             {10}
  WriteLn('Nazwisko : ',nazwisko[t1] );                         {11}
  WriteLn('Telefon  : ',telefon[t1] );                          {12}
  WriteLn;
  Write('Wcisnij jakis klawisz...');
  c2:=readkey;
End;

Begin
  Iloscosob:=0;                                                 {13}
  Repeat
  ClrScr;
  Write('1. Nowy wpis    2. Wyswietlenie wpisu     3.Koniec programu    : ');
    Repeat
      c:=readkey;
    Until (c='1') OR (c='2') OR (c='3');
  If c='1' Then Wprowadz;
  If c='2' Then Wyswietl;
  Until c='3';
End.
Jak widzisz linijek doszło niewiele a ilość wpisów zwiększona została do 30. Teraz opiszę co się zmieniło:

Deklaracje:
{1} zmodyfikowałem 3 zmienne z pojedynczych na tablice
{2} dodałem zmienną "iloscosob" określającą ile mamy wpisów w bazie
{3} dodałem zmienną pomocniczą "t1" która będzie nam później na moment potrzebna

Główny program:
{13} wyzerowałem zmienną "iloscosob" ponieważ nie mamy jeszcze żadnego wpisu

Procedury:
{4} ponieważ procedura ma za zadanie dopisywanie nowych danych musimy zwiększyć zmienną "iloscosob" będącą równocześnie ilością wpisów w bazie o jeden
{5} {6} {7} wprowadzenie danych do zmiennych tablicowych do elementów o numerze "iloscosob"
{8} wyświetlenie informacji o ilości dostępnych do uzyskania danych
{9} wprowadzenie zmiennej pomocniczej będącej numerem rekordu danych do wyświetlenia
{10} {11} {12} wyświetlenie danych z tablic o elementach numer "t1"

Do tamtego programu dodamy jeszcze teraz dwie procedury do zapisu i odczytu z dysku, dwie procedury w tym listingu wyciąłem, aby nie przeszkadzały w studiowaniu zmian w programie ale oczywiście muszą się one tam znajdować ( w
listingach do ściągnięcia nie są one wykasowane ) :
Uses CRT;

Var
  Imie,nazwisko,telefon:array[1..30] of string;
  c,c2:char;
  iloscosob:byte;
  t1:byte;
  plik:text;                                            {1}

PROCEDURE Wprowadz; { taka jak poprzednio }

[...]

PROCEDURE Wyswietl; { taka jak poprzednio }

[...]

PROCEDURE Zapisz;                                       {2}
Begin
  Assign(plik,'BAZA.DAN');                              {3}
  ReWrite(plik);                                        {4}
  WriteLn(plik,iloscosob);                              {5}
  t1:=0;                                                {6}
  Repeat
    t1:=t1+1;                                           {7}
    WriteLn(plik,imie[t1] );                            {8}
    WriteLn(plik,nazwisko[t1] );                        {9}
    WriteLn(plik,telefon[t1] );                         {10}
  Until t1=iloscosob;                                   {11}
  Close(plik);                                          {12}
End;

PROCEDURE Czytaj;                                       {13}
Begin
  Assign(plik,'BAZA.DAN');                              {14}
  Reset(plik);                                          {15}
  ReadLn(plik,iloscosob);                               {16}
  t1:=0;                                                {17}
  Repeat
    t1:=t1+1;                                           {18}
    ReadLn(plik,imie[t1] );                             {19}
    ReadLn(plik,nazwisko[t1] );                         {20}
    ReadLn(plik,telefon[t1] );                          {21}
  Until t1=iloscosob;                                   {22}
  Close(plik);                                          {23}
End;

Begin
  Iloscosob:=0;
  Repeat
  ClrScr;
  WriteLn('1. Nowy wpis');                              {24}
  WriteLn('2. Wyswietlenie wpisu');                     {25}
  WriteLn('3. Odczyt z pliku');                         {26}
  WriteLn('4. Zapis do pliku');                         {27}
  WriteLn('5. Koniec programu');                        {28}
    Repeat
      c:=readkey;
    Until (c>='1') AND (c<='5');                        {29}
  If c='1' Then Wprowadz;
  If c='2' Then Wyswietl;
  If c='3' Then Czytaj;                                 {30}
  If c='4' Then Zapisz;                                 {31}
  Until c='5';                                          {32}
End.
{1} Definiujemy zmienną PLIK jako typ TEXT
{2} Tworzymy nową procedurę ZAPISZ która będzie odpowiedzialna za zapis utworzonej bazy na dysku
{3-4} Otwieramy do zapisu plik o nazwie 'BAZA.DAN'
{5} Zapisujemy ilość wpisów na dysku
{6} Zerujmy zmienną pomocniczą T1 będzie ona potrzebna do odliczania ilości zapisanych wpisów
{7} Zwiększamy zmienną T1 o jeden
{8-10} Zapisujemy IMIE NAZWISKO i TELEFON osoby numer T1
{11} Jeżeli zapisane zostało już "ILOSCOSOB" wpisów ( tzn. wszystkie ) to przejdź dalej jeśli nie wróć do {18}
{12} Zamykamy plik, gdybyśmy tego nie zrobili to stracilibyśmy część danych
{13} Tworzymy nową procedurę CZYTAJ która będzie odpowiedzialna za odczytanie bazy z dysku
{14-15} Otwieramy do odczytu plik o nazwie 'BAZA.DAN'
{16} Odczytujemy pierwszą linię będącą liczbą z informacją o ilości wpisów
{17} Zerujmy zmienną pomocniczą T1 będzie ona potrzebna do odliczania ilości odczytanych wpisów
{18} Zwiększamy zmienną T1 o jeden
{19-21} Odczytujemy IMIE NAZWISKO i TELEFON osoby numer T1
{22} Jeżeli odczytane zostało już "ILOSCOSOB" wpisów ( tzn. wszystkie ) to przejdź dalej jeśli nie wróć do {7}
{23} Zamykamy plik
{24-28} Nowe ulepszone menu :)
{29} Czekaj na wciśnięcie 1,2,3,4 lub 5
{30-31} Wywołaj nowe funkcje ( odczyt i zapis )
{32} Jeżeli wciśnięty został klawisz 5 to opuść program


I oto mamy najprostszą bazę danych, teraz możesz ją już udoskonalać, proponuję takie rzeczy:
  • przy wyświetlaniu danych dodać obsługę klawiszy do wyświetlania następnego/poprzedniego/pierwszego/ostatniego wpisu
  • opcję: nowa baza danych
  • możliwość zmiany nazwy zapisywanego i odczytywanego pliku
  • zabezpieczenie przed wyświetleniem wpisu nr X jeżeli taki nie istnieje

Na tym zakończmy naszą czwartą lekcję, jak widzisz nasza prosta baza danych wcale nie była aż taka prosta w pisaniu :)

Powrot na Strone Glowna