background image

Artur Poznański

PROGRAMOWANIE

W JĘZYKU C 

DLA CHĘTNYCH

Kraków 1998

background image

Część 1

1. WSTĘP

Programowanie w każdym języku przypomina budowanie domku z cegieł. Czasem zamiast domku powstaje olbrzymi 

gmach, a budowniczych jest cała masa. Mogą oni pracować nawet całymi latami nad jakąś budową. Zwykle nie tworzy 

się programów od zera tylko korzysta z tego co się zrobiło wcześniej i jedynie to ulepsza, poprawia oraz dodaje nowe 

elementy. Aby zacząć budować my również będziemy musieli poznać cegiełki jakie dany język posiada. Bez wątpienia 

najpopularniejszym obecnie jest język C i to nim właśnie się zajmiemy. Moim zdaniem aby umieć programować, wcale 

nie jest potrzebna znajomość fachowego słownictwa jakie z pewnością odstrasza wielu chętnych tej zabawy. Dlatego w 

mojej książce nie będzie takich mądrych określeń jak identyfikatory, operatory czy dyrektywy preprocesora. Mnie na 

początku  skutecznie  zniechęcały  do  czegokolwiek.  Nie  wymagam   od  czytelników   znajomości   programowania   ani 

języka angielskiego czy też wyższej matematyki Jedyne czego wymagam to chęci, cierpliwości i prób zrozumienia tego 

o  czym  piszę.  Zakładam, że Ty czytelniku masz  program   umożliwiający  tworzenie  innych programów  czyli   tzw. 

kompilator. Ja korzystałem z kompilatora o nazwie "Borland C++" wersja 3.1 ale może być oczywiście inny byleby był 

języka C. To chyba na tyle uwag wstępnych. Myślę, że niektórzy mogą mi zarzucić brak fachowości w moich opisach 

ale   ten  tekst   kierowany  jest   do  ludzi,  którzy  nigdy  nie  programowali  w  żadnym  języku,  a  marzy  im  się   pisanie 

świetnych gier lub tylko lepsze poznanie komputera. Nie chcą oni studiować opasłych tomów, gdzie zaczyna się od 

rzeczy bardzo trudnych i przechodzi do jeszcze trudniejszych. Opis języka nie jest kompletny i nie zamierza wcale taki 

być. Po prostu to jest książka o programowaniu nie zaś o samym języku C. Na koniec mała uwaga: Programowanie jest 

przyjemne pod warunkiem, że nie siedzi się nad nim całymi godzinami, dzień w dzień. Pamiętaj, że świat jest piękny, a 

komputer nie zastąpi jazdy na rowerze czy wycieczki w góry lub nad morze.

Miłej lektury życzy wszystkim autor.

2. POZNAJMY NARZĘDZIA

Programowanie polega na pisaniu programu. Wspomniałem już, że potrzebny nam jest oprócz samego komputera 

jeszcze pewien program zwany kompilatorem. Kompilator jak to ktoś poetycko napisał, tłumaczy nasze bazgroły i 

wypociny na język zrozumiały dla komputera. Tą czynność zwie się kompilowaniem i trwa naprawdę bardzo krótko. 

Metoda jest taka: wpierw piszemy program, potem go kompilujemy, a jak nam wyskoczą błędy to je poprawiamy i 

znowu kompilujemy, aż do skutku. Obecnie kompilatory są na tyle mądre, że mają własny edytor. Program przed 

kompilacją to tak zwany kod źródłowy a po kompilacji kod wynikowy.

W kompilatorach "Borland C++" i "Turbo C++" robi się to tak. Tworzymy plik (F3), najlepiej niech ma rozszerzenie .c . 

Następnie piszemy instrukcje w tym pliku. Potem naciskamy Alt-F9 co powoduje kompilację. Jeśli wszystko jest OK, 

to powstaje nam plik o rozszerzeniu .exe będący programem. Uruchamianie programu w kompilatorze to Ctrl-F9. Żeby 

zobaczyć efekt działania zwykle wciskamy Alt-F5 który chowa okna i pokazuje to co jest pod spodem. Ważne aby 

często zapisywać sobie naszą pracę (F2) najlepiej do kilku plików pod różnymi nazwami (opcja Save as..). Uchroni to 

nas przed pisaniem wszystkiego od nowa np. w razie braku prądu. Z kompilatora wychodzimy kombinacją Alt-X. Są to 

jedynie najważniejsze opcje, lecz na początek powinny wystarczyć. Jeśli masz inny kompilator, to musisz dowiedzieć 

się jak się kompiluje  (z książek lub lepiej spytać kogoś). System UNIX ma również wbudowany kompilator C. Jednak 

nie ma on edytora z okienkami i w ogóle jest zupełnie inny. Opisy kompilatorów jednak wykraczają poza ramy tej 

background image

książki. Mamy już narzędzia, możemy tworzyć arcydzieła. Zrób może wpierw tak. Utwórz plik o nazwie proba.c (z 

polskimi literkami są zawsze problemy). Napisz w nim linijkę 

void main(){}

i spróbuj ją skompilować. Na razie nie musisz wiedzieć co to znaczy i co to robi. Wyjaśnię tylko, że jest to najmniejszy 

program   napisany   w   języku   C.   Nie   robi   on   zupełnie   nic   z   wyjątkiem   tego,   że   da   się   go   skompilować   a   potem 

uruchomić. W tym samym katalogu powinien Ci powstać plik o nazwie proba.exe. U mnie plik proba.c ma 14 bajtów 

a  proba.exe  ma 6 165 bajtów (zauważ, że to 400 razy więcej). Jednak cóż to jest w dzisiejszych czasach 6 kb. To 

naprawdę bardzo mało. Wniosek jest taki, kod wynikowy jest zwykle większy od   źródłowego (przynajmniej gdy 

piszemy   małe   programy).   Powstanie   tam   także   plik  proba.obj,   który   nie   jest   do   niczego   potrzebny   i   można   go 

spokojnie skasować. Można powiedzieć, że przed chwilą napisałeś pierwszy program. Moje gratulacje !!! Proponuję 

abyś przećwiczył na nim kompilowanie, uruchamianie, zapisywanie pod inną nazwą. Zrób też kilka błędów i zobacz co 

się stanie. Nie bój się, gdyż tylko pokażą się komunikaty, gdzie kompilator wykrył błąd. Zwróć uwagę na to, że 

mógłbyś ten program napisać tak

   void

main (

)

{

}

Jednak byłby on bardzo nieczytelny. My będziemy pisać tak aby każdy nawias { i } były w osobnym wierszu. 

3. NIC NIE ROBI

Jeszcze nic nie robi, ale wiele się można na nim nauczyć. Ostatecznie powinien wyglądać tak:

Przykład 1 – ap1.c

void main()

{

}

Jest to nasza pierwsza cegiełka. Chyba najważniejsza, więc teraz kilka słów wyjaśnienia. Jeśli za wyrazem są nawiasy 

okrągłe ( i ) znaczy to, że jest to funkcja. Funkcja to mówiąc ogólnie wyraz będący jakąś czynnością komputera. Każdy 

program zaczyna się od funkcji main. Jest to obowiązkowy element, jakby fundament, na którym stoi reszta. Instrukcje 

dla komputera wykonywane są z góry na dół, zatem { oznacza początek zaś } oznacza koniec. Na razie nie musisz 

wiedzieć co to void. Dowiesz się w swoim czasie.

4. KOMENTARZE

Komentarz to cegiełka nieobowiązkowa lecz niezmiernie użyteczna. Kompilator nie widzi komentarzy. Zupełnie je 

pomija. Jednak dla nas są nieocenione, zwłaszcza jak chcemy wrócić do jakiegoś programu po pewnym czasie.

Przykład 2 – ap2.c

void main()

{

/* początek programu */

/* tu będą instrukcje dla komputera */

}

/* koniec programu */

Komentarze piszemy pomiędzy znakami /* i */ . W komentarzu nie może być drugiego komentarza. Będę je co jakiś 

czas stosował, bo są bardzo pomocne.

background image

5. WITAJ MISTRZU

Przydało by się by następny program już coś robił. Będzie wypisywał na ekranie tekst. (Przypominam, że Alt-F5 chowa 

okna i pokazuje efekt działania programu)

Przykład 3 – ap3.c

#include <stdio.h>

void main()

{

  puts("Witaj mistrzu");

}

Wyjaśniam  nowe  elementy.  Funkcja  puts  wyświetla  to co  podamy  jej  w  nawiasie. Jest   to  jedna  cegiełka  będąca 

pojedynczą instrukcją dla komputera. Pamiętaj, że każda instrukcja kończy średnikiem. Zastanawiasz się pewnie co jest 

w  pierwszej  linii. Tak jak cegły gromadzone  są  w magazynach, tak wszystkie  funkcje gromadzone  są w plikach 

zwanych bibliotekami. Funkcja puts jest w bibliotece o nazwie stdio.h. Musieliśmy kazać kompilatorowi ją dołączyć. 

Inaczej nie rozpoznał by tej funkcji i podałby   błąd. Spróbuj zrobić z pierwszej linii komentarz  /* #include 

<stdio.h> */ a sam się przekonasz, że czegoś mu będzie brakować.

6. WYMAZUJE EKRAN I CZEKA NA KLAWISZ

W poprzednim programie mieliśmy jedną instrukcję wewnątrz funkcji. Takich instrukcji może być wiele (nawet setki i 

tysiące).

Przykład 4 – ap4.c

#include <stdio.h>

void main()

{

  puts("Witaj");

  puts("mistrzu");

}

Tu  mamy  przykład  dwóch  takich  samych  instrukcji.  Zauważ,  że  funkcja  puts  przenosi   kursor  do  następnej   linii. 

Przydałoby   się   gdyby   to   co   napiszemy   nie   chowało   się   od   razu.   Ponadto   niech   napis   ekran   zostanie   ładnie 

wyczyszczony ze śmieci jakie tam zostały.

Przykład 5 – ap5.c

#include <stdio.h>

#include <conio.h>

void main()

{

  clrscr(); /* czyszczenie ekranu */

  puts("Witaj mistrzu");

  getch(); /* czekanie na dowolny klawisz */

}

Dodałem trzy nowe elementy: funkcje  clrscr  i  getch  i jeszcze jeden plik z biblioteką. Funkcja  clrscr  czyści ekran i 

ustawia kursor w lewym górnym rogu ekranu. Funkcja  getch  czeka na naciśnięcie jakiegoś klawisza. Obie funkcje 

znajdują się w bibliotece conio.h .

background image

7. USTAW  MI KURSOR

Powiem teraz o kolejnej rzeczy. Powiedzmy, że chcemy nasz napis umieścić na środku ekranu.

przykład 6 – ap6.c

#include <stdio.h>

#include <conio.h>

void main()

{

  clrscr(); /* czyszczenie ekranu */

  puts("\n\n\n\n\n\n\n\n\n\n\n\n\t\t\t\tWitaj mistrzu");

  getch(); /* czekanie na dowolny klawisz */

}

Pewnie widać różnicę. Dodałem dwanaście razy \n i cztery razy \t. Symbol \n powoduje przejście do następnej linii, zaś 

\t działa jak tabulator. Spróbuj pozmieniać ilość tych symboli np. dodaj jeden między dwa wyrazy i obejrzyj efekt. Jest 

jednak prostszy i lepszy sposób na wyświetlenie napisu na środku.

Przykład 7 – ap7.c

#include <stdio.h>

#include <conio.h>

void main()

{

  clrscr();

  gotoxy(33,13);

/* ustawienie kursora */

  puts("Witaj mistrzu");

  getch();

}

Zamiast tych dziwnych znaczków użyliśmy funkcji gotoxy, która ustawia kursor na wybranej wysokości i szerokości. 

W naszym przypadku kursor zostanie przeniesiony 33 pozycje w prawo i 13 w dół. Ta funkcja też znajduje się w 

bibliotece conio.h.

8. WŁASNA FUNKCJA

Powiedzmy, że mamy takie zadanie. Niech jedno słowo będzie w lewym górnym rogu ekranu, a drugie w prawym 

dolnym.

Przykład 8 – ap8.c

#include <stdio.h>

#include <conio.h>

void main()

{

  clrscr();

  gotoxy(5,2);

  puts("Witaj");

  gotoxy(65,24);

  puts("mistrzu");

  getch();

background image

}

Nie ma tu nic nowego. Wszystko działa, jednak można by połączyć dwie powtarzające się funkcje w jedną własną o 

nazwie pisz. Poniższy program działa identycznie, jednak zbudowany jest  nieco inaczej.

Przykład 9 – ap9.c

#include <stdio.h>

#include <conio.h>

/* poniżej jest nasza funkcja o nazwie pisz */

void pisz(int x, int y, char napis[]) 

{

  gotoxy(x,y);

  puts(napis);

}

void main()

{

  clrscr();

  pisz(5,2,"Witaj");

  pisz(65,24,"mistrzu");

  getch();

}

Pojawiło się tu sporo nowych elementów. Nie będę ich wszystkich wyjaśniał. Po pierwsze popatrz, że teraz jest nowa 

funkcja pisz, której podać trzeba trzy rzeczy: dwie liczby i tekst. Te rzeczy to tak zwane argumenty. Funkcja gotoxy 

wymaga dwóch argumentów, zaś funkcja  puts  jednego argumentu. Ważne byś jedynie wiedział, że można łączyć 

funkcje w inne własne funkcje. To tak jakbyś skleił dwie małe cegły i powstała ci jedna większa.  W środku funkcji pisz 

są trzy wyrazy: xy i napis, które coś przechowują. Jak się nazywają dowiesz się później. Zauważ jeszcze, że nasza 

funkcja znajduje się przed main i zaczyna się od tajemniczego void.

9. DWA PLUS DWA

Umiesz już wypisać jakiś tekst w dowolnym miejscu ekranu. Teraz trzeba nauczyć się korzystać z tego, że komputer to 

wielki kalkulator. Na początek niech nam mądrala policzy ile jest 2+2.

przykład 10 – ap10.c

#include <stdio.h>

void main()

{

  printf("2+2 = %d",2+2);

}

W  tym  celu  musieliśmy  skorzystać  z   nowej   funkcji  printf.    Działa  ona   podobnie   do  puts  ale  może  mieć  wiele 

argumentów.   Pierwszy   argument   to   jakiś   tekst,   pozostałe   muszą   mieć   jakąś   wartość.     Symbol  %d  oznacza,   że 

kompilator ma podstawić tam liczbę, której wartość jest kolejnym argumentem. Funkcja printf różni się jeszcze tym, że 

po wyświetleniu tekstu kursor nie przechodzi do nowej linii. Początkowe 2+2 to tylko napis i jeśli go zmienimy to 

background image

kompilator nie wykryje błędu. Wtedy program może nam np. wyświetlić, że 2+1 = 4 co jest oczywiście nieprawdą. 

Wniosek: jak widać to co po lewej musi być również po prawej.

10. DWIE ZMIENNE

Teraz czeka nas kolejne zadanie. Zmieńmy program aby obie liczby wystarczało napisać tylko w jednym miejscu.

przykład 11 – ap11.c

#include <stdio.h>

int liczba1=2, liczba2=2;

void main()

{

  printf("%d+%d = %d",liczba1,liczba2,liczba1+liczba2);

}

Teraz   jeśli   chcemy   wiedzieć   ile   to   jest   3+4   to   wystarczy   poprawić   jedynie   dwie   liczby.   Co   zmieniliśmy? 

Wprowadziliśmy dwa wyrazy które przechowują pewną wartość. Są to tak zwane zmienne. Zmienna to w pewnym 

sensie pudełko na liczby. Każda zmienna ma swoją nazwę. Mamy tutaj zmienne o nazwach  liczba1  i  liczba2, choć 

równie dobrze mogłyby się nazywać a i b albo kot i pies. Jednak ja zalecam na sam początek stosowanie długich nazw, 

które mówią co dana zmienna przechowuje. Trzeba zawsze na początku określić zawartość zmiennej, gdyż jeśli jej nie 

określimy to kompilator nie wykryje żadnego błędu i wsadzi tam coś przypadkowego. Pudełka mogą być różnych 

rozmiarów. Podobnie zmienne mogą być różnych typów. Typ zmiennej to tak jakby rozmiar pudełka. Nasze dwie 

zmienne są typu int, czyli każda przechowuje liczbę całkowitą. 

11. PODAJ DWIE LICZBY

Nasz program jest jednak daleki od doskonałości. Żeby w nim coś policzyć, trzeba zmieniać początkowe  wartości w 

kodzie źródłowym. Może dla programisty byłby przydatny, ale nie dla zwykłego użytkownika. Trzeba program tak 

zmienić, aby samemu można było wprowadzać dane.

Przykład 12 – ap12.c

#include <stdio.h>

int liczba1=2, liczba2=2;

void main()

{

  puts("Podaj dwie liczby, oddzielając je spacją:");

  scanf("%d %d",&liczba1,&liczba2);

  printf("%d+%d = %d",liczba1,liczba2,liczba1+liczba2);

}

Dodaliśmy dwie instrukcje. Pierwsza informuje użytkownika co ma robić, za pomocą znanej nam już funkcji  puts  . 

Druga to funkcja o nazwie scanf. Tu pobiera od użytkownika dwie liczby i wpisuje ich wartość do zmiennych liczba1 i 

liczba2. Zwróć uwagę, że przy nazwach zmiennych jest symbol &. Nie zapomnij go napisać.

12. PASKUDNE UŁAMKI

Kiedy program już działa, można zacząć go testować. Może liczby całkowite to on dodaje, ale zupełnie nie radzi sobie z 

ułamkami. Na przykład podając 2 i 0.5 wypisuje wynik 2 zamiast 2.5. Trzeba będzie zmienić typ zmiennych z liczb 

całkowitych na rzeczywiste.

background image

Przykład 13 – ap13.c

#include <stdio.h>

float liczba1=2, liczba2=2;

void main()

{

  puts("Podaj dwie liczby, oddzielając je spacją:");

  scanf("%f %f",&liczba1,&liczba2);

  printf("%.3f+%.3f = %.3f",liczba1,liczba2,liczba1+liczba2);

}

Są tu w sumie trzy zmiany. Zamiast int mamy typ float. Trzeba było także zmienić symbol %d na %f. Symbol %d był 

dla typu  int, zaś %f jest dla typu  float. Po tych przeróbkach wynik wyświetlany był z dokładnością 6 miejsc po 

przecinku. Dodając .3 w funkcji printf zmniejszyliśmy dokładność do trzech miejsc po przecinku.

13. JESZCZE RAZ ?

Nasz program już działa poprawnie, ale programista nigdy nie jest zadowolony. Po policzeniu czegokolwiek program 

od razu wychodzi, to znaczy kończy swoje działanie. Najlepiej żeby się pytał użytkownika o zgodę, czy może go 

opuścić.

Przykład 14 – ap14.c

#include <stdio.h>

float liczba1=2, liczba2=2;

int cyferka=1;

void main()

{

  do {     /* powtarzaj poniższe instrukcje... */

    puts("Podaj dwie liczby, oddzielając je spacją:");

    scanf("%f %f",&liczba1,&liczba2);

    printf("%.3f+%.3f = %.3f",liczba1,liczba2,liczba1+liczba2);

    printf("\nCzy liczymy jeszcze raz ? (0=tak):");

    scanf("%d",&cyferka);

  } while (cyferka == 0);  /*... aż do spełnienia warunku */

}

Zacznę   wyjaśnianie   od   rzeczy,   które   są   najprostsze.   Pierwsze   co   dodaliśmy   to   instrukcję  printf  z   pytaniem   do 

użytkownika. Dlaczego ją, a nie puts ? Bo chcę aby kursor pozostał w tej samej linii, a puts go przenosi do następnej. 

Na początku jest symbol \n ,po to żeby cały ten tekst był w nowej linii. Funkcja scanf czeka na podanie liczby i pakuje 

ją do zmiennej  cyferka. Zmienna ta jest typu  int  i określiliśmy jej wartość jako 1 (w trzeciej linijce od góry).Teraz 

nowa cegiełka – instrukcja do ... while. Nazywana jest fachowo pętlą, bo instrukcje będące w środku chodzą w kółko. 

Ogólnie można by ją zapisać tak.

do {

  instrukcja1

  instrukcja2

background image

  ...

} while (warunek)

Pomiędzy { } wykonywane są instrukcje tak długo, aż zostanie spełniony warunek po  while. Nasz warunek brzmi: 

zmienna cyferka musi równać się 0. Symbol == oznacza znak równości. Warunek nie jest spełniony, bo wpisaliśmy 

inną liczbę ? Wtedy program kończy swoje działanie. Dzięki tej pętli możemy opuścić program wtedy, kiedy my 

chcemy i liczyć sobie nawet milion razy :)

14. T ZAMIAST ZERA

Jednak  wpisywanie zera i potwierdzanie go klawiszem [Enter] jest trochę niewygodne i mało intuicyjne. Spróbujmy 

zmienić to na literę t i pomińmy ten [Enter].

Przykład 15– ap15.c

#include <stdio.h>

#include <conio.h> 

float liczba1=2, liczba2=2;

char literka='n';

void main()

{

  do {     

    puts("\nPodaj dwie liczby, oddzielając je spacją:");

    scanf("%f %f",&liczba1,&liczba2);

    printf("%.3f+%.3f = %.3f",liczba1,liczba2,liczba1+liczba2);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while (literka == 't');  

}

Zamiast zmiennej cyferka jest teraz literka. Ta zmienna ma nieco inny typ. Stanowi takie pudełko na litery, a nie na 

liczby jak przy typach int i float. Typ ten ma nazwę char. Każda litera zaznaczana jest apostrofami (znaki ' ) . Ponadto 

mamy tu nową funkcję getch, która zastąpiła scanf. Funkcja getch pobiera od nas jeden znak i wpisuje go do zmiennej 

literka. Co ciekawe nie wyświetla go na ekranie komputera i nie wymaga naciskania klawisza [Enter]..Popatrz teraz na 

linijkę z tą funkcją. Znak = wcale nie oznacza równości tylko przypisanie. Przypisanie znaczy danie tego co po prawej, 

temu co po lewej. Tak jak na początku zmiennym  liczba1  i  liczba2  przypisaliśmy wartość 2, tak samo na końcu 

zmiennej  literka  przypisaliśmy znak zwracany przez funkcję  getch. Jeśli w tym miejscu nadal nie rozumiesz co to 

przypisanie to zobacz następny przykład.

Przkład 16 –ap16.c

#include <stdio.h>

int a=1,b=2;

void main()

{

  printf("\n%d %d",a,b);

  a=b;

  printf("\n%d %d",a,b);

}

background image

Taki króciutki programik, z którego możemy czerpać wnioski. Mamy dwie zmienne  a  i  b  typu  int. To co w sobie 

zawierają pokaże nam funkcja  printf. Najpierw zawierają liczby 1 i 2, potem 2 i 2. Dlaczego? Wartość zmiennej  

(czyli tego co stoi na prawo od znaku = ) została przypisana do zmiennej  a  (czyli tego co na lewo). Poprzednia 

zawartość pudełka a została bezpowrotnie stracona. Można to sobie wyobrazić jakby = działało jak strzałka w lewo. 

(  <=  ). Koniecznie spróbuj zamienić sobie miejscami a i b, czyli napisać b=a; i obejrzeć efekt.

15.  DUŻA LITERA T

Wróćmy jednak do naszego programu. Kontynuuje pracę po naciśnięciu litery t. Jednak co będzie jeśli użytkownik ma 

wciśnięty klawisz [CapsLock] ? Duże T już programowi nie pasuje, a przecież powinno.

Przykład 17– ap17.c

#include <stdio.h>

#include <conio.h> 

float liczba1=2, liczba2=2;

char literka='n';

void main()

{

  do {     

    puts("\nPodaj dwie liczby, oddzielając je spacją:");

    scanf("%f %f",&liczba1,&liczba2);

    printf("%.3f+%.3f = %.3f",liczba1,liczba2,liczba1+liczba2);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while ((literka=='t') || (literka=='T'));  

}

Troszkę rozbudowaliśmy warunek w pętli do...while. Dodana jest możliwość, że  może być też duże T. Dwie kreski 

pionowe oznaczają LUB. Czyli literka może być równa 't' lub 'T'. Dzięki nawiasom program jest bardziej czytelny i 

mamy określoną kolejność sprawdzania warunku.

16. WIZYTÓWKA

Jeszcze poinformujmy użytkownika co ten program robi, jak się nazywa i kto go stworzył (ach ta duma programisty :)

Przykład 18– ap18.c

#include <stdio.h>

#include <conio.h> 

float liczba1=2, liczba2=2;

char literka='n';

void main()

{

  clrscr();

  puts("*********************************");

  puts("* Program DODAWANIE  wersja 1.0 *");

  puts("*    autor: Artur Poznański     *");

  puts("* Program dodaje dwie liczby.   *");

background image

  puts("*********************************");

  do {  

    puts("\nPodaj dwie liczby, oddzielając je spacją:");

    scanf("%f %f",&liczba1,&liczba2);

    printf("%.3f+%.3f = %.3f",liczba1,liczba2,liczba1+liczba2);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while ((literka=='t') || (literka=='T'));  

}

Zrobiliśmy małą, ładną wizytówkę, która krótko opisuje nasz program. Nowe instrukcje są poza pętlą, gdyż chcemy aby 

nasza wizytówka pojawiła się tylko raz, zaraz po uruchomieniu programu. Najlepiej jeszcze, żeby taka sama wizytówka 

była  w  naszym   kodzie  źródłowym  jako komentarz  (na  samym   początku jako  informacja dla  nas). To już  jednak 

napiszesz sobie sam jeśli chcesz.

17. CHCĘ MIEĆ WYBÓR

 Powiedzmy, że chwilowo jesteśmy już zadowoleni, chociaż nasz program nie jest jeszcze głupoto-odporny ( ktoś może 

wpisać tekst zamiast liczb; trzy liczby itp..) Zakładam, że piszemy program dla siebie i na razie nie musi sobie z tym 

radzić. Teraz nasz nowy cel  to rozbudowa programu DODAWANIE o nowe działania:  odejmowanie, mnożenie i 

dzielenie.   Najprostsze   rozwiązanie   to   napisanie   jeszcze   trzech   podobnych   programów   zamieniając   jedynie   kilka 

drobiazgów (możesz to zrobić jako ćwiczenie, oczywiście zmieniając też komunikaty i wizytówkę). Jednak korzystanie 

z czterech programów zamiast jednego staje się super niewygodne. Dodamy te działania do istniejącego programu, 

jednak pora poznać najpierw potrzebne nam, nowe instrukcje.

Przykład 19. – ap19.c

#include <stdio.h>

int liczba;

void main()

{

  puts("Podaj liczbę 1, 2 lub 3");

  scanf("%d",&liczba);

  switch(liczba)

  {

    case 1: puts("Podałeś 1");

break;

    case 2: puts("Podałeś 2");

break;

    case 3: puts("Podałeś 3");

break;

    default: puts("Podałeś złą liczbę");

 break;

  }

}

background image

Wpierw powiem o działaniu programu.  Prosi o podanie liczby 1, 2 lub 3 i wyświetla odpowiedni napis. Tłumaczę co 

nowego. Program nam się wykonuje od wyświetlenia tekstu funkcją  puts  i pobrania liczby funkcją  scanf. W tym 

przykładzie chciałem pokazać, że nie musimy zawsze określać zawartości zmiennej zaraz przy jej nazwie (2 linijka od 

góry). W tym przypadku gdybyśmy nawet napisali  int liczba=0;  to i tak wartość ta zostanie zmazana przez 

funkcję scanf i dzięki niej określona na nowo przez użytkownika. Krótko mówiąc to czy określimy zawartość pudełka 

liczba w tym przykładzie nie ma znaczenia i możemy to pominąć. Ja jednak wolę znać zawartość wszystkich moich 

pudełek w każdej chwili. Czas omówić nową instrukcję. Nazywa się switch jest to instrukcja wyboru bo możemy sobie 

coś wybrać, np. jedną opcję z menu. Jej ogólna budowa wygląda tak.

switch(zmienna)

{

  case wartość1instrukcja1

                 ...

  case wartość2: instrukcja2  
                                         ...

  default: instrukcja3

           ...

}

Jeżeli zmienna będąca w nawiasach switch ma wartość1 to zostanie wykonana instrukcja1 i te co są po niej(czyli także 

instrukcja2, instrukcja3...).Jeżeli zmienna ma wartość2 to wykona się instrukcja2 i te co są po niej (instrukcja3,...).Jeżeli 

zmienna ma jakąś jeszcze inną wartość, której nie ma po napisie case, to zostanie wykonana instrukcja3 i te pod nią. 

Część default nie jest obowiązkowa i gdy jej brak, to w ostatnim omawianym przypadku nic się nie wykona. Żeby nam 

komputer nie wykonywał instrukcji od pozostałych case, używamy instrukcji break.  Wychodzi ona całkiem ze switch.

Pewnie się domyślasz, że trzy kropki oznaczają dalsze instrukcje w ramach danej wartości. Spróbuj z tego ostatniego 

przykładu  skasować  wszystkie  break  (np.  zrobić  z  nich  komentarze)  i  po  uruchomieniu  wpisać  1, 2  a  potem  3. 

Przekonasz się wtedy jak bardzo są potrzebne.

18. BUDUJEMY KALKULATOR

Poniżej masz obiecany program KALKULATOR. Jeszcze bez wizytówki i paru rzeczy, które wyjdą na wierzch przy 

testowaniu.

Przykład 20 – ap20.c

#include <stdio.h>

#include <conio.h> 

float liczba1=0, liczba2=0, wynik=0;

char literka='n', znak='+';

void main()

{

do {  

    puts("\nPodaj liczbę, znak [+,-,*,/] i drugą liczbę.");

    puts("Na końcu naciśnij [ENTER].");

    scanf("%f %c %f",&liczba1,&znak,&liczba2);

    switch(znak)

    {

background image

      case '+' : wynik=liczba1+liczba2;

                 break;

      case '-' : wynik=liczba1-liczba2;

                 break;

      case '*' : wynik=liczba1*liczba2;

                 break;

      case '/' : wynik=liczba1/liczba2;

                 break;

    }

    printf("%.3f%c%.3f = %.3f",liczba1,znak,liczba2,wynik);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while ((literka=='t') || (literka=='T'));  

}

Przykład ten jest dość podobny do przykładu 17. Jednak są tu dwie nowe zmienne:   znak  i  wynik. Mamy inny 

komunikat dla użytkownika (co ma robić). Potem  scanf  pobiera trzy dane. Zobacz, że  znak  jest typu  char, więc w 

funkcji scanf mamy jako drugi, symbol %c. Następnie instrukcja switch bada sobie tą zmienną i kieruje program do 

odpowiedniej części. Tam wykonywane jest odpowiednie działanie i jego  wynik przesyłany jest (przypisany) zmiennej 

o nazwie wynik. W funkcji printf zamiast liczba1+liczba2 wsadziliśmy wynik. Chcemy także, aby wyświetlił nam się 

odpowiedni znak działania, więc pomiędzy %f  stoi %c, zaś jeden z argumentów to zmienna znak.

19. PAMIĘTAJ CHOLERO...

Testując   program   stwierdzamy,   że   można   na   nim   wykonać   działanie   2/0.   Jednak   nasz   kalkulator   nie   powinien 

dopuszczać do takich obliczeń.(tylko nie pytaj dlaczego). Nieco więc go zmodyfikujemy.

Przykład 21 – ap21.c

#include <stdio.h>

#include <conio.h> 

#include <stdlib.h>

float liczba1=0, liczba2=0, wynik=0;

char literka='n', znak='+';

void main()

{

do {  

    puts("\nPodaj liczbę, znak [+,-,*,/] i drugą liczbę.");

    puts("Na końcu naciśnij [ENTER].");

    scanf("%f %c %f",&liczba1,&znak,&liczba2);

    switch(znak)

    {

      case '+' : wynik=liczba1+liczba2;

                 break;

      case '-' : wynik=liczba1-liczba2;

                 break;

background image

      case '*' : wynik=liczba1*liczba2;

                 break;

      case '/' : if (liczba2==0)

                 {

                    puts("Błąd: Dzielenie przez zero!");

                    exit(1);

                 }

                 wynik=liczba1/liczba2;

                 break;

    }

    printf("%.3f%c%.3f = %.3f",liczba1,znak,liczba2,wynik);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while ((literka=='t') || (literka=='T'));  

}

Funkcja  exit  powoduje zakończenie działania. Podajemy jej w nawiasie powód zakończenia (0 – normalne, 1- w 

wyniku błędu). Skorzystałem tu z nowej instrukcji if. Jej budowa to:

if (warunek)

   instrukcja

lub

if (warunek)

   instrukcja1

else

   instrukcja2

Jak warunek jest spełniony to wykonuje się instrukcja (lub w drugim przypadku instrukcja1), jak nie jest spełniony to 

nic się nie stanie (lub w drugim przypadku wykona się instrukcja2). Wszystko jasne? Jeśli nie to spójrz na króciutki 

programik z instrukcją if.

Przykład 22 – ap22.c

#include <stdio.h>

int a=2, b=1;

void main()

{

  if (a > b)   

    puts("a jest większe niż b");

  else

    puts("a jest mniejsze niż b"); 

}

Zmienne a i wynoszą 2 i 1. Warunek, że a > b jest zatem spełniony i wyświetli się napis , że a jest większe niż b. Jak 

zmienisz początkowe wartości a i b na odwrotne.(a=1, b=2), to wyświetli się komunikat po słowie else.

Wracając do programu Kalkulator, warunkiem dla if było to, że zmienna liczba2 będzie się równała zero. Gdy tylko 

zostanie on spełniony to wyświetla się komunikat i program przerywa działanie przez funkcję exit. Funkcja ta znajduje 

się w bibliotece stdlib.h.

background image

20. NIEWŁAŚCIWY ZNAK !

Teraz możemy się jeszcze zabezpieczyć, żeby nie dało się wpisać jako znaku działania np. wykrzyknika albo znaku 

zapytania albo innej litery oprócz tych przez nas ustalonych ( widziałeś może działanie 2!2 albo 2a2 ?).

Przykład 23 – ap23.c

#include <stdio.h>

#include <conio.h> 

#include <stdlib.h>

float liczba1=0, liczba2=0, wynik=0;

char literka='n', znak='+';

void main()

{

do {  

    puts("\nPodaj liczbę, znak [+,-,*,/] i drugą liczbę.");

    puts("Na końcu naciśnij [ENTER].");

    scanf("%f %c %f",&liczba1,&znak,&liczba2);

    switch(znak)

    {

      case '+' : wynik=liczba1+liczba2;

                 break;

      case '-' : wynik=liczba1-liczba2;

                 break;

      case '*' : wynik=liczba1*liczba2;

                 break;

      case '/' : if (liczba2==0)

                 {

                    puts("Błąd: Dzielenie przez zero!");

                    exit(1);

                 }

                 wynik=liczba1/liczba2;

                 break;

      default: puts("Błąd: Niewłaściwy znak działania!");

               exit(1);

               break;

    }

    printf("%.3f%c%.3f = %.3f",liczba1,znak,liczba2,wynik);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while ((literka=='t') || (literka=='T'));  

}

Dodałem nowe trzy linijki. Jest to nieobowiązkowa część instrukcji switch.  Wróć do programu 19 i popatrz jeszcze raz 

na jego budowę. Po słowie default znajdują się te instrukcje, które mają się wykonać gdy wartość w nawiasie switch 

nie pasuje do żadnej  z wartości podanych  po słowach case.

background image

21.  NARESZCIE GOTÓW

Pewnie zauważyłeś, że program nam się strasznie rozbudował. Może teraz wydaje ci się duży, ale prawdziwe programy 

mają dziesiątki tysięcy linijek. Nasz ma ich ledwie 35. Dodamy do niego wizytówkę i zajmiemy się budowaniem 

czegoś innego.

Przykład 24 – ap24.c

#include <stdio.h>

#include <conio.h> 

#include <stdlib.h>

float liczba1=0, liczba2=0, wynik=0;

char literka='n', znak='+';

void main()

{

  clrscr();

  puts("    *********************************");

  puts("    * Program KALKULATOR wersja 1.0 *");

  puts("    *    autor: Artur Poznański     *");

  puts("    *   Program dodaje, odejmuje,   *");

  puts("    * mnoży lub dzieli dwie liczby. *");

  puts("    *********************************");

  do {  

    puts("\nPodaj liczbę, znak [+,-,*,/] i drugą liczbę.");

    puts("Na końcu naciśnij [ENTER].");

    scanf("%f %c %f",&liczba1,&znak,&liczba2);

    switch(znak)

    {

      case '+' : wynik=liczba1+liczba2;

                 break;

      case '-' : wynik=liczba1-liczba2;

                 break;

      case '*' : wynik=liczba1*liczba2;

                 break;

      case '/' : if (liczba2==0)

                 {

                    puts("Błąd: Dzielenie przez zero!");

                    exit(1);

                 }

                 wynik=liczba1/liczba2;

                 break;

      default: puts("Błąd: Niewłaściwy znak działania!");

               exit(1);

               break;

    }

background image

    printf("%.3f%c%.3f = %.3f",liczba1,znak,liczba2,wynik);

    printf("\nCzy liczymy jeszcze raz ? (t=tak):");

    literka=getch();

  } while ((literka=='t') || (literka=='T'));  

}

W tym momencie mam jeszcze kilkadziesiąt pomysłów jak usprawnić program Kalkulator. Można by dać wizytówkę 

na środek ekranu, dodać potęgowanie i pierwiastki, zrobić kolorowe napisy, działania w nawiasach, obsługę myszy i 

duże przyciski, dźwięk, 100 megabajtowe intro... Ops, chyba się trochę zagalopowałem. To przecież ma być użyteczny 

kalkulator i taki właśnie jest, dlatego zostawimy go już w spokoju (pewnie i tobie znudziło się jego ciągłe testowanie).

22. PODSUMOWANIE

W tym miejscu będzie małe podsumowanie dotychczasowych wiadomości. Wiesz już, że program buduje się trochę jak 

dom. Zamiast cegieł są funkcje (np. printfscanfputs) i instrukcje (np. ifswitchdo...while). Program zaczyna się 

wykonywać od funkcji  main. Przed nią umieszczamy jakieś biblioteki (odpowiednik magazynów dla cegieł), oraz 

określamy nazwy i typy zmiennych (jakby rozmiary pudełek).Tymi typami mogą być int (pudełko na liczby całkowite), 

float  (na ułamki),  char  (najmniejsze pudełko na pojedynczy znak). Jak kilka zmiennych jest tego samego typu, to 

wymieniamy je w tej samej linii oddzielając przecinkami i kończąc średnikiem. Możemy też przypisać zmiennym jakąś 

wartość znakiem = (wsadzić coś do pudełka). Przypominam, że w funkcji scanf przed nazwą zmiennej piszemy znak &, 

a warunek równości zaznaczamy symbolem ==. Zapominanie o tych dwóch ostatnich rzeczach to jedne z najczęstszych 

błędów, gdyż nie wykrywa ich kompilator. 

23. KILKA RAD PRAKTYCZNYCH

Spróbuj koniecznie napisać kilka własnych programów, które coś wypiszą i coś policzą. Przez same przepisywanie 

gotowych niewiele się nauczysz. Twórz, podpatruj, przerabiaj czyjeś, jednym słowem eksperymentuj. Pamiętaj, że 

najpierw trzeba wymyślić co program ma robić. Potem staramy się, żeby w ogóle działał. Ozdoby w postaci wizytówki 

zostawiaj zawsze na koniec. Jeszcze jedna uwaga, nie nazywaj programów tak samo jak nazwy funkcji czy instrukcji. 

Ja raz zrobiłem taki błąd. Nazwałem program if.c i skompilowałem na if.exe. Nie wiedziałem dlaczego nie chce chodzić 

mimo, że kompilator nie wykrył żadnego błędu. Teraz już wiem, że w DOS'ie jest polecenie o takiej samej nazwie... :)

Część 2

24. WYŚWIETL MI 5 LICZB

Przechodzimy już do pisania nowych programów. Cel jest taki: wyświetlić 5 liczb (od 1 do 5) , jedna pod drugą. 

Przykład 25 – ap25.c

#include <stdio.h>

void main()

{

  printf("1\n");

  printf("2\n");

background image

  printf("3\n");

  printf("4\n");

  printf("5\n");

}

Program robi to co chcieliśmy, ale trzeba było napisać 5 razy funkcję printf. Zmienimy to ale jeszcze nie od razu. Teraz 

zastąpimy tylko te 5 liczb zmiennymi. Przypominam, że symbol \n powoduje przejście kursora do następnej linii. Oto 

kolejna wersja, obserwuj zmiany.

Przykład 26 – ap26.c

#include <stdio.h>

void main()

{

  printf("%d\n",1);

  printf("%d\n",2);

  printf("%d\n",3);

  printf("%d\n",4);

  printf("%d\n",5);

}

Program robi oczywiście to samo, ale teraz można będzie zastąpić liczby 1...5, zmienną powiedzmy k.

Przykład 27 – ap27.c
 #include <stdio.h>

int k;

void main()

{

  k=1;

  printf("%d\n",k);

  k=2;

  printf("%d\n",k);

  k=3;

  printf("%d\n",k);

  k=4;

  printf("%d\n",k);

  k=5;

  printf("%d\n",k);

}

Zapytasz pewnie po co to wszystko. Ano po to, byś zrozumiał jak działa nowa instrukcja. Zobacz do czego już 

doszliśmy. Mamy wreszcie pięć razy taką samą funkcję printf. Zmienia się tylko wartość zmiennej k.

Pamiętasz instrukcję do...while ? Spróbujemy trochę to przekształcić używając właśnie jej.

Przykład 28 – ap28.c
 #include <stdio.h>

int k=1;

void main()

{

background image

  do {

    printf("%d\n",k);

    k=k+1;

  } while (k < 6);

}

Teraz jest ważne abyś zrozumiał jak działa ten program, który oczywiście wypisuje 5 liczb. Jest on o wiele krótszy od 

poprzedniego i funkcja printf napisana jest tylko raz. Prześledźmy jak zmienia się wartość k. Wpierw wynosi ona jeden 

(2 linijka od góry). Potem wykonuje się działanie k+1 (czyli 1+1) i wynik przypisany jest k (czyli 2). Zatem instrukcja 

k=k+1; zwiększa wartość k o jeden. Potem wyświetla się jedynka i sprawdzany jest warunek czy k jest mniejsze od 5 

(czyli 2 < 5). Warunek jest spełniony więc jedziemy na początek. Znowu k+1 (czyli 2+1) i wynik wysyłamy do k (3 <= 

2+1). Wyświetla się dwójka i sprawdzany jest warunek czy k < 5 (czyli 3 < 5) . Dalej jest spełniony więc....itd. aż 

warunek nie będzie spełniony czyli aż zmienna k osiągnie wartość 6. 

25. MAŁE JEST PIĘKNE

Na koniec ostateczna wersja jeszcze bardziej skrócona dzięki nowej instrukcji.

Przykład 29 – ap29.c

#include <stdio.h>

int k;

void main()

{

  for (k=1; k<6; k++)

    printf("%d\n",k);

}

Cztery poprzednie programy były po to abyś mógł zrozumieć jak działa ten program. Wypisuje on 5 liczb, jednak 

zajmuje jeszcze mniej niż poprzedni. Mamy tu instrukcję  for, która jest pętlą, podobnie jak  do...while. Składa się z 

trzech części oddzielonych średnikami. Pierwsza z nich to instrukcja wykonywana tylko raz (tutaj k=1). Druga część 

jest sprawdzanym warunkiem (k<6), zaś trzecia to instrukcja wykonywana za każdym razem (k++). Instrukcja k++ robi 

dokładnie to samo co k=k+1, czyli zwiększa wartość k o 1.  Wewnątrz pętli for znajduje się printf. Można też umieścić 

wewnątrz więcej instrukcji, wtedy ogólna postać będzie wyglądać tak:

for (instrukcja1; warunek; instrukcja2)

{

    instrukcja3;

    instrukcja4;

    ...

}

Instrukcja2, instrukcja3, instrukcja4 i dalsze (wewnątrz nawiasów { }) wykonywać się będą aż do spełnienia warunku 

znajdującego się w nawiasie. Teraz już nie będzie dla nas stanowić problemu np. wypisanie 20 liczb, zamiast pięciu      ( 

wystarczy zmienić 6 na 21). A tak musiałbyś dwadzieścia razy pisać  printf  :(   Pewnie wydaje ci się to wszystko 

strasznie zagmatwane.  Nie przejmuj się, ważne byś wiedział, że jest taka cegiełka jak for i używamy jej wtedy, gdy 

wiemy ile razy ma się wykonać dana instrukcja.

26. ZNAK TO LICZBA

background image

Teraz zrobimy coś pożytecznego. Czy wiesz, że każdy znak zapisany jest w komputerze jako liczba?

Przykład 30 – ap30.c

#include <stdio.h>

void main()

{

  printf("Znak %c to liczba %d\n",'a','a');

}

Program ten wyświetli nam jaki jest kod znaku a. Funkcja printf wyświetla znak 'a' raz jako literę (symbol %c), a drugi 

raz jako liczbę (symbol %d). Kod znaku a to liczba 97. A jakim liczbom odpowiadają inne znaki?

Przykład 31 – ap31.c

#include <stdio.h>

#include <conio.h>

char znak='a';

void main()

{

  znak=getch();

  printf("Znak %c to liczba %d\n",znak,znak);

}

Program  czeka na  naciśnięcie klawisza i  podaje kod znaku. Wprowadziłem  tu zmienną  znak, której  wartość jest 

ustalana przez funkcję getch. Zauważ, że kody innych znaków są liczbami pomiędzy 0 a 255. 

Ale jak tu sprawdzać sobie kody znaków kiedy program od razy kończy działanie?

Przykład 32 – ap32.c

#include <stdio.h>

#include <conio.h>

char znak='a';

void main()

{

  puts("Naciskaj klawisze (q=wyjscie)");

  while (znak!='q') 

  {

    znak=getch();

    printf("Znak %c to liczba %d\n",znak,znak);

  }

}

Teraz zastosowałem nową pętlę, której do tej pory nie było. Nazywa się while i jej budowa to:

while (warunek)

{

    instrukcja1;

    instrukcja2;

    ...

}

background image

Działa podobnie do pętli do...while, ale różni się tym, że warunek sprawdzany jest na początku, a nie na końcu. Jeśli 

jest spełniony to wykonują się instrukcje wewnątrz nawiasów (czyli instrukcja1, instrukcja2 itd...).Natomiast jeśli nie 

jest spełniony, to nie wykona się nic. W naszym przykładzie warunek wyglądał tak znak!='q' i oznacza, że znak musi 

być różny od litery q. Symbol != oznacza nierówność. Na samym początku zmienna znak miała wartość a (patrz na 2 

linijkę od góry) a zatem warunek został spełniony i program wskoczył do instrukcji wewnątrz pętli. Pobrany jest znak, 

(np. b) wyświetlony jego kod (dla b jest to 98) i z powrotem sprawdzany jest warunek w nawiasach (znak!='q' czyli b 

różne od 'q'). Jak chcemy  skończyć działanie programu to naciskamy 'q' gdyż wtedy warunek różności nie zostanie 

spełniony i program pominie instrukcje znajdujące się wewnątrz pętli. Co się stanie jak na początku zmienna znak 

będzie miała wartość 'q' zamiast 'a' ? Nie wykona się żadna instrukcja będąca wewnątrz pętli while

27. NIE WYŚWIETLAJ KODU Q

Testujemy i już nam się znudziło. Naciskamy 'q' a program zamiast od razu wyjść, wypisuje nam jeszcze kod tej litery. 

Jak temu zaradzić?

Przykład 33 – ap33.c

#include <stdio.h>

#include <conio.h>

char znak='a';

void main()

{

  puts("Naciskaj klawisze (q=wyjscie)");

  while (1) 

  {

    znak=getch();

    if (znak=='q')

      break;

    printf("Znak %c to liczba %d\n",znak,znak);

  }

}

Można by w ten sposób. Jedynka w nawiasie oznacza warunek zawsze spełniony (1 to prawda, 0 to nieprawda). Potem 

pobierany jest znak. Zanim zostanie wypisany na ekran, instrukcja if sprawdza czy nie jest to klawisz 'q'. Jak jest to 

wykonuje się instrukcja break powodująca wyjście z pętli while. Czyli jak naciśniemy q to nie pokaże nam się jego 

kod a przecież o to nam chodziło.

28. NIECH WYCHODZI ESKEJP

Zauważ, że kod klawisza ENTER to 13, kod ESC to 27 zaś SPACJA ma 32. Możemy to wykorzystać zmieniając 

program aby wychodziło się z niego inaczej.

Przykład 34 – ap34.c

#include <stdio.h>

#include <conio.h>

char znak='a';

void main()

{

background image

  puts("Naciskaj klawisze (ESC=wyjscie)");

  while (1) 

  {

    znak=getch();

    if (znak==27)  /* 27 to kod klawisza ESC */

      break;

    printf("Znak %c to liczba %d\n",znak,znak);

  }

}

29. LICZBY Z MINUSAMI

Ja mam Windows 95 i jak nacisnę ALT-A to dla litery ą wyskakuje kod –91. Podobnie jest z innymi polskimi znakami. 

Dlaczego? Odpowiedź jest taka. Kody liczb są od 0 do 255. Tylko, że typ char potrafi przechowywać liczby pomiędzy 

-127 a 128 i dla tych polskich następuje jakby przekręcenie licznika. Następny program już sobie z tym radzi.

Przykład 35– ap35.c

#include <stdio.h>

#include <conio.h>

unsigned char znak='a';

void main()

{

  puts("Naciskaj klawisze (ESC=wyjscie)");

  while (1) 

  {

    znak=getch();

    if (znak==27)  

      break;

    printf("Znak %c to liczba %d\n",znak,znak);

  }

}

Zmieniłem jedynie typ z char na unsigned char. Dodanie tego słówka spowodowało, że zmienna znak może pomieścić 

liczby tylko dodatnie, więc przesunął się zakres z –127...128 do 0...255. Teraz już ą ma 165 zaś ń to 228 (zamiast –28).

30. ROBIMY TABLICĘ

Spróbujemy sobie zrobić taką tablicę wszystkich kodów. ( Jako ciekawostkę dodam, że te kody są to tzw. kody ASCII)

Przykład 36– ap36.c

#include <stdio.h>

#include <conio.h>

unsigned char znak='a';

void main()

{

  clrscr();

  for (znak=32; znak<255; znak++)

background image

    printf("%d=%c",znak,znak);

}

Dzięki instrukcji  for  zmienna znak przyjmuje wartości od 32 do 254. Zastanawia cię pewnie dlaczego wyświetlamy 

dopiero od 32 znaku a nie od zerowego ? Te znaki do 32 są sterujące i wyświetlanie ich może być kłopotliwe( np. znak 

o kodzie 7 wywołuje dźwięk głośniczka). 

31. PORZĄDKI NA EKRANIE

Jednak po uruchomieniu programu na ekranie widać straszny bałagan. Trzeba zrobić naszą tablicę bardziej czytelną.

Przykład 37- ap37.c

#include <stdio.h>

#include <conio.h>

unsigned char znak='a';

void main()

{

  clrscr();

  for (znak=32; znak<255; znak++)

    printf("%6d=%c",znak,znak);

}

Dopisaliśmy   tylko   jedną   cyferkę   w   funkcji  printf,   ale   za   to   jaka   różnica   !  Teraz   mamy   wszystkie   kody   ładnie 

poukładane w dziesięciu kolumnach. Cyfra 6 przed literką d   powoduje, że na liczbę zarezerwowane jest 6 miejsc. 

Ekran może pomieścić 80 znaków w poziomie i 25 w pionie. Sześć znaków na liczbę plus znak = i znak wyświetlany 

daje w sumie osiem. 80/8 równa się 10 i stąd mamy dziesięć kolumn.

32. NA KONIEC KOSMETYKA

Powiedzmy, że program się nam już podoba i poprawimy jedynie by nie kończył od razu działania oraz dodamy 

wizytówkę.

Przykład 38- ap38.c

#include <stdio.h>

#include <conio.h>

unsigned char znak='a';

void main()

{

  clrscr();

  puts("***************************************");

  puts("* Program TABLICA ZNAKÓW   wersja 1.0 *");

  puts("*     autor: Artur Poznański          *");

  puts("* Opis: program wyświetla wszystkie   *");

  puts("*         kody znaków ASCII           *");

  puts("***************************************");

  puts("\nNaciśnij dowolny klawisz...");

  getch();

  clrscr();

background image

  for (znak=32; znak<255; znak++)

    printf("%6d=%c",znak,znak);

  puts("\nNaciśnij dowolny klawisz...");

  getch();

}

Nie ma tu żadnych nowych instrukcji i chyba nie musze mówić co ten program robi. Zauważ, że w dwóch miejscach 

mamy po dwie takie same instrukcje. Chodzi mi o funkcje puts i getch. Zastąpimy je jedną własną o nazwie dowolny

Lecz wpierw troszkę teorii.

Przykład 39– ap39.c

void jakas_funkcja(void)

{

/* początek naszej funkcji */

/* tu będą instrukcje */

}

/* koniec naszej funkcji */

void main()

{

  jakas_funkcja();

}

Ten program nic nie robi. To jest demonstracja jak się tworzy własne funkcje. Wiesz, że program wykonuje się od 

funkcji main. Potem przechodzi do funkcji o nazwie jakas_funkcja i wykonuje wszystkie instrukcje wewnątrz jej. (Na 

razie ich nie ma, ale zaraz je dodamy). Teraz jeszcze zauważ, że nasza funkcja ma z przodu słówko void i wewnątrz 

nawiasu również. Teraz ci powiem co to oznacza. Słowo void oznacza dosłownie nic. Nic tej funkcji nie przekazujemy 

(void  w  nawiasie)  i  nic  ona nie zwraca  (void  przed nazwą). Tutaj pewnie się załamiesz. Jak funkcji  można  coś 

przekazać ? Co funkcja może zwracać ? A pamiętasz poprzednie funkcje ? Funkcjom   puts,  prinf,  scanf  i  gotoxy 

można było przekazać argumenty ( jakiś tekst, jakieś liczby). Funkcja getch zwracała nam naciśnięty znak.

33. NACIŚNIJ COŚ

Zrobimy teraz funkcję, która czeka na klawisz.

Przykład 40 – ap40a.c

#include <stdio.h>

#include <conio.h>

void dowolny(void)

{

  puts("\tNaciśnij dowolny klawisz...");

  getch();

}

void main()

{

  dowolny();

}

background image

Tutaj   w   funkcji  main  wywoływana   jest   jedynie   nasza   funkcja  dowolny,   która   z   kolei   wykonuje   dwie   instrukcje 

(wypisanie tekstu i czekanie na klawisz). Własną funkcję można też umieścić pod main, ale nad nią musi zostać sam 

nagłówek funkcji (pierwsza linijka funkcji).

Przykład 40 – ap40b.c

#include <stdio.h>

#include <conio.h>

void dowolny(void); /* to jest ta pierwsza linijka */

void main()

{

  dowolny();

}

void dowolny(void)

{

  puts("\tNaciśnij dowolny klawisz...");

  getch();

}

W podręczniku do C widziałem stosowanie drugiej metody. Jednak moim zdaniem ta pierwsza jest lepsza, bo mamy 

mniej pisania (gdyż nie wsadzamy przed  main  nagłówków). Ja ją będę stosował, ale Ty oczywiście możesz robić 

inaczej.

34. POWRÓT DO TABLICY

Wróćmy do programu TABLICA ZNAKÓW i zmieńmy to co zamierzaliśmy zmienić.

Przykład 41- ap41.c

#include <stdio.h>

#include <conio.h>

unsigned char znak='a';

void dowolny(void)

{

  puts("\tNaciśnij dowolny klawisz...");

  getch();

}

void main()

{

  clrscr();

  puts("***************************************");

  puts("* Program TABLICA ZNAKÓW   wersja 1.0 *");

  puts("*     autor: Artur Poznański          *");

background image

  puts("* Opis: program wyświetla wszystkie   *");

  puts("*         kody znaków ASCII           *");

  puts("***************************************");

  dowolny();

  clrscr();

  for (znak=32; znak<255; znak++)

    printf("%6d=%c",znak,znak);

  dowolny();

}

Program ten robi dokładnie to samo, co program z przykładu 38. Co prawda poprzez zastąpienie dwóch instrukcji jedną 

zysk wydaje się niewielki, ale program zyskał na czytelności. Zasada w programowaniu jest taka, żeby mieć jak 

najmniej instrukcji w funkcji main.

35. WIZYTÓWKA NA ŚRODEK

Aż żal ściska jak widzę ile miejsca się marnuje, gdy nasza śliczna wizytówka wyświetla się w lewym górnym rogu 

ekranu. Spróbujemy wyświetlić ją na środku ekranu. W tym celu skorzystamy z funkcji pisz będącej w przykładzie 9.

Przykład 42-ap42.c

#include <stdio.h>

#include <conio.h>

unsigned char znak='a';

void pisz(int x, int y, char napis[]) 

{

  gotoxy(x,y);

  puts(napis);

}

void dowolny(void)

{

  pisz(1,24,"Naciśnij dowolny klawisz...");

  getch();

}

void main()

{

  clrscr();

  pisz(20,10,"***************************************");

  pisz(20,11,"* Program TABLICA ZNAKÓW   wersja 1.0 *");

  pisz(20,12,"*     autor: Artur Poznański          *");

  pisz(20,13,"* Opis: program wyświetla wszystkie   *");

  pisz(20,14,"*         kody znaków ASCII           *");

  pisz(20,15,"***************************************");

  dowolny();

background image

  clrscr();

  for (znak=32; znak<255; znak++)

    printf("%6d=%c",znak,znak);

  dowolny();

}

Teraz  już  wizytówka  jest   mniej  więcej    na   środku.  Przyjrzyj   się   zmianom.  Zacznę   od  funkcji  main.  Wizytówkę 

wyświetla obecnie funkcja  pisz. Pierwsze dwie liczby wewnątrz niej to pozycja kursora dla wyświetlanego tekstu. 

Zmieniłem też funkcję dowolny. Również w niej znajduje się wywołanie funkcji pisz, którą umieściłem na samej górze. 

Dlaczego pisz jest przed dowolny (znajduje się wyżej)  ? Ponieważ funkcje będące później mogą wykonywać jedynie 

instrukcje zawarte w funkcjach będących wcześniej. Mówiąc po   ludzku, gdy zamienimy miejscami funkcje  pisz  i 

dowolny  (oczywiście nie w  main  :) to kompilator dojdzie do  pisz  i nie będzie wiedział co to jest, gdyż nie została 

WCZEŚNIEJ zdefiniowana (określona jej zawartość). Od tej pory zajmiemy się czymś zupełnie innym.

36. ZRÓBMY BIP

Każdy komputer ma wbudowany głośniczek. Spróbujemy poznać nowe funkcje, wydobywające dźwięki z naszego 

peceta.

Przykład 43 – ap43.c

#include <dos.h>

void main()

{

  sound(200);

  delay(500);

  nosound();

}

Ten program wyda nam krótki półsekundowy dźwięk. Są tutaj trzy nowe funkcje (wszystkie w bibliotece  dos.h). 

Funkcja sound powoduje wydobycie z głośnika dźwięku o podanej częstotliwości. Funkcja delay wstrzymuje działanie 

programu na pewien czas podany w milisekundach (1 sekunda =  1000 milisekund). Ostatnia z przedstawionych funkcji 

to nosound. Wyłącza ona głośniczek włączony wcześniej funkcją sound.

37.  DAJ GŁOS

Od razu przerobimy ten wcześniejszy programik na własną funkcję, powiedzmy dzwiek (w nazwach funkcji nie można 

stosować polskich liter :(  ) .

Przykład 44 – ap44.c

#include <dos.h>

void dzwiek(int nuta, int czas)

{

  sound(nuta);

  delay(czas);

  nosound();

}

void main()

background image

{

  dzwiek(200,500);

}

Program robi to samo co poprzedni. Jedyna zmiana to własna funkcja  dzwiek, której przekazujemy dwa argumenty, 

pierwszy to wysokość dźwięku (częstotliwość), drugi to jego długość (czas trwania).

38. STAŁE A ZMIENNE

W kolejnym przykładzie zademonstruję nowy element języka C. Będą nim stałe (tu wysokosc i czas).

Przykład 45 – ap45.c

#include <dos.h>

const wysokosc=200, czas=500;

void dzwiek(int nuta, int czas)

{

  sound(nuta);

  delay(czas);

  nosound();

}

void main()

{

  dzwiek(wysokosc,czas);

}

W programie wystąpiło słówko const, które powoduje, że wyrazy wymienione za nim to stałe. Stała to taka zmienna, 

która nie może się zmieniać i  dlatego tak się nazywa. Mówiąc prościej jest to (podobnie jak zmienna ) pewne pudełko 

na liczby. Lecz jak coś do niego wsadzimy (przypiszemy znakiem =) to już nie możemy tego zmienić. Ma to swoje 

plusy jak i minusy. Na przykład jak tworzymy pudełko pi na liczbę 3.14 to powinna to być stała. Od tego momentu 

wszystkie stałe będę pisał WIELKIMI LITERAMI. Obowiązku oczywiście nie ma, ale wszyscy tak robią, bo dzięki 

temu łatwiej w programie je odróżnić od zmiennych.

39. WLAZŁ KOTEK NA PŁOTEK

Zrobimy teraz takie małe pianino, że po naciśnięciu przycisku zagra odpowiedni dźwięk.

Przykład 46– ap46.c

#include <conio.h>

#include <dos.h>

const C2=131,

D2=147,

E2=165,

F2=175,

G2=196,

background image

A2=220,

B2=248,

C3=262,

      CZAS=200;

char znak;

void dzwiek(int nuta, int czas)

{

  sound(nuta);

  delay(czas);

  nosound();

}

void main()

  while(1)

  {

    znak=getch();

    if (znak==27) /* 27 to kod klawisza ESC */

       break;

    switch(znak)

    {

      case 'a' : dzwiek(C2,CZAS);

                 break;

      case 's' : dzwiek(D2,CZAS);

                 break;

      case 'd' : dzwiek(E2,CZAS);

                 break;

      case 'f' : dzwiek(F2,CZAS);

                 break;

      case 'g' : dzwiek(G2,CZAS);

                 break;

      case 'h' : dzwiek(A2,CZAS);

                 break;

      case 'j' : dzwiek(B2,CZAS);

                 break;

      case 'k' : dzwiek(C3,CZAS);

                 break;

    } /* koniec switch */

  } /* koniec while */

} /* koniec main */

Co programik robi ? Klawisze od a do k wydają dźwięki, ESC wychodzi. Na tym pianinie można zagrać słynną melodię 

"Wlazł kotek na płotek"( klawisze g d d f s s a d g, g d d f s s a d a). Dwa słowa o budowie programu. wszystkie  

background image

elementy omawiałem już wcześniej więc jeśli rozumiesz poprzednie przykłady, zrozumiesz i działanie tego (mam taką 

nadzieję). Każda nuta ma swój dwuliterowy symbol, który ma stałą częstotliwość. Z tych symboli zrobiliśmy stałe 

(przecież nie chcemy aby zmieniała nam się wysokość danej nuty). Nie trzeba określać typu stałej, wystarczy na 

początku   słówko  const.  Wszystkie   stałe   pisałem   jedna   pod   drugą,   żeby   program   był   czytelniejszy.   Stałą  CZAS 

ustawiłem na 200 bo 500 to jak dla mnie trochę za długo. Może pokusisz się o napisanie programu, który sam zagra 

jakąś melodię (np. tą podaną przeze mnie). 

39. WIZYTÓWKA I STARY NIEDŹWIEDŹ

Oto ostatnie kosmetyczne przeróbki ( użytkownik powinien wiedzieć co ma wciskać :).

Przykład 47– ap47.c

#include <stdio.h>

#include <conio.h>

#include <dos.h>

const C2=131,

D2=147,

E2=165,

F2=175,

G2=196,

A2=220,

B2=248,

C3=262,

      CZAS=200;

char znak;

void dzwiek(int nuta, int czas)

{

  sound(nuta);

  delay(czas);

  nosound();

}

void main()

  clrscr();

  puts("    *********************************");

  puts("    * Program PIANINO    wersja 1.0 *");

  puts("    *    autor: Artur Poznański     *");

  puts("    *  opis: Program wydaje przez   *");

  puts("    * wbudowany głośniczek dźwięki. *");

  puts("    *********************************");

  puts("\nKlawisze od [a] do [k] wydają odpowiedni dzwięk.");

  puts("Klawisz [ESC] powoduje opuszczenie programu.");

background image

  while(1)

  { 

    znak=getch();

    if (znak==27) /* 27 to kod klawisza ESC */

       break;

    switch(znak)

    {

      case 'a' : dzwiek(C2,CZAS);

                 break;

      case 's' : dzwiek(D2,CZAS);

                 break;

      case 'd' : dzwiek(E2,CZAS);

                 break;

      case 'f' : dzwiek(F2,CZAS);

                 break;

      case 'g' : dzwiek(G2,CZAS);

                 break;

      case 'h' : dzwiek(A2,CZAS);

                 break;

      case 'j' : dzwiek(B2,CZAS);

                 break;

      case 'k' : dzwiek(C3,CZAS);

                 break;

    } /* koniec switch */

  } /* koniec while */

} /* koniec main */

Cóż mogę więcej dodać do tego co już wiesz. Częstotliwości dźwięków wziąłem z książki Janusza Malika pt. "Norton 

Utilites 6.0" (str.158). Jak znam życie pewnie jej nie masz, a może ci  być za mało te  osiem dźwięków (np. próbując 

zagrać "Stary niedźwiedź mocno śpi"). Mam nadzieję, że autor książki się nie obrazi jeśli przytoczę wartości dla trzech 

pierwszych oktaw.

C

65

131

262

F#/Gb

93

185

370

C#/DB

69

139

277

G

98

196

392

D

73

147

294

G#/Ab

104

208

415

D#/Eb

78

156

311

A

110

220

440

E

82

165

330

A#/Bb

117

233

466

F

87

175

349 

B

123

248

494

Można by program zmodyfikować, żeby klawisze plus i minus wydłużały bądź skracały czas dźwięku ale twoja w tym 

głowa jak to zrobić ( dam ci podpowiedź: trzeba pewną stałą przerobić na zmienną).

40. TROCHĘ NAMIESZAM

Dzisiaj poznasz rzecz, która może bardzo ułatwić programiście życie. Pamiętasz wizytówkę z poprzedniego programu ? 

Nie umieszczałem jej na środku ekranu bo na początku musiałbym umieścić funkcję pisz, znaną choćby z przykładu 9. 

background image

Takie wstawianie tych samych funkcji do plików jest dość uciążliwe. Lecz znaleziono na to radę. Możemy wszystkie 

nasze funkcje umieścić w jednym pliku, a potem się do niego odwoływać. Niejako przy okazji poznasz jeszcze jedną 

nową rzecz od której teraz zacznę.

Przykład 48 – ap48.c

#include <stdio.h>

int wynik=0;

int suma(int a, int b)

{

  return(a+b);

}

void main()

{

  wynik=suma(2,2);

  printf("Wynik wynosi %d",wynik);

}

Jest to chyba najprostszy program jaki udało mi się wymyślić by pokazać jeszcze jedną własność funkcji. Oprócz tego, 

że funkcji można coś przekazać, to funkcja może nam coś zwracać. Poprzednie nasze funkcje nic nie zwracały bo miały 

na początku słowo void. Tutaj występuje funkcja  suma, która zwraca liczbę całkowitą (ma przed nazwą słowo int). 

Zwracaną wartością jest zawsze to co znajduje się w nawiasie instrukcji return.  Liczba zwracana przez funkcję suma 

przypisana jest zmiennej wynik, której wartość na koniec wyświetla printf. Czy domyślasz się jaką liczbę wyświetli 

program ?

49. WŁASNA BIBLIOTEKA, HURA !!!

Jeśli chcielibyśmy korzystać z funkcji  suma  w innych programach, to zrobimy sobie własną bibliotekę ( taki plik z 

funkcjami). Po przeróbkach program, który robi to co poprzedni lecz korzysta z funkcji, które są poza nim, wygląda 

tak:

Przykład 49 – ap49.c

#include <stdio.h>

#include "moja.h"

void main()

{

  wynik=suma(2,2);

  printf("Wynik wynosi %d",wynik);

}

Plik  moja.h

int suma(int a, int b); 

Plik  moja.c

int suma(int a, int b)

{

background image

  return(a+b);

}

Program z przykładu 49 składa się z trzech plików, które muszą podczas kompilacji znajdować się w tym samym 

katalogu. Stworzyliśmy bibliotekę o nazwie  moja, która jest dołączana do programu (słowo  #include). Biblioteka 

składa się z dwóch części: pliku z rozszerzeniami .c i .h . W pliku moja.c jest cała funkcja, zaś w pliku moja.h tylko jej 

nagłówek ( przypominam, że nagłówek to pierwsza linijka funkcji). Pewnie zdziwi cię dlaczego nazwa moja.h jest po 

podana w cudzysłowie a nie w nawiasach < >.   Cudzysłów oznacza tu, że biblioteka ma być szukana w bieżącym 

katalogu, zaś nawiasy < > oznaczają, że kompilator szuka w standardowym (jakimś swoim) katalogu . Jak to udało mi 

się skompilować? Szczerze powiedziawszy na początku miałem z tym drobne problemy. Żeby w moim kompilatorze 

skompilować więcej niż jeden plik, trzeba otworzyć tzw. projekt (opcja Open project...), tam podać nazwę (np. suma). 

Otworzy się okienko, gdzie możemy dodać pliki do kompilacji (tu wystarczy moja.c  i  ap49.c). Najeżdżamy na plik 

moja.c i naciskamy F9 (kompilacja).  Jak nie ma błędu powstanie plik taki jak nazwa projektu z rozszerzeniem .exe (tu 

suma.exe). To tyle wyjaśnień.

50. STAŁA NA GŁÓWKACH

Zróbmy sobie bibliotekę o nazwie  apbibl1.c  (bibl to skrót od słowa biblioteka, zaś co znaczy ap już się pewnie 

domyśliłeś :). Umieścimy w niej wszystkie funkcje, do tej pory przez nas stworzone (oprócz tej ostatniej bo jest mało 

przydatna).

Przykład 50 – ap50.c

#include <conio.h>

#include "apbibl1.h"

void main()

{

  clrscr();

  pisz(20,10,"W tym programie wykorzystałem własne funkcje");

  dzwiek(C2,CZAS);

  dowolny();

  pisz(25,15,"znajdujące się w innych plikach.");

  dzwiek(C3,CZAS);

  dowolny();

}

Plik apbibl1.h

const C2=131,

D2=147,

E2=165,

F2=175,

G2=196,

A2=220,

B2=248,

C3=262,

      CZAS=200;

background image

void pisz(int x, int y, char napis[]);

void dowolny(void);

void dzwiek(int nuta, int czas);

Plik apbibl1.c

#include <stdio.h>

#include <conio.h>

#include <dos.h>

void pisz(int x, int y, char napis[]) 

{

  gotoxy(x,y);

  puts(napis);

}

void dowolny(void)

{

  pisz(1,24,"Naciśnij dowolny klawisz...");

  getch();

}

void dzwiek(int nuta, int czas)

{

  sound(nuta);

  delay(czas);

  nosound();

}

Plik zawierający nagłówki funkcji zwany jest plikiem nagłówkowym. Wszystkie pliki z rozszerzeniem .h są plikami 

nagłówkowymi. W naszym pliku nagłówkowym apbibl1.h umieściliśmy oprócz trzech nagłówków jeszcze stałe. Mogą 

być używane we wszystkich programach do których dołączymy tą bibliotekę. Świetnym pomysłem jest zrobienie sobie 

stałych z kodów ważniejszych klawiszy np. ESC=27, ENTER=13, SPACJA=32 itp. 

51. PODSUMOWANIE 2

Najwyższa pora na kolejne podsumowanie, które być może poukłada nieco w głowie. Poznałeś nowe instrukcje (for, 

while, break, return), a także nowe funkcje (sound, delay, nosound). Wiesz już co oznacza słówko void oraz to, że 

litery w komputerze są przechowywane jako liczby. Własne funkcje (np. pisz, dowolny, dzwiek) można umieszczać we 

własnych bibliotekach (np apbibl1). Funkcji można coś przekazać (np. dwie liczby) i może coś zwracać (np. ich sumę). 

Oprócz zmiennych istnieją jeszcze podobne pudełka zwane stałymi (pisaliśmy je WIELKIMI LITERAMI). Ich wartość 

(zawartość) i  nazwę określamy po słówku const. Pierwsza linijka funkcji to jej nagłówek, zaś pliki z rozszerzeniem .h 

to pliki nagłówkowe (np. stdio.hconio.h czy moja.h).

background image

52. KILKA UWAG PRAKTYCZNYCH 2

Może   cię   to   zmartwi,   a   może   ucieszy,   ale   to   wszystko   co   poznaliśmy   do   tej   pory,   to   jedynie   maleńki   fragment 

możliwości   języka   C.   Jednak   pozwala   pisać   proste   programiki   i   poznać   lepiej   możliwości   swego   komputera. 

Programowanie to zabawa dla cierpliwych. Można parę godzin szukać jakiegoś błahego błędu, lecz jaka jest potem 

olbrzymia satysfakcja ! Nie zatrzymuj się w miejscu ! Jeśli jeden program nie chodzi, a ty nie wiesz czemu, zaznacz to 

w komentarzu i próbuj z drugim programem. Gdy już więcej się nauczysz (zostaniesz świetnym programistą), wtedy 

wróć do tego pierwszego i będziesz miał zupełnie nowe spojrzenie. Co prawda kompilator wykrywa więcej niż jeden 

błąd, ale ty nie staraj się poprawiać ich wszystkich lecz pierwszy napotkany.  Nie ma ludzi omylnych. Ja też mogłem się 

gdzieś pomylić. Najważniejsze by się nie poddawać i by stale zdobywać wiedzę. Tylko ta wiedza jest warta, z której 

umiesz skorzystać. Praktyka czyni mistrza !

KONIEC


Document Outline