Kurs języka C

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

Paweł Boiński

PDF by tommy@tommy.ltd.pl



Kurs języka C++

http://www.kurs-cpp.prv.pl/








1

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński


Język C++ jest jednym z najbardziej popularnych języków używanych przez

programistów na całym świecie. O jego uniwersalności świadczy przede wszystkim

zróżnicowanie pisanych w nim programów. Mimo dość zaawansowanego już wieku
języka C jego nowa wersja czyli C++ nadal się rozwija. Niepodważalną zaletą tego

języka jest jego prostota oraz obiektowość rozumiana w szerokim sensie. Nie przez
przypadek to języki obiektowo zorientowane zawojowały i podbiły rynek

programistyczny. Wszystkich zapraszam do przeczytania tego kursu i zapewniam, że

pomoże on wam w pisaniu efektownych i efektywnych programów.

Kurs podzielony jest na rozdziały. Każdy z nich dotyczy nowego zagadnienia. Uwaga!!!
Nie rezygnuj z kontynuowania nauki po przeczytaniu pierwszych kilku rozdziałów!!! Być

może wydadzą Ci się one trochę nudne, są jednak koniecznym wprowadzeniem do
pisania programów. Dotyczą one przede wszystkim podstaw języka C i C++. Jeżeli

pisałeś już programy w C (lub C++) to możesz je pominąć. Zachęcam jednak do

przejrzenia ich - być może znajdziesz coś o czym zapomniałeś, a z pewnością
odświeżysz sobie pamięć.


Moja przygoda z programowaniem zaczęła się od języka BASIC, którego możecie nie

pamiętać. Były to czasy gdy światem komputerowym "rządziły" takie maszyny jak

Commodore 64, Atari XT, ZX Spectrum. Moim kolejnym krokiem było zapoznanie się z
językiem Pascal, potem Turbo Pascal, a następnie z Object Pascalem. Stąd już prosta

droga prowadzi do języka C++.








2

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński





KURS JĘZYKA C++............................................................................................1

ROZDZIAŁ 1

PIERWSZY PROGRAM..............................................................4

ROZDZIAŁ 2

ZMIENNE .................................................................................7

ROZDZIAŁ 3

ZAKRES WIDOCZNOŚCI (WAŻNOŚCI) I ZASŁANIANIE NAZW

10

ROZDZIAŁ 4

INSTRUKCJE STERUJĄCE CZ.1...............................................14

ROZDZIAŁ 5

INSTRUKCJE STERUJĄCE CZ.2...............................................18

ROZDZIAŁ 6

INSTRUKCJE STERUJĄCE CZ.3...............................................22

ROZDZIAŁ 7

COUT CZY PRINTF ?...............................................................26

Printf..............................................................................................................26

Cout...............................................................................................................28

ROZDZIAŁ 8

MANIPULATORY ....................................................................30

ROZDZIAŁ 9

FUNKCJE................................................................................34

D

ODATEK

A ..........................................................................................................37

3

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 1 Pierwszy program

W tym rozdziale opisane są elementarne podstawy języka C:

-konstrukcja programu
-konstrukcja funkcji

-importowane bibliotek


Najprostszym programem, który robi cokolwiek jest aplikacja typu "hello world". Jej
zadaniem jest wyświetlenie napisu na ekranie monitora.

#include <stdio.h>

void main(void)
{

printf("hello world");

}

Zacznijmy od ogólnej konstrukcji.
W każdym programie w C++ musimy wyróżnić główną funkcję o nazwie main. To

właśnie ona jest uruchamiana gdy chcemy wykonać program. Część void main(void)

nazywamy nagłówkiem funkcji.
Składa się on z nazwy typu zwracanego przez funkcję, nazwy funkcji i listy argumentów

jakie przyjmuje funkcja. Typ void tak naprawdę oznacza brak typu - nasza funkcja ma
wypisywać na ekranie tylko napis "hello world", nie musi więc zwracać żadnej wartości i

nie potrzebuje żadnych argumentów. Po nagłówku następuje definicja funkcji którą ma

postać
{

//..
//instrukcje

//..

}
Dla ścisłości dodam, że dwa ukośniki (//) oznaczają komentarz - wszystko to co znajduje

się po nich aż do końca linii jest ignorowane przez kompilator.
W naszym programie jest tylko jedna instrukcja printf() służąca do wypisywania różnych

rzeczy na ekranie - opis tej funkcji można znaleźć w pomocy do kompilatora, a
użytkownicy linuksa mogą przeczytać opis każdej instrukcji w manualu (polecenie man

4

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

np. man printf ).

W najprostszej postaci wywołanie funkcji printf wymaga podania jednego parametru -
łańcuha znaków (string) albo zmiennej niekoniecznie typu łańcuchowego.

Zauważmy, że po każdej instrukci stawiamy znak ; (średnik). Taka konwencja zapisu

przyjęła się w bardzo wielu językach np. pascal, java. Po kompilacji i wykonaniu
programu na ekranie wyświetlony zostanie napis hello world (bez cudzysłowów).

Co by się stało gdybyśmy dodali jeszcze jedna linijkę printf("hello world") ?
Otrzymalibyśmy na ekranie napis hello worldhello world. Dlaczego?

Wynika to ze specyfikacji funkcji printf. Po wykonaniu tej funkcji znak kursora nie jest

przenoszony automatycznie do następnej linii. Aby uzyskać pożądany efekt stosujemy
tzw. znaki specjalne. Jednym z nich jest znak łamania linii \n. Otrzymujemy zatem

instrukcję o postaci printf("hello world\n"); która spełni nasze oczekiwania.

Ważnym elementem, o którym do tej pory nie wspomniałem są biblioteki języka C++.
Są to jakby gotowe zestawy funkcji, które możemy wykorzystać w naszych programach.

Jedną z takich bibliotek jest stdio.h, która zawiera funkcję printf. Importowanie biblioteki

polega na zasygnalizowaniu kompilatorowi, że chcemy z niej skorzystać. Istnieją dwa
sposoby zapisy dodania biblioteki do programu:

#include<nazwa_biblioteki>
lub

#include"nazwa_biblioteki"

Na razie wystarczy, że zapamiętasz jeden ze sposobów (o różnicy napiszę przy innej
okazji) i będziesz go używał.









5

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński


6

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 2 Zmienne

Bez zmiennych trudno sobie wyobrazić działanie jakiegokolwiek programu

komputerowego. Istnieje wiele rodzajów typów zmiennych. Co to jest typ zmiennej ?
Ogólnie mówiąc jest to definicja dotycząca zawartości danej zmiennej. Wiadomo

przecież, że liczby całkowite są przechowywane inaczej w pamięci komputera niż np.

liczby rzeczywiste, inne też są dopuszczalne operacje na tych typach zmiennych.
Programista musi poinformować kompilator ze zmienną jakiego typu ma do czynienia.

Typy można podzielić na:
-podstawowe(fundamentalne)

-pochodne

lub
-wbudowane

-zdefiniowane przez programistę

Najważniejsze typy zmiennych podstawowych to:
a)do reprezentacji liczb całkowitych

Short int, int, long int (różnią się zakresami)
b)do reprezentacji liczb rzeczywistych

float, double, long double (różne dokładności)

c)do reprezentacji znaków
char, wide char


Sposób deklaracji:

Jest on bardzo prosty - składa się z nazwy typu i nazwy zmiennej.

Int I; // deklaracja zmiennej całkowitej i , czytamy „i jest zmienną typu int”
Double x; // x jest zmienną typu double,

Char z; // z jest zmienną typu char.

Mając takie zmienne możemy je wykorzystać w dalszych instrukcjach np.

I = 5; // przypisz zmiennej i wartość 5
I = I + 2; // można tak, gdyż kompilator najpierw oblicza wartość wyrażenia stojącego

po prawej stronie operatora = a następnie przypisuje tę wartość zmiennej stojącej po
lewej stronie; w tym przypadku zwiększamy zmienną I o 2.


z = ’a’ ; przypisanie zmiennej z znaku ’a’

7

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński


Oprócz typów podstawowych możemy także tworzyć typy pochodne(w rzeczywistości

nie tworzymy typów pochodnych a tylko definiujemy obiekty pochodne od typów

podstawowych - na razie zapamiętaj tylko, że każda zmienna jest obiektem) . Często
początkujący programiści zadają pytanie czy są one konieczne. Odpowiedź jest prosta -

są niezbędne. Nie tylko ułatwiają pracę, ale również są w niektórych sytuacjach
niezastąpione. Przed wymienieniem tych typów chcę Ci powiedzieć, że na razie

zajmiemy się tylko jednym (pierwszym) z nich a resztę zostawimy sobie na później.


Typy pochodne:

-tablica
-referencja

-wskaźnik
-funkcja

Tablica jest to uporządkowany zbiór zmiennych o tym samym typie. Wyobraźmy sobie,
że potrzebujemy 200 zmiennych typu int. Deklarowanie takiej liczby zmiennych byłoby

samobójstwem nie wspominając o szukaniu nazw dla nich. To samo możemy załatwić
jedną linijką

Int t[200]; // jest to deklaracja tablicy 200 obiektów typu int


A jak się odwoływać do takich obiektów??

W ten sposób:
t[20] = 30; // do 21 elementu tablicy przypisz wartość 30

Nie, nie pomyliłem się, do 21 a nie 20 - wyjaśnia to fakt, że elementy tablicy są

numerowane od 0 a nie od 1. Zatem w naszej tablicy możemy posługiwać się numerami
pól (czyli elementów tablicy) od 0 do 199. Może początkowo być to przyczyną błędów,

ale po pewnym czasie można się do tego przyzwyczaić.






8

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

9

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 3 Zakres widoczności

(ważności) i zasłanianie

nazw

Skoro umiesz już deklarować obiekty (zmienne) nie sposób pominąć tematu zasłaniania

(zwanego czasem przesłanianiem) nazw. Aby wyjaśnić co to takiego jest konieczne jest
zdefiniowanie następujących pojęć:

- czas

życia obiektu - jest to czas od momentu powstania obiektu (powołania go do

życia aż do czasu jego zlikwidowania

- zakres

widoczności obiektu - jest to zakres programu, w którym możemy

odwołać-

się do tego obiektu (inaczej mówiąc jest to zakres programu, w

którym kompilator widzi dany obiekt)

Mając dany obiekt musimy zadbać o to aby był on widoczny we wszystkich miejscach, w
których będzie wykorzystywany.

Możemy wyróżnić kilka zakresów ważności:

- zakres lokalny - jeżeli jest ograniczony do pewnego fragmentu programu.

Przykładem może być-

blok instrukcji

{

//...
}

Każda zmienna(obiekt), która jest zadeklarowana wewnątrz takiego bloku jest

znana tylko i wyłącznie w nim. Czas życia obiektu kończy się w momencie końca
bloku instrukcji.

Np.
{

//...

{
int a = 15;

cout << a; #1
}

10

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

cout << a; #2

}
W #1 zostanie wypisana nazwa, ale w #2 jest błąd (taki program się nie

skompiluje).

Obiekt a jest widoczny i istnieje tylko wewnątrz tego bloku instrukcji, w którym
został stworzony. Poza tym blokiem nie ma żadnego obiektu a.

- zakres globalny (pliku) - na razie omawiane programy mieszczą się w jednym

pliku, więc wystarczy zapamiętać- ,

że obiekt zadeklarowany poza obszarem

bloku instrukcji (również bloku funkcji - patrz następny podpunkt) jest widziany w
całym programie (o ile nie zostanie przesłonięty), mówimy, że jest to obiekt

globalny
Np.

int a;
main (void)

{

#1
}

#2

Obiekt a jest obiektem globalnym - jest widziany zarówno w #1 jak i w #2

- zakres

funkcji

taki zakres ważności ma etykieta (wykorzystywana przez instrukcję goto), o
której może wspomnę później, choć jak się przekonasz nie jest ona niezbędna.

Wymieniam ją tutaj tylko ze względu na kompletność informacji

- zakres klasy - nazwa widoczna jest w całej klasie

brak przykładu - będzie gdy już dowiesz się co to jest klasa

Zasłanianie nazw:

Możemy zadeklarować dwa obiekty o tej samej nazwie - jedyny warunek - muszą mieć
inny zakres ważności. Zasłanianie nazw jest bardzo intuicyjne. Jeżeli mamy obiekt

globalny X to zadeklarowanie w pewnym bloku instrukcji obiektu o nazwie X przesłoni

obiekt globalny X.
Oczywiście będzie on cały czas istniał, jednak odwołanie się w tym bloku instrukcji do X

spowoduje odwołanie się do obiektu X zadeklarowanego w tym bloku. Można także
odwołać się do obiektu globalnego - z pomocą przychodzi nam operator zakresu ::,

który umieszcamy przed interesującą nas zmienną.


Zastanów się nad wynikiem działania tego programu:

Wskazówka: instrukcja cout wyrzuca napisy na ekran, zapis cout << x << endl; jest

11

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

równoważny następującemu: cout << x; cout << endl; gdzie endl do znak końca linii

(END Line).

Przykład:

#include <iostream.h>
int x = 5;

void main(void)
{

cout << x << endl;

int x = 10;
{

int x =15;
cout << x <<endl;

}
cout << x << endl;

cout << ::x << endl;

}

Program wypisz na ekranie:
5

15

10
5


Jeżeli zgadza się to z twoimi przewidywaniami to gratuluję - zrozumiałeś ten rozdział.








12

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński






13

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 4 Instrukcje sterujące cz.1

Przejdę teraz do opisu tzw. instrukcji sterujących bez których nie ma mowy o napisaniu

jakiegokolwiek bardziej złożonego programu. Na początku mogą się one wydawać nieco
skomplikowane ale po pewnym czasie nabierzesz takiej wprawy, że będą ci się one

wydawały zupełnie naturalne i nie będziesz na nie zwracał uwagi(co często prowadzi do

trudnych do wykrycia błędów).

Instrukcja if ...

Instrukcja if ... służy do sprawdzenia warunku, a następnie wykonania, bądź

niewykonania kolejnych instrukcji. Jej postać jest następująca:
if (wyrażenie)

{
//instrukcja/e

}

Jeżeli wyrażenie jest spełnione to instrukcje w zamknięte w klamrach są wykonywane.
Czym jest wyrażenie?

Tutaj wiele zależy od nas samych. W skrajnym przypadku może to być jedna zmienna i
to niekoniecznie typu bool. Otóż w C++ za prawdę uważa się wszystko co jest różne od

zera. Zatem liczba int o wartosci 1 jest w tym wypadku traktowana jako prawda. Nas

zapis wyglądałby np. tak:

int liczba_int=1;
if (liczba_int)

printf("prawda");


po wykonaniu tych instrukcji zobaczylibyśmy na ekranie napis "prawda"


Podobnie jest w przypadku następującego programu

int liczba_int;

//...
if (liczba_int>0)

printf("prawda")

Napis prawda ukaże się nam gdy liczba_int jest większa od zera.
A co zrobić gdy chcemy sprawdzić czy liczba znajduje się w danym zakresie? np. czy jest

14

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

większa od 5 ale mniejsza od 10?

Można to zrobić tak:
if (liczba_int>5)

if (liczba_int<10)

printf("liczba nalezy do przedziału (5,10)");

Jest to jednak mało eleganckie i bardzo niepraktyczne rozwiązanie. Łatwo sobie
wyobrazić co by było gdybyśmy mieli do sprawdzenia np. 10 warunków...

Z pomocą przychodzą nam wyrażenia złożone. Jak sama nazwa wskazuje składają się

one z kilku części. Przykład :
if ( (liczba_int>5) && (liczba_int<10) )

printf("liczba nalezy do przedziału (5,10)");

Tutaj widzimy, że sprawdzane są dwa warunki. Połączeniem jest symbol && zwany
operatorem koniunkcji. Aby wyrażenie było prawdziwe obie jego części muszą być

prawdziwe. Innym często stosowanym operatorem jest alternatywa ||. Aby takie

wyrażenie było spełnione wystarczy, że jedna ze stron jest spełniona. Pełny opis
operatorów logicznych znajduję się w dodatku B.


Pętle


Instrukcja for


Czy nie zastanawiałeś się np. jak wypełnić tablicę, powiedzmy, kolejnymi liczbami

naturalnymi począwszy od jeden.

Załóżmy, że naszą tablicą jest tablica o nazwie Liczby o następującej deklaracji
int Liczby[10];


Przypominam, że elementy są numerowane od zera.

Można nasze zadanie wykonać tak:

Liczby[0]=1;
Liczby[1]=2;

....
Liczby[9]=10;

No tak, powiesz, że proste. Wyobraź sobie teraz tablicę o 100 tysiącach elementów.
Trudne ??

Oczywiście, że nie. Stosujemy instrukcję for.
Nasz programik wyglądałby następująco:

for (int i=0; i<100000; i=i+1)
{

Liczby[i]=i+1;

15

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

}


A teraz komentarz:

Instrukcja for ma postać :

for (zmienna sterująca=stan początkowy ; warunek wykonywania ; operacja sterująca)
{

//instrukcje
}

Naszą zmienną sterującą jest w tym przypadku zmienna i. Początkowo ma wartość
równą 0. Warunkiem wykonywania jest wyrażenie i<100000. Należy to rozumieć w

następujący sposób. Dopóki zmienna i jest mniejsza od 100000 wykonuj zadanie. W
momencie gdy zmienna i jest większa lub równa 100000 przestań wykonywać ciało pętli

(czyli instukcje w niej zawarte). Ostatnim polem jest operacja sterująca. Mówi ona co po
każdym wykonaniu pętli ma być wykonane ze zmienną sterującą. W naszym przypadku

jest to zwiększenie o 1.

UWAGA!!! Podkreślam, że operacja(instrukcja) sterująca jest wykonywana na koniec
każdego wykonania pętli.


Przytoczony programik jest najprostszym przykładem użycia pętli for. Uwierz mi już

teraz – ta pętla jest najczęściej wykorzystywana we wszystkich programach, wkrótce

sam się o tym przekonasz.









16

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński



17

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 5 Instrukcje sterujące cz.2

Jeżeli już zapoznałeś się z poprzednimi instrukcjami pora przejść do kolejnych. Będą to

również pętle. Jak to, pętle już były powiesz. Rzeczywiście, jednak instrukcja for nie
zawsze jest najlepszym rozwiązaniem. W niektórych przypadkach znacznie łatwiej jest

używać innych instrukcji.


Instrukcja while ...


Jej postać to

while (warunek)
{

// instrukcje
}

Instrukcja while działa tak długo, jak spełniony jest warunek. Zauważ, że jeżeli warunek
nie jest spełniony na początku pętla nigdy się nie wykona. Jest to bardzo ważna uwaga i

radzę Ci byś dobrze ją zapamiętał. Aby lepiej zrozumieć instrukcję while przeanalizujmy
następujący program

#include „iostream.h”
void main(void)

{

int wysokosc_trojkata=10;

while

(wysokosc_trojkata>0)

{
for

(int

licznik=0;

licznik<wysokosc_trojkata;licznik++)

cout << '*' ;

cout

<<

endl;

wysokosc_trojkata--;

}
}


Na wstępie już wyjaśniam co robi cout (console out). Jest to instrukcja, która została

wprowadzona w C++ w celu ułatwienia wyprowadzania znaków na ekran. Aby ją
wykorzystać należy dodać bibliotekę iostream.h . Poprzednio używałem w przykładach

18

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

instrukcji printf, jednak dobrze abyś wiedział, ze nie jest to jedyny sposób wypisywania

napisów (ponadto printf pochodzi jeszcze z języka C ). Instrukcję cout wywołujemy z
jednym lub więcej parametrami.

cout << „hello”

wypisze na ekranie hello

cout << endl

spowoduje, że zostanie wypisany znak końca linii (czyli nastąpi

przejście do nowej linii)

Dodam, że endl to skrót od ENd Of Line a w wyświetlanym ciągu można używać również
znaków specjalnych.

Tyle dygresji na temat cout. Wracając do naszej pętli czy wiesz już co pojawi się na

ekranie??
Będzie to trójkąt złożony z gwiazdek, dokładnie taki:

**********
*********

********
*******

******

*****
****

***
**

*


Prześledźmy działanie programu krok po kroku.

/* ta linia definiuje i inicjalizuje zmienna przypisując jej wartość 10; */

int wysokosc_trojkata=10;

/* dopóki zmienna jest większa od zera wykonujemy ciało pętli */

while (wysokosc_trojkata>0)

{

/* Wypisujemy tyle gwiazdek ile wynosi zmienna wysokosc_licznika */

for (int licznik=0; licznik<wysokosc_trojkata;licznik++)

cout << '*' ;

/* przechodzimy do nowej linii */

cout

<<

endl;

/* zmniejszamy wysokość trójkąta o1*/

wysokosc_trojkata--;

}

Na początku zmienna wysokosc_trojkata ma wartość 10. Jest > 0 czyli wchodzimy do
pętli while.

Tam wypisujemy za pomocą pętli for 10 gwiazdek. Po zakończeniu pętli for

przechodzimy do nowej linii. Zmniejszamy wysokosc_trojkata o 1. ( gdyby tej instrukcji
nie było program działałby w nieskończonej pętli). Wracamy do warunku pętli while.

Teraz zmienna wysokosc_trojkata ma wartość 9 nadal jest więc większa 0 – znowu

19

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

wykonujemy ciało pętli. Widać, że będzie tak się działo dopóki zmienna

wysokosc_trojkata nie będzie miała wartości 0. Wówczas pętla while się zakończy.

Mam nadzieję, że dobrze wyjaśniłem działanie tego programu.

Najważniejszą rzeczą, którą trzeba zapamiętać to to, że warunek pętli while jest
sprawdzany na początku. Dlaczego?

Otóż jest jeszcze jeden typ pętli, który różni się tylko momentem, w którym sprawdzany
jest warunek wykonania. Jest to pętla do ... while.


Instrukcja do ... while


Jej działanie jest prawie identyczne jak w przypadku instrukcji while... . Najważniejszą

różnicą jest to, że warunek sprawdzany jest na końcu. Niesie to za sobą bardzo ważne
konsekwencje – pętla zostanie ZAWSZE wykonana przynajmniej jeden raz.


Jeżeli poprzedni program nieco zmodyfikujemy(zamieniamy while... na do...while) :


#include "iostream.h"

void main(void)
{

int

wysokosc_trojkata=10;

do

{

for

(int

licznik=0;

licznik<wysokosc_trojkata;licznik++)

cout << '*' ;

cout

<<

endl;

wysokosc_trojkata--;

}

while

(wysokosc_trojkata>0);

}


Wynik będzie identyczny.

Ale zauważ, że o ile taki program
#include „iostream.h”

void main(void)
{

int wysokosc_trojkata=0;

do
{

for

(int

licznik=0;

licznik<wysokosc_trojkata;licznik++)

20

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

cout << '*' ;

cout

<<

endl;

wysokosc_trojkata--;

}

while (wysokosc_trojkata>0)

}


nie wypisałby na ekranie nic, to taki (z pętla while):

wypisałby znak końca linii.
Jest to spowodowane tym, że warunek (wysokosc_trojkata>0) jest sprawdzany na

końcu, po przejściu pętli.

21

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 6 Instrukcje sterujące cz.3

Znowu instrukcje sterujące?! zapytasz. Spokojnie, to już ostatni rozdział na ich temat.

Tym razem zajmiemy się instrukcją switch, goto, break, continue.

Instrukcja switch


Wyobraź sobie następującą sytuację:

Masz zrobić menu w trybie tekstowym, które będzie sterowane za pomocą
wczytywanych liczb np.

1) Nowa baza

2) Dodaj element
3) Usun element

4) Koniec

Program ma pobierać numer komendy z klawiatury i wykonywać odpowiednią akcję.

Pomijając kwestię wczytywania z klawiatury, dotychczas omówione instrukcje pozwalają
na rozwiązanie tego zadania w następujący sposób:


int NumerKomendy;

// Deklaracja zmiennej, w której będzie przechowywany numer

komendy

cout << „Podaj numer komendy:”;

// Wypisanie komunikatu

cin >> NumerKomendy;

// Pobranie numeru z klawiatury


if ( NumerKomendy == 1 )

{

// ... Tutaj odpowiedni kod odpowiadający za utworzenie nowej bazy

}

if (NumerKomendy == 2 )
{

// ... Tutaj odpowiedni kod odpowiadający za dodanie elementu

}
...itd.


Mało efektywne i dużo trzeba pisać.

W takiej sytuacji niezastąpiona jest instrukcja switch. Jak sama nazwa wskazuje pełni
ona rolę przełącznika.

22

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

Jej składnia jest następująca:

switch (ZmiennaSterujaca)
{

case wartosc : //instrukcje

break;
}


W naszym przypadku odpowiedni byłby taki kod:

int NumerKomendy;

cout << „Podaj numer komendy:”;
cin >> NumerKomendy;


switch ( NumerKomendy )

{

case 1 :

// ... Tutaj odpowiedni kod odpowiadający za utworzenie nowej bazy

break;

case 2 :

// ... Tutaj odpowiedni kod odpowiadający za dodanie elementu

break;

case 3 :

// ... Tutaj odpowiedni kod odpowiadający za usuniecie elementu

break;

case 4 :

// ... Tutaj odpowiedni kod odpowiadający za wyjscie

break;
default : cout << “Zla komenda”;

break;

}

Wydaje się, że jest to bardzo intuicyjne. Jako parametr switch podajemy zmienną, której
wartość wpływa na wykonywane akcje. Następnie po case podajemy wartość. Jeżeli jest

ona taka sama jak wartość zmiennej sterującej to zostanie wykonana akcja. Ich
wykonywanie kończy się po napotkaniu instrukcji break. Jeżeli żadna wartość nie jest

taka sama jak wartość zmiennej to wykonana zostanie akcja zdefiniowana jako default

(domyślny).
UWAGA! Dopasowanie powoduje wykonanie wszystkich akcji następujących po

napotkaniu pasującego case’a aż do napotkania instrukcji break lub końca instrukcji
switch.

Np.

Wykonanie poniższego programu
int Numer = 2;

// deklaracja zmiennej Numer i nadanie jej wartości 2

switch(Numer)
{

case 1: cout << “A\n”;

brak;
case 2: cout << “B\n”;

case 3: cout << “C\n”;

23

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

break;

}

spowoduje wypisanie na ekranie BC ani samego C. Zauważ, że dedfinicja akcji

domyślnej (default) nie jest konieczna.


Instrukcje break, continue, goto.

Z instrukcją break spotkaliśmy się już w poprzednim paragrafie. Powoduje ona
natychmiastowe zakończenie wykonywania instrukcji i można ją stosować również w

pętlach for, while, do...while. Jeżeli mamy do czynienia z pętlami zagnieżdżonymi to
wywołanie instrukcji break spowoduje zakończenie tej, w której się bezpośrednio

znajduje.
Instrukcja continue powoduje przerwane wykonywania pętli w danym przebiegu i

rozpoczęcie wykonywania następnego przebiegu (nie ma więc sensu stosowanie jej w

instrukcji switch – tam jest jeden przebieg) np.

int Licznik;

for (Licznik=1; Licznik<10; Licznik++)

{

cout << ”A”;

if (Licznik>5)

continue;

cout <<”B”;

}

da w wyniku napis na ekranie:

ABABABABAAAAAA

Instrukcja goto
Wiele osob pomija albo pragnie pominąć tę funkcję. Jej działanie polega na skoku do

pewnego określonego miejsca zaznaczonego etykietą. Mówi się, że stosują ją tylko źli

programiści ale ja uważam, że są sytuacje gdy użycie goto jest wskazane np. przy
natychmiastowym opuszczaniu wielokrotnie zagnieżdżonych pętli. Można sobie bez niej

poradzić ale program byłby wtedy znacznie mniej czytelny. Ale pamiętaj : używaj jej w
ostateczności.

Przykład:


cout <<”poczatek\n”;

goto Etykieta1;
cout << ”tego nie wypisze”;

Etykieta1: cout << ”koniec\n”;


Wynik to oczywiście:

poczatek

24

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

koniec




25

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 7 Cout czy printf ?

O tych dwóch instrukcjach już wspomniałem wcześniej. Jak już wiesz, służą one do

wypisywania napisów na ekranie. Ponieważ jeszcze przez dość długi czas omawiane
przykłady będą opierały się na trybie dosowym postanowiłem dokładniej omówić te

funkcje.


Printf


Jest to funkcja znajdująca się w bibliotece stdio.h – aby z niej skorzystać musisz dodać

na początku kodu:

#include ”stdio.h”
Jej składnia wygląda następująco:

printf(const char *format[, argument, ...]);

Wygląda to paskudnie więc już tłumaczę. Parametrem tej funkcji jest zawsze ciąg

znaków (może być pusty). Ciągi znaków zawsze zapisujemy w cudzysłowach. Może być
zatem następujące wywołanie:

printf(”To trzeba wypisac”);

Na ekranie pojawi się napis: to trzeba wypisac
Jak wspomniałem ciąg może być pusty, zatem poprawnie jest także wywołanie

printf(””);

W tym przypadku nic nie zostanie wypisane.

Jest jednak coś, co sprawia, że ta funkcja jest bardzo wygodna w użyciu. Są to tzw.
Specyfikatory formatu ( ang. format specifiers). Nie będę tu omawiał wszystkich

ponieważ jest ich zbyt dużo a wiele z nich pewnie nigdy nie użyjesz. Warto skupić się

jednak na najważniejszych, czyli tych, które najczęściej są używane.
Co to jest specyfikator formatu?

Jest to wyrażenie, które określa format wyświetlanej informacji. Specyfikatory formatu
zawsze są podawane w ciągu znaków i zaczynają się od znaku %.

Myślę, że najlepiej będzię wytłumaczyć to na prostym przykładzie.

Załóżmy, że mamy jakąś zmienna wynik typu integer i chcemy wyświetlić ją na ekranie.
Umożliwia to właśnie funkcja printf a wygląda to tak:

int wynik;
wynik = 2*4+2;

printf(”W zmiennej wynik przechowywana jest wartosc = %i ”,wynik);

26

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

Na ekranie ukaże się napis:
W zmiennej wynik przechowywana jest wartosc = 10

A teraz opis działania.
Jak zapewne widzisz w wywołaniu funkcji printf mamy ciąg znaków oraz zmienną wynik

( po przecinku). Tutaj, choć dopiero funkcje zostaną omówione w następnych
rozdziałach, muszę już zapowiedzieć, że przy wywołaniu funkcji można użyć od zera do

n argumentów. Jeżeli wywołujemy funkcje z więcej niż jednym argumentem to musimy

je rozdzielić przecinkami.
Właśnie w naszym przypadku jest taka sytuacja. Funkcja printf jest wywoływana z

dwoma argumentami – zatem wywołanie ma postać printf( argument1, argument 2).
Wracając do specyfikatorów formatu – zauważ, że pierwszym argumentem jest, tak jak

to było do tej pory, ciąg znaków (czyli string). Różni się on tylko tym, że w jego wnętrzu
mamy znak % a po nim literkę „i”. Tutaj tkwi właśnie cała tajemnica. Literka „i” to skrót

od angielskiego integer czyli typu zmiennej, który zadeklarowaliśmy. Taki zapis mówi

kompilatorowi, że chcemy aby została wyświetlona dana w postaci integer. Tą daną jest
zmienna wynik i dlatego umieszczamy ją jako drugi argument. Oczywiście można użyć

większej ilości zmiennych i nie muszą to być zmienne typu integer.

Przykład:

int zmienna1, zmienna2; // deklarujemy dwie zmienne typu integer

zmienna1 = 14;

zmienna2 = zmienna1 / 2; // zmienna2 to polowa ze zmiennej1

printf(” zmienna 1 = %i \n zmienna 2 = %i ”, zmienna1, zmienna2);


Wynik to:

zmienna 1 = 14
zmienna 2 = 7

W powyższym programie mamy trzy parametry w wywołaniu printf. Jest to
spowodowane faktem, że zastosowaliśmy dwa specyfikatory formatu – musieliśmy

dodać do nich zmienne.
Zawsze specyfikatory czytamy od lewej do prawej i podstawiamy za nie kolejne

argumenty, które są wymienione we funkcji printf.
UWAGA!!! Nie możemy podać za małej ilości argumentów. Choć program się skompiluje

bez błędów to wynik będzie zły – w miejscu „niepokrytych” specyfikatorów zostaną

wstawione dziwne liczby. Możesz sam to sprawdzić. Odwrotna sytuacja tzn. jest więcej
argumentów za stringiem niż specyfikatorów w stringu nie spowoduje żadnych błędów

wyświetlania – nie zostaną wykorzystane wszystkie argumenty.

Specyfikatory mają rozmaite właściwości i zastosowanie. Za ich pomocą można np.

określić liczbę miejsc po przecinku wyświetlanej liczby albo sposób zaokrąglania liczb
itd...

27

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

Pełną listę specyfikatorów możesz znaleźć w dodatku B.


Cout


Jest to funkcja znajdująca się w bibliotece iostream.h – aby z niej skorzystać musisz

dodać na początku kodu:
#include ”iostream.h”

Funkcja cout jest jedną z tzw. Funkcji strumieniowych ( ang. stream – strumień).
Strumień to dane „płynące” od źródła do celu np. z klawiatury na ekran. Funkcja cout

zostałą wprowadzona dopiero w języku C++ ( printf było już w C ). Jej użycie w wielu
przypadkach jest znacznie wygodniejsze od zastosowania printf , przede wszystkim

wtedy, gdy mamy do wyświetlenia dużą liczbę zmiennych. Jej użycie jest bardzo proste
np.

cout << ”Na ekran \n”;

Jak widać można w niej używać także symboli specjalnych ( patrz dodatek A), tutaj
mamy \n czyli znak nowej linii. Możliwe jest również takie wywołanie:

cout << ”napis1” << ”napis2”;
Funkcja wypisze na ekranie:

napis1napis2


A jak wygląda wyprowadzanie na ekran wartości zmiennych ?


Bardzo prosto. Rozważmy przykład omawiany przy funkcji printf.

Dla przypomnienia :

int zmienna1, zmienna2; // deklarujemy dwie zmienne typu integer

zmienna1 = 14;

zmienna2 = zmienna1 / 2; // zmienna2 to polowa ze zmiennej1

printf(” zmienna 1 = %i \n zmienna 2 = %i ”, zmienna1, zmienna2);


Wynik to:

zmienna 1 = 14
zmienna 2 = 7


Napiszmy to samo z zastosowaniem cout.

Przykład:

int zmienna1, zmienna2; // deklarujemy dwie zmienne typu integer

zmienna1 = 14;

zmienna2 = zmienna1 / 2; // zmienna2 to polowa ze zmiennej1
cout <<” zmienna 1 = ” <<zmienna1 << ”\n zmienna 2 = ”<< zmienna2;

Wynik to:

28

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

zmienna 1 = 14

zmienna 2 = 7

Jak widać wyprowadzenie zmiennej na ekran jest bardzo proste. Wystarczy napisać :

cout << zmienna1;

A co z formatowaniem wyjścia ??
Tutaj NIE możemy zastosować żadnych specyfikatorów typu. Istnieją jednak tzw.

manipulatory ale o tym w następnym rozdziale.

29

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 8 Manipulatory

Manipulatory to specjalne rozkazy, które „wrzucamy” do strumienia. W łatwy sposób

umożliwiają formatowanie strumienia.
Przykład.

Wiesz już, że możemy wyświetlić tekst w taki sposób:

cout << ”jakiś tekst”;

A co gdybyśmy chcieli wyświetlić w postaci heksadecymalnej zmienną?
Wystarczy, że napiszemy

cout << hex << nazwa_zmiennej;


W tym przypadku manipulatorem jest hex, który „mówi” strumieniowi, że dane mają być

wyświetlane w postaci heksadecymalnej. Warto zauważyć, że manipulatory nie są
wyświetlane na ekranie.

Wyróżniamy manipulatory bezargumentowe i argumentowe czyli, ładnie mówiąc po
polsku, parametryzowane. Omówię osobno każdy z manipulatorów.


Manipulatory bezargumentowe.

1. Manipulator ws.
Skrót pochodzi od angielskiego white spaces czyli białe znaki. Powoduje on

przeskoczenie wszystkich tzw. białych znaków takich jak np. tabulatory, spacje itp.

2. Manipulator ends.

Powoduje wstawienie znaku końca napisu (NULL) (z ang. end of string – koniec
napisu). Stosowany przeważnie gdy wypisujemy coś nie na ekran, lecz np. do pliku ,

czy też do tablicy znaków – odpowiednika typu string z Pascala(uwaga dla
wtajemniczonych).

3. Manipulator endl.
Jest to chyba najczęściej wykorzystywany manipulator. Jak sama nazwa wskazuje (z

ang. end of line – koniec linii) jego wstawienie powoduje zakończenie linii np.
cout << ”jestem wspaniały” << endl << „ i wielki.”;

Da w rezultacie napis:
Jestem wspaniały

30

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

i wielki.


4. Manipulatory oct, dec, hex.

Te trzy manipulatory mają bardzo podobne działanie. Ich zadaniem, jak zapewne się

domyślasz, jest formatowanie liczb.
oct – ustawia formatowanie na tryb oktalny(ósemkowy),

dec - ustawia formatownie na tryb dziesiętny,
hex – ustawia formatowanie na tryb heksadecymalny.

Takie manipulatory ułatwiają do maksimum zmianę formatu wyświetlanych liczb np.
cout << dec << nazwa_zmiennej << ” a ósemkowo = ” << oct <<

nazwa_zmiennej << ”a heksadecymalnie = ” << hex << nazwa_zmiennej;

5. Manipulator flush.
Strumień danych może być buforowany. Oznacza to, że dane nie trafiają natychmiast

po wysłaniu do celu, lecz są przechowywane w specjalnej pamięci zwanej buforem,

czyli jakby ”poczekalnią” a dopiero potem przesyłane dalej. Manipulator flush
stosujemy wówczas, gdy chcemy natychmiastowo opróżnić bufor. Jest to przydatne

szczególnie podczas debugowanie programów, gdy chcemy na bieżąco śledzić to co
dzieje się w programie.

Manipulatory argumentowe (parametryzowane).

1. Manipulator setprecision.

Wywołanie tego manipulatora ma postać setprecision(int), gdzie int w nawiasie
oznacza liczbę typu całkowitego. Przy pominięciu manipulatora domyślnie

zostanie przyjęta szóstka. Manipulator setprecision, jak sama nazwa wskazuje,

pozwala na ustalenie precyzji z jaką wyświetlana jest liczba zmiennoprzecinkowa.
Przykład:

#include ”iostream.h”

int main(void)
{

double x = 2333.123456789; // deklaracja i definicja zmiennej x

cout << x << endl;

// wykorzystujemy manipulator endl

cout << setprecision(3) << x << endl << setprecision(10) << x;

return 0;

}

Wynik:

2333.123456

2333.123

2333.1234567890

2. Manipulator setbase.

Jest to jakby odpowiednik manipulatorów bezargumentowych hex, bin, oct.
Wywołanie ma postać setbase(int) gdzie wartość zmiennej int określa rodzaj

systemu liczenia.

31

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

Przykład:

#include ”iostream.h”

int main(void)

{

int x = 134;

// deklaracja i definicja zmiennej x

cout << x << endl; // wykorzystujemy manipulator endl
cout << setbase(2) << x << endl << setbase(8) << x;

return 0;

}

Wynik:
134

10000110

206

Jak widać manipulatory np. hex i setbase(16) są sobie równoważne.

Uwaga: Jeżeli ustawimy setbase(0) to dla strumienia wyjściowego zostanie

przypisany system dziesiętny a dla strumienia wejściowego nie zostanie
przypisany żaden konkretny system. Konwersja będzie się odbywać na podstawie

formatu wprowadzanej liczby. (Np. zapis 0x2345 sugeruje, że mamy do czynienia
z liczbą heksadecymalną).

3. Manipulator setfill. - cdn
4. Manipulator setw. - cdn


UWAGA !!! Aby użyć manipulatorów parametryzowanych musisz dodać bibliotekę

”iomanip.h”.





32

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński



33

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

ozdział 9 Funkcje

W poprzednich rozdziałach, w niektórych miejscach, pojawiły się zapisy funkcji. Celowo

zwlekałem z wprowadzeniem tego pojęcia aż do tego rozdziału. Wynika to z chęci
jednoczesnego wprowadzenia pojęcia funkcji oraz metody i wyjaśnienia różnicy między

tymi pojęciami. Do tego celu potrzebne będzie omówienie podstaw obiektowości, która

dotyczy nie tylko języka C++.
Wracając do pojęcia samej funkcji. Można powiedzieć, że jest to wydzielona część kodu

realizująca określone zadanie. Oczywiście ktoś może powiedzieć, że funkcja może nic nie
robić, więc nie realizuje też żadnego zadania. To prawda, jednak taki funkcje są

rzadkością i bywają wykorzystywane tylko w nielicznych przypadkach i to w sytuacjach

bardzo nietypowych. W swoich programach powinieneś/aś unikać takich funkcji, chyba
że stanowią one pewien etap przejściowy.

Podstawowy format funkcji w języku C++ wygląda następująco:

Parametr_zwracany nazwa_funkcji(argumenty funkcji)

{

ciało funkcji
}

Parametr zwracany – jest to typ zwracanego przez funkcję wyniku. Być może samo

sformułowanie „zwracanie wyniku” jest niezbyt eleganckie ale bardzo często jest
wykorzystywane przez programistów. Oznacza ono przekazanie wyliczonego wyniku do

miejsca w programie, gdzie ta funkcja została wywołana.

Nazwa funkcji – funkcję identyfikujemy przez jej nazwę – uwaga – nie może zaczynać
się od cyfr oraz być słowem zastrzeżonym języka C, ważna jest wielkość liter.

Argumenty – lista oddzielonych przecinkiem argumentów funkcji, czyli tego co chcemy
funkcji przekazać.


Przykład:

int multiple(int a, int b)
{

int

amulb;

amulb = a * b;

result

amulb;

34

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

}

Powyższy fragment kodu to funkcja o nazwie multiple, która mnoży przez siebie dwie

liczby podane na wejściu i zwraca obliczoną liczbę jako wynik swojego działania.
Zwrócenie następuje przez zapis result co_zwrócić. Należy pamiętać, że zwrócić można

tylko taką zmienną jaka została zadeklarowana w nagłówku funkcji.
Warto też dodać, że powyższą funkcję można znacznie uprościć.

int multiple(int a, int b)

{

result a * b;

}

Jak widać, nie trzeba specjalnie tworzyć zmiennej, którą chcemy zwrócić, kompilator
zadba o to sam.


Jak użyć takiej funkcji ?

Najlepszą ilustracją będzie kolejny przykład.

#include ”stdio.h”

int multiple(int a, int b)
{

result a * b;

}

void main(void)
{

int

a;

int

b;

a = 5;

b = 7;

int

c;

c = multiple(a,b);

printf(”Obliczona

wartośc %i\n”,c);

// ten sam efekt

printf(”Krocej to samo %i\n”,multiple(5,7));

}

Wynik:
Obliczona wartość 35

Krócej to samo 35


Komentarz:

Definicja funkcji znajduje się na początku programu, zaraz po sekcji include. Następnie
jest zapis

35

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński

void main(void) – czy zauważyłeś podobieństwo do funkcji? Tak, jest to funkcja, ale

bardzo specyficzna. Praktycznie każdy program musi ją mieć. Jak widać, zamiast
argumentów i zwracanego typu widnieje napis „void”. Najprościej mówiąc jest to „nic”.

Inaczej – zapis:

main()
{

//...

}

będzie działał w większości kompilatorów równie dobrze (Czasami wymagane jest
wstawienie void – w zależności od używanego kompilatora).

Funkcja main to miejsce w którym rozpoczyna się działanie programu. Zaraz po

uruchomieniu następuje wywołanie tej funkcji (automatyczne – sami nie możemy jej
wywołąć!!!) i przetwarzanie kolejnych rozkazów. Pominięte zostają wszelkie

wcześniejsze struktury, nawet jeżeli znajdują się przed funkcją main.
Kolejno zostają zadeklarowane dwie zmienne typu int, przypisane im wartości,

deklaracja kolejnej zmiennej dla przechowania wyniku a następnie wywołanie funkcji.

Jako argumentów używamy wcześniej zdefiniowanych zmiennych(a,b) a wynik
przypisujemy do zmiennej c. Zapis

C = multiple(a,b);

oznacza, że to co zostało wyliczone przez multiple (czyli to co zwraca ta metoda) zostaje
przypisane do zmiennej c. Pamiętaj, że przetwarzanie rozpoczyna się od prawej strony,

zatem najpierw zostaje wyliczona funkcja, potem jest przypisanie.
Taki sam efekt działania programu można uzyskać bez deklarowania jakichkolwiek

zmiennych. Jest to dobre tylko w przypadku, gdy zmienne te nie byłyby potrzebne w

dalszej części programu.

Uwaga: deklaracja funkcji powinna być przed miejscem jej wywołania ! Oznacza to, że
gdybyśmy definicję multiple wstawili po funkcji main, kompilator wyrzuciłby bład.

36

background image

Kurs języka C++ www.kurs-cpp.prv.pl

Paweł Boiński



Dodatek A

Funkcja Symbol

Nazwa

C+

Nowy wiersz

Tabulacja pozioma
Tabulacja pionowa

O jeden znak do tyłu
Powrót karetki

Nowa strona

Lewy ukośnik
Pytajnik

Liczba ósemkowa
Liczba szesnastkowa

Apostrof

Cydzysłów

NL

HT
VT

BS
CR

FF

\
?

ooo
hhh

\n

\t
\v

\b
\r

\f

\\
\?

\ooo
\xhhh

\’

\“


37


Document Outline


Wyszukiwarka

Podobne podstrony:
ZAIMEK ZWROTNY, Kurs Jezyka hiszpanskiego
Completa la frases en de, Kurs Jezyka hiszpanskiego
ANGIELSKI, Unit one1, Kurs języka angielskiego ENJOY YOUR ENGLISH
Kurs języka Łacińskiego Łacina
ser estar hay teoria, Kurs Jezyka hiszpanskiego
la casa slownictwo, Kurs Jezyka hiszpanskiego
cw.odmiana czasownika, Kurs Jezyka hiszpanskiego
RZECZOWNIKI, Kurs Jezyka hiszpanskiego
Kurs języka Turbo Pascal(1)
Oferta - kurs jezyka medycznego, OPIEKUN MEDYCZNY
Czas. zwr. zaimki zwr. teoria, Kurs Jezyka hiszpanskiego
Cwiczenie pytania i odpowiedzi, Kurs Jezyka hiszpanskiego
Cw ser estar hay, Kurs Jezyka hiszpanskiego
ZAIMKI I PRZYSŁÓWKI PYTAJĄCE, Kurs Jezyka hiszpanskiego
LA CASA-dialog, Kurs Jezyka hiszpanskiego

więcej podobnych podstron