cpp cwiczenia podstawowe 1 Kluczewski


PROGRAMOWANIE OBIEKTOWE
Ćwiczenia podstawowe Cz. I
" Kompilacja i linkowanie
" Pierwszy program w C++
" Rozpoznawanie błędów
" Zmienne
" Instrukcja warunkowa
" Rodzaje zmiennych
" Wskazniki
" Iteracje
" Macierze
" Tablice i wskazniki
" Dynamiczny przydział pamięci
©2008 Jerzy Kluczewski
2 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
I. Kompilacja i linkowanie
Za pomocą środowiska Borland C++ Builder, będziemy kodować, kompilować i
likować programy (Rys .1).
kod zródłowy
kompilacja
linkowanie
plik wykonywalny
Polecenie w C++ Builder: Make lub Build
powoduj,e \e kod zródłowy będzie poddany
kompilacji, i jeśli nie będzie błędów to nastąpi
linkowanie bibliotek i tworzenie pliku
wykonywalnego.
Rys. 1. Proces tworzenia pliku wykonywalnego.
Najprostszy program
Najprostszy program w C++ zawiera funkcję main, która zawsze zwraca wartość
całkowitą. Nawiasy okrągłe oznaczają, ze mamy do czynienia funkcją. Nawiasy
klamrowe do wpisywania miedzy nimi, treści funkcji (wpisujemy tam instrukcje języka
C++).
int main()
{
}
Program ten nic nie robi, więc nie ma celu praktycznego.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 3
______________________________________________________________________
Prawdziwy program
Praktyczny, prawdziwy program w C++ będzie wyświetlał na ekranie napis Moj drugi
program. Aby operator cout był właściwie zinterpretowany, nale\y na początku wpisać
linię #include . iostream to biblioteka języka C++ słu\ąca do obsługi
klawiatury i ekranu. Operator << słu\y do skierowania napisu do ekranu. Ekranem jest
tu symbol cout. Funkcja system z parametrem "pause" słu\y do zatrzymania pracy
programy i wyczekiwaniem przez niego na naciśnięcie dowolnego klawisza.
#include
int main()
{
cout << "Moj drugi program";
system("pause");
}
Standard opisu języka C++ umo\liwia pisanie programów z u\yciem tzw. przestrzeni
nazw, program powy\szy będzie wyglądał następująco (dwie wersje jednakowo
działające):
#include #include
using namespace std; #include
int main() int main()
{ {
cout << "Moj drugi program"; std::cout << "Moj drugi program";
system("pause"); system("pause");
} }
II. Rozpoznawanie błędów
Kompilacja to proces tłumaczenia kodu zródłowego na kod zrozumiały dla danego
procesora. Powstaje plik pośredni (OBJ). Konsolidacja (linkowanie) to utworzenie z
pliku pośredniego programu wynikowego, który będzie mo\na uruchamiać jako
aplikację. W tracie linkowania plik pośredni jest łączony z dodatkowymi bibliotekami
(modułami, pakietami).
Ka\dy programista musi pogodzić się z faktem, \e pisząc programy, będzie
jednocześnie popełniał błędy. Szczególnie nara\one na pomyłki są osoby początkujące.
©2008 Jerzy Kluczewski
4 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Błędy mo\na podzielić na trzy grupy:
" występujące na etapie kompilacji i sygnalizowane przez kompilator (Rys. 2),
" występujące w trakcie działania programu, powodujące jego zatrzymanie,
" błędy logiczne nie powodujące komunikatów kompilatora, ani zatrzymania
programu, ale powodujące błędne jego działanie (na przykład program
produkuje błędne wyniki).
Rys. 2. Błędy kompilacji
Dziwny błąd linkera
Początkujący u\ytkownicy środowiska Borland C++ często spotykają się z błędem,
który pojawia się podczas kompilacji projektu. Objawia się on dziwnym komunikatem
w postaci:
[Linker Fatal Error] Fatal: Expected a file name:
Jak widać ta linia komunikatu informuje programistę, \e błąd nie wystąpił w etapie
kompilacji, lecz linkowania, czyli konsolidacji. Przyczyna tego błędu jest bardzo prosta
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 5
______________________________________________________________________
Otó\ programista zapisał pliki projektu w katalogu o ście\ce w której znajdują się znaki
niedozwolone dla środowiska Borland C++. Na ście\ce dostępu do projektu
C:\Program Files\Borland\CBuilder6\Projects\c++ znajdują się znaki c++, które
zawierają ++, a to przez linker środowiska Borland C++ zostało zrozumiane jako część
komendy, a nie katalog. RozwiÄ…zaniem naprawczym jest po prostu zmiana nazwy
katalogu na taką aby zawierały wyłącznie znaki alfabetu łacińskiego (ewentualnie znaki
podkreślenia i cyfry).
Niezadeklarowana zmienna
Ka\dą zmienną przed u\yciem nale\y zadeklarować. W przeciwnym razie wystąpi błąd
kompilacji. Na przykład w programie errory.cpp, w linii 5 wystąpi błąd:
[C++ Error] terrory.cpp (5): E2451 Undefined symbol  z .
int main()
{
for (int i =0; i < 5; i++)
{
z = i * 5;
}
return 0;
}
Program errory.cpp
Przyczyna: brak deklaracji zmiennej z.
Literówki
Literówki popełniają nawet zaawansowani programiści, na szczęście te błędy są łatwe
do wykrycia. W programie trzeci.cpp, w linii 5 wystąpi błąd:
[C++ Error] trzeci.cpp (5): E2335 Overloaded  count ambiguous in this context.
#include
using namespace std;
int main()
{
count << "Moj trzeci program";
system("pause");
return 0;
}
Program trzeci.cpp
Przyczyna: programista zamiast słowa cout u\ył count.
©2008 Jerzy Kluczewski
6 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Pliki nagłówkowe
W następnym programie czwarty.cpp, programista zapomniał dołączyć plik
nagłówkowy iostream, dlatego kompilator zgłosił błąd:
[C++ Error] czwarty.cpp (3): E2451 Undefined symbol  cout .
int main()
{
cout << "Moj czwarty program";
return 0;
}
Program czwarty.cpp
Przestrzenie nazw
W następnym programie piaty.cpp, programista zapomniał u\yć dyrektywy using
namespace std (standardowej przestrzeni nazw), aby zapewnić dostęp do nazw
zdefiniowanych w bibliotece iostream. W takim przypadku kompilator zgłosił błąd:
[C++ Error] piaty.cpp (4): E2451 Undefined symbol  cout .
#include
int main()
{
cout << "Moj piaty program";
return 0;
}
Program piaty.cpp
Koniec instrukcji
W kolejnym przykładzie szosty.cpp, popełniono banalny błąd, polegający na braku
średnika na końcu instrukcji cout << "Moj szosty program" (ka\da instrukcja musi
kończyć się średnikiem). W takim przypadku kompilator zgłosił błąd:
[C++ Error] szosty.cpp (6): E2379 Statement missing ;.
#include
using namespace std;
int main()
{
cout << "Moj szosty program"
return 0;
}
Program szosty.cpp
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 7
______________________________________________________________________
Cudzysłów
W programie siodmy.cpp, wprowadzono drobny błąd, polegający na braku średnika na
końcu instrukcji cout << "Moj szosty program". W takim przypadku kompilator
zgłosił błąd: [C++ Error] siodmy.cpp (3): E2034 Cannot convert  char* to  char .
Zadeklarowano zmiennÄ… dana o typie char. Ten typ pozwala na przechowywanie
znaków oraz niewielkich liczb całkowitych. Programista chciał przypisać tej zmiennej
jeden znak a. Aby to zrobić nale\y znak ująć w parę apostrofów. Prawidłowym zapisem
jest char dana =  a ;
int main()
{
char dana = "a";
return 0;
}
Program siodmy.cpp
Argumenty funkcji
Kolejny błąd często popełniany przez początkujących programistów wią\e się z
przekazywaniem argumentów do funkcji. Pokazuje to przykładowy program
errory2.cpp, którego zadaniem jest obliczenie drugiej potęgi wprowadzonej przez
u\ytkownika liczby. Za obliczenia odpowiada funkcja drugaPotega. Jaki będzie wynik
działania takiego programu, gdy podamy mu liczbę np. 5 ?
Podaj liczbe 5
Druga potega tej liczby to 5
#include
using namespace std;
void drugaPotega(double liczba)
{
liczba = liczba * liczba;
}
int main()
{
double liczba;
cout << "Podaj liczbe ";
cin >> liczba;
drugaPotega(liczba);
cout << "Druga potega tej liczby to "<< liczba;
system("pause");
return 0;
}
Program errory2.cpp
©2008 Jerzy Kluczewski
8 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Program nie działa prawidłowo. Stan zmiennej liczba nie zmienił się, wygląda to tak,
jakby funkcja drugaPotega nie została wykonana. Błąd jest w sposobie przekazywania
argumentu do funkcji. Aby na zewnątrz funkcji nastąpiła zmiana argumentu, nale\y
u\yć innego sposobu przekazywania argumentów. Wyró\niamy tutaj dwa sposoby:
" przekazywanie przez wskaznik,
" przekazywanie przez referencjÄ™
Pierwszy sposób (program argumenty1.cpp)
#include
using namespace std;
void drugaPotega(double* liczba)
{
*liczba = (*liczba) * (*liczba);
}
int main()
{
double liczba;
cout << "Podaj liczbe ";
cin >> liczba;
drugaPotega(&liczba);
cout << "Druga potega tej liczby to "<< liczba;
system("pause");
return 0;
}
Drugi sposób (program argumenty2.cpp)
#include
using namespace std;
void drugaPotega(double& liczba)
{
liczba = liczba * liczba;
}
int main()
{
double liczba;
cout << "Podaj liczbe ";
cin >> liczba;
drugaPotega(liczba);
cout << "Druga potega tej liczby to "<< liczba;
system("pause");
return 0;
}
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 9
______________________________________________________________________
III. Zmienne
Zmienne pozwalają na przechowywanie w programie danych. Ka\da zmienna ma swój
typ, który określa, jakiego rodzaju dane mo\e ona przechowywać. Typy występujące w
C++ mo\emy podzielić na następujące główne rodzaje (patrz rysunek Rys. 3):
" typy arytmetyczne,
" typ logiczny,
" typy specjalne.
Rys. 3. Podział typów
Ka\da zmienna, zanim zaczniemy jej u\ywać, musi zostać wcześniej zadeklarowana.
Deklaracja polega na podaniu typu oraz nazwy zmiennej (kończymy ją średnikiem,
bowiem w C++ deklaracja jest tzw. instrukcjÄ… deklarujÄ…cÄ…).
int liczba;
Została tu zadeklarowana zmienna o nazwie liczba, której typem jest int.
Oznacza to, \e będzie ona mogła przechowywać liczby całkowite. W platformach 32-
bitowych liczba ta jest reprezentowana jako słowo 32-bitowe. Zakres wartości takich
liczb całkowitych mieści się w przedziale od -2 147 483 648 do 2 147 483 647
Inicjowanie zmiennych
Pierwsze przypisanie wartości do zmiennej nazywamy jej inicjacją.
int liczba;
liczba = 100;
Takie przypisanie mo\e odbywać się zarówno po jej deklaracji, jak i w jej deklaracji.
Oto równowa\ny kod inicjowania zmiennej.
int liczba = 100;
©2008 Jerzy Kluczewski
10 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Jak nazywać zmienne?
ObowiÄ…zujÄ… tutaj pewne zasady. Nazwa zmiennej:
" mo\e składać się z du\ych i małych liter oraz cyfr,
" nie mo\e rozpoczynać się od cyfry,
" nie mo\na stosować w niej polskich znaków diakrytycznych,
Nazwa zmiennej powinna odzwierciedlać funkcję pełnioną w programie, co bardzo
poprawia czytelność kodu oraz ułatwia jego analizę.
Typ znakowy
Typ znakowy ma nazwę char i słu\y do reprezentowania znaków, ze zbioru znaków
ASCII. Zmienna typu char zajmuje w pamięci 8 bitów. Za jej pomocą mo\na
przedstawić 256 znaków. Jeśli chcemy przypisać do zmiennej jakiś znak, musimy ująć
go w apostrofy.
char zmienna =  z ;
Ten typ jest zaliczony do typów arytmetycznych, bo zmienne takie mo\emy traktować
jako liczby, na przykład znak  z ma kod ASCII 122. Zmienna typu char, w naszym
przykładzie, w rzeczywistości przechowuje liczbę 122. Zatem na takich zmiennych
mo\na wykonywać proste operacje arytmetyczne (dodawanie i odejmowanie).
Program zmienne1.cpp pokazuje, \e jest to mo\liwe; wyświetli on na ekranie literę  y .
#include
using namespace std;
int main()
{
char zmienna = 'z';
zmienna = zmienna  1;
cout << zmienna;
system("pause");
return 0;
}
Program zmienne1.cpp
Modyfikatory signed i unsigned
Zakres liczb jaki reprezentują typy całkowite i znakowe mo\na modyfikować. W tym
celu u\ywamy modyfikatorów signed i unsigned.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 11
______________________________________________________________________
#include
using namespace std;
int main()
{
signed zmienna1 =  2147483648;
unsigned zmienna2 = 4294967295;
cout << zmienna1 << " , " << zmienna2;
system("pause");
return 0;
}
Program zmienne2.cpp
Do zmiennej typu signed int mo\na przypisywać liczby całkowite ujemne i dodatnie.
Do zmiennej typu unsigned int mo\na przypisywać tylko liczby całkowite dodatnie, ale
o większej wartości. Dlatego \e w przypadku typu signed int ostatni (31 bit) jest
zarezerwowany do sygnalizowania, czy jest to liczba ujemna, czy dodatnia (czyli
określa znak liczby). W przypadku typu bezznakowego unsigned int, wszystkie bity
reprezentują wartość liczby.
typ liczba bitów Zakres
unsigned int X 32 0 <= X <= 4 294 967 295
signed int X 32 -2 147 483 648 <= X <= 2 147 483 647
Uwaga: Liczba kombinacji dla signed int, 231=2 147 483 648, dla unsigned int
232=4 294 967 296.
Liczby zmiennoprzecinkowe
Do reprezentacji liczb zmiennoprzecinkowych, czyli takich z częścią ułamkową słu\ą
typy float, double i long double.
typ liczba bitów Zakres
float Y 32 3.4 * (10**-38) <= Y <= 3.4 * (10**+38)
double Y 64 1.7 * (10**-308) <= Y <= 1.7 * (10**+308)
long double Y 80 3.4 * (10**-4932) <= Y <= 3.4 * (10**+4932)
Istnieją dwa sposobu przypisywania wartości takim zmiennych. Pierwszy polega na \e
część ułamkową przedstawiamy po kropce dziesiętnej 1023.4. Drugi sposób to zapis
wykładniczy. 10.234e2 oznacza 10,234 razy 10 do potęgi 2.
y = 1023.4;
z = 10.234e2;
©2008 Jerzy Kluczewski
12 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
IV. Instrukcja warunkowa
Instrukcje warunkowe są niezbędne do działania ka\dego bardziej rozbudowanego
programu. Podstawowa instrukcja warunkowa w C++ to instrukcja if. W najprostszej
postaci mo\na ją zapisać w jednej linii kodu:
if (warunek) instrukcja;
Nale\y ją rozumieć następująco: Je\eli
warunek jest prawdziwy, to wykonaj
instrukcję. Jako warunek najczęściej wykorzystujemy wyra\enie zawierające
instrukcję porównania, korzystające z jednego z operatorów porównania. Operatory
opisano na rysunku Rys. 4.
OPERATORY PORÓWNANIA
Operator Przykład Znaczenie
= = a = = b a równe b
! = a ! = b a ró\ne od b
< a < b a mniejsze od b
> a > b a większe od b
< = a < = b a mniejsze lub równe b
> = a > = b a większe lub równe b
#include
using namespace std;
int main()
{
int a = 5;
int b = 6;
if (a < b) cout << "a jest mniejsze od b" << endl;
system("pause");
return 0;
}
#include
using namespace std;
int main()
{
int a = 5;
int b = 6;
if (a > b) cout << "a jest wieksze od b" << endl;
else cout << "a jest mniejsze lub rowne b" << endl;
system("pause");
return 0;
}
Rys. 4. Operatory porównania.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 13
______________________________________________________________________
Gdy po radzeniu warunku, gdy jest on prawdziwy, wystÄ…pi potrzeba wykonania kilku
instrukcji, nale\y je ująć w nawiasy klamrowe (tzw. blok instrukcji).
if (warunek) {
instrukcja1;
instrukcja2;
instrukcja3;
instrukcja4;
}
Kolejną instrukcją formą instrukcji warunkowej jest instrukcja if& else. Jej ogólna
postać jest następująca:
if (warunek) {
instrukcja1;
}
else {
instrukcja2;
}
Instrukcja warunkowa zagnie\d\ona
Bardzo często w programach zachodzi konieczność sprawdzania wielu warunków w
jednej instrukcji if. Nazywamy ją zagnie\d\oną instrukcją warunkową. Przykładowy
kod wykorzystujący tą postać instrukcji pokazany jest następujący:
int a, b;
cout << "Podaj pierwsza liczbe:" << endl;
cin >> a;
cout << "Podaj druga liczbe:" << endl;
cin >> b;
cout << "a=" << a << ", " << "b=" << b << endl;
if (a = = b) {
cout << "a jest rowne b" << endl;
}
else if (a < b) {
cout << "a jest mniejsze od b" << endl;
}
else if (a > b) {
cout << "a jest wieksze od b" << endl;
}
©2008 Jerzy Kluczewski
14 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
V. Rodzaje zmiennych
Korzystając ze zmiennych, nale\y przestrzegać wa\nych zasad. Inaczej program będzie
działał losowo. Zasady te, to świadomy wybór deklarowania zmiennych jako lokalnych
lub globalnych.
Zmienne lokalne
W programie zmienne2.cpp, zmienne zadeklarowane w ciele funkcji nazywamy
zmiennymi lokalnymi. Nazwa wzięła się stąd, \e są one dostępne jedynie w funkcji, w
której zostały zadeklarowane i \adna inna funkcja nie ma do nich dostępu. Mo\na je
zatem traktować jako prywatną własność danej funkcji.
#include
using namespace std;
void funkcja1()
{
int liczba1;
int liczba2;
Zasięg zmiennych
liczba1 = 100;
lokalnych
liczba2 = 200;
cout << "Liczba1=" << liczba1 << endl;
cout << "Liczba2=" << liczba2 << endl;
}
int main()
{
funkcja1();
system("pause");
return 0;
}
Program zmienne2.cpp.
Ka\da próba u\ycia zmiennej lokalnej poza jej zasięgiem (poza nawiasami
klamrowymi wewnątrz których została zadeklarowana) skutkuje błędem kompilatora
Undefined symbol.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 15
______________________________________________________________________
Zmienne globalne
Zmienne globalne, jak łatwo się domyślić są przeciwieństwem zmiennych lokalnych.
Nie zale\ą one do \adnej funkcji, mogą być za to wykorzystywane we wszystkich
funkcjach. Zmienna globalna musi zostać zadeklarowana przed definicjami funkcji.
Najlepiej to zobaczyć na konkretnych przykładach.
W programie zmienne3.cpp została zadeklarowana jedna zmienna globalna o nazwie
liczba1 oraz dwie funkcje main i funkcja3. Poniewa\ deklaracja zmiennej liczba1
znajduje siÄ™ przed definicjami funkcji, zmienna ta jest widoczna w obu funkcjach.
#include
using namespace std;
int liczba1;
void funkcja3()
{
liczba1 = 200;
}
int main()
{
liczba1 = 100;
cout << "liczba1 przed wywolaniem fukcji funkcja3: ";
cout << liczba1 << endl;
funkcja3();
cout << "liczba1 po wywolaniu fukcji funkcja3: ";
cout << liczba1 << endl;
system("pause");
return 0;
}
Program zmienne3.cpp.
Program wygeneruje na ekranie następujące wiersze:
liczba1 przed wywolaniem fukcji funkcja3: 100
liczba1 po wywolaniu fukcji funkcja3: 200
Zmienne modułowe
Zmienne zadeklarowane na początku kodu zródłowego w rzeczywistości są globalne
tylko obrębie jednego pliku z kodem zródłowym. W przypadku prostych programów,
składających się z jednego tylko pliku, są oczywiście globalne dla całego programu. W
przypadku bardziej skomplikowanych aplikacji wieloplikowych, niestety nie. Dlatego
zmienne te nazywa się równie\ zmiennymi modułowymi lub zmiennymi o zasięgu
modułowym.
©2008 Jerzy Kluczewski
16 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Przesłanianie zmiennych globalnych
W programie zmienne4.cpp mamy zadeklarowane dwie zmienne: liczba1 i liczba1.
Wydawałoby się \e występuje tu konflikt nazw, bowiem obie mają tą są nazwę. Jest to
jednak konflikt pozorny  wszystko jest w porzÄ…dku, dlatego \e to kompilator decyduje
która zmienna jest zmienną globalną a która lokalną. Poza funkcją main program widzi
tylko zmienną globalną równą 200. Funkcja main rozpoczynając swoje działanie, widzi
tylko zmienną lokalną o wartości 100. Po prostu wewnątrz funkcji zmienna globalna
zostaje przesłonięta przez lokalną.
#include
using namespace std;
int liczba1 = 200;
int main()
{
int liczba1 = 100;
cout << "zmienna lokalna liczba1 ma wartosc: " << liczba1 << endl;
cout << "zmienna globalna liczba1 ma wartosc: " << ::liczba1 << endl;
::liczba1 = liczba1;
cout << "zmienna globalna liczba1 ma wartosc: " << ::liczba1 << endl;
system("pause");
return 0;
}
Program zmienne4.cpp.
Wynik działania programu:
zmienna lokalna liczba1 ma wartosc: 100
zmienna globalna liczba1 ma wartosc: 200
zmienna globalna liczba1 ma wartosc: 100
Na szczęście język C++ posiada sposób na uzyskiwanie dostępu do zmiennych
globalnych w momentach w których są one przesłonięte. Słu\y do tego operator
zasięgu (podwójny dwukropek). W instrukcji ::liczba1 = liczba1; następuje
przekazanie wartości zmiennej lokalnej do zmiennej globalnej. Zmienna globalna
otrzymuje wartość100, co potwierdza wyniki działania przykładowego programu.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 17
______________________________________________________________________
VI. Wskazniki
Znajomość wskazników jest potrzebna ka\demu programiście, jak człowiekowi tlen do
oddychania. Wskaznik to specjalny typ danych, który wskazuje na inne dane.
Najczęściej wskaznik traktuje się jako wskazanie pewnego miejsca pamięci komputera.
W miejscu tym mo\e znajdować się zmienna, funkcja czy inny obiekt. Praktycznie
mo\na skonstruować wskaznik do dowolnego typu danych, czy to do typu int, char,
czy te\ stworzonego przez programistÄ™.
Typ wskaznikowy
Typ wskaznikowy konstruuje się w bardzo prosty sposób  do nazwy typu
(podstawowego) nale\y dodać znak * (gwiazdka). Oznacza to \e jeśli typem
podstawowym jest int, to wskaznik do int zapisywany jest jako int*.
Znak * jest w C++ wykorzystywany jako operator mno\enia, ale kompilator bez trudu
poradzi sobie z tą sytuacją, odczytując właściwe znaczenie znaku * z kontekstu.
Przykład deklaracji zmiennych typu int*:
int* liczba1;
int* liczba2;
int* liczba3;
Zadeklarowano trzy wskazniki (trzy zmienne wskaznikowe) wskazujÄ…ce typ int.
Przykład deklaracji zmiennych typu int:
int liczba1;
int liczba2;
int liczba3;
Zadeklarowano trzy zmienne typu int.
UWAGA: Przykład nieprawidłowej deklaracji zmiennych typu int*:
int* liczba1, liczba2, liczba3;
Zadeklarowano jeden wskaznik liczba1 wskazujÄ…cy typ int oraz dwie zmienne typu
int. Nale\y starać się unikać takiego stylu deklarowania zmiennych wskaznikowych!
Przykład prawidłowej deklaracji zmiennych typu int:
int liczba1, liczba2, liczba3;
Zadeklarowano trzy zmienne typu int.
©2008 Jerzy Kluczewski
18 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
W przykładowym programie pointer1.cpp mamy zadeklarowane trzy wskazniki
(zmienne wskaznikowe): liczba1, liczba2, liczba3. oraz jednÄ… zmiennÄ… liczba4 typu int.
Zmiennej liczba4 przypisujemy wartość 100, następnie zmiennej wskaznikowej
liczba1, przypisujemy adres zmiennej liczba4. Znak & (ampersand) jest tzw.
operatorem pobrania adresu (operator adresowy). Po wyświetleniu wartości zmiennych
liczba4 i liczba1, otrzymujemy następujący wyniki:
zmienna liczba4 ma wartosc: 100
wskaznik liczba1 ma wartosc: 4203528
Drugą linię nale\y interpretować jako adres w pamięci komputera. Przypomnijmy sobie
\e zmienna wskaznikowa to taka sobie prosta zmienna, tylko adres jakiegoÅ› miejsca w
pamięci. Zmienna liczba4 znajduje się pod adresem 4203528 w pamięci .
#include
using namespace std;
int* liczba1;
int* liczba2;
int* liczba3;
int liczba4;
int main()
{
liczba4 = 100;
liczba1 = &liczba4;
cout << "zmienna liczba4 ma wartosc: " << liczba4 << endl;
cout << "wskaznik liczba1 ma wartosc: " << liczba1 << endl;
system("pause");
return 0;
}
Program pointer1.cpp
W języku C++ istnieje te\ operator odwrotny do operatora & a mianowicie operator
wyłuskania wartości (dereferencji) spod adresu pamięci. I o dziwo jest to znak
gwiazdka *, ale u\yta nie w deklaracji, tylko w instrukcji.
Jeśli do programu pinter1.cpp dopiszemy instrukcję
cout << *liczba1 << endl;
to uzyskamy następujący wynik:
100
Co nale\y zinterpretować jako  wartość 100 jest przechowywana w komórce pamięci o
adresie liczba1 .
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 19
______________________________________________________________________
Wskazniki do funkcji
W C++ mo\na tworzyć wskazniki do funkcji, poniewa\ kod funkcji znajduje się
przecie\ w pamięci, a zatem ma adres. Konstrukcja wskaznika jest trudniejsza ni\
wskaznika do zmiennej. Schemat definicji wskaznika do funkcji jest następujący:
typ_zwracany (*nazwa_wskaznika) (argumenty funkcji);
Konkretny przykład deklaracji wskaznika do funkcji:
void (*pfun) ();
Potem nale\y przypisać adres funkcji do wskaznika.
pfun = &fun();
A na koniec mo\na wywołać funkcję za pomocą wskaznika pfun.
(*pfun)();
Ostatnia instrukcja jest równowa\na następującej instrukcji (wywołanie bezpośrednie
funkcji):
fun ();
Kod programu pointer2.cpp pokazuje wykorzystanie wskaznika do wywołania funkcji
oraz operatora adresowego & do pobrania adresu funkcji.
#include
using namespace std;
void fun()
{
cout << "Wykonanie funkcji..." << endl;
}
int main()
{
void (*pfun)(); // deklaracja wskaznika do funkcji
pfun = &fun; // przypisanie adresu funkcji do wskaznika
(*pfun)(); // wywołanie funkcji za pomocą wskaznika pfun
fun(); // wywołanie bezpośrednie funkcji.
system("pause");
return 0;
}
Program pointer2.cpp
©2008 Jerzy Kluczewski
20 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Wskazniki do funkcji na skróty
Zamiast pisać:
pfun = &fun;
mo\na zastosować równowa\ną konstrukcję:
pfun = fun;
Podobnie zamiast:
(*pfun)();
mo\na napisać:
pfun();
ale taki zapis mo\e wprowadzić programistę w błąd, sugeruje bowiem, \e w kodzie
programu istnieje funkcja o nazwie pfun, której w rzeczywistości nie ma.
Wskazniki do klas
W odniesieniu do klas w C++ mo\na u\ywać wskazników w takim sam sposób, jak
u\ywaliśmy dotychczas (za pomocą operatorów * i &), lecz z u\yciem specjalnego
symbolu dwuznakowego  >.
Najlepiej będzie zaobserwować sposoby dostępu do składowych klasy na następującym
przykładzie klasy Tosoba:. Operacje będą wykonywane na obiekcie x klasy Tosoba.
#include
using namespace std;
class Tosoba
{
public:
char* nazwisko;
char* imie;
};
int main()
{
TOsoba x;
x.nazwisko = "Kowalski";
x.imie = "Jan";
cout << x.imie << " " << x.nazwisko << endl;
system("pause");
return 0;
}
Program pointer3.cpp  dostęp do klasy bez u\ycia wskazników.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 21
______________________________________________________________________
Drugi przykład (pointer4.cpp) zamiast deklaracji obiektu x klasy Tosoba zawiera
deklaracjÄ™ wskaznika pointerx do klasy Tosoba.
#include
using namespace std;
class Tosoba
{
public:
char* nazwisko;
char* imie;
int wiek;
};
int main()
{
TOsoba* pointerx;
pointerx >nazwisko = "Kowalski";
pointerx >imie = "Jan";
pointerx >wiek = 25;
cout << pointerx >imie << " " << pointerx >nazwisko << endl;
cout << "Wiek: " << pointerx >wiek << endl;
system("pause");
return 0;
}
Program pointer4.cpp  dostęp do klasy za pomocą wskazników.
Wskaznik do składowej klasy
Język C++ dostarcza mechanizm specjalnego dostępu do składowych klasy; jest to
alternatywny typ wskaznika, a mianowicie wskaznik do składowej klasy. Oto ten sam
przykład z uwzględnieniem nowego wskaznika (program pointer5.cpp).
#include
using namespace std;
class Tosoba
{
public:
char* nazwisko;
char* imie;
int wiek;
};
©2008 Jerzy Kluczewski
22 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
// ciÄ…g dalszy programu
int main()
{
Tosoba x;
char* Tosoba::*wsk1;
char* Tosoba::*wsk2;
int Tosoba::*wsk3;
x.nazwisko = "Nowak";
x.imie = "Jan";
x.wiek = 25;
wsk1 = &Tosoba::nazwisko;
wsk2 = &Tosoba::imie;
wsk3 = &Tosoba::wiek;
cout << x.*wsk2 << " " << x.*wsk1 << endl;
cout << x.*wsk3 << endl;
system("pause");
return 0;
}
Program pointer5.cpp  dostęp do składników klasy za pomocą operatora zasięgu :: oraz
wskazników.
VII. Iteracje czyli pętle
Aby fragment kodu wykonać wielokrotnie nale\y wykorzystać pętle. Pętla to instrukcja
wykonująca pewne, te same czynności wiele razy. W C++ występują dwie główne
odmiany pętli : instrukcja for i instrukcja for.
Pętla for
Ogólna postać instrukcji for to:
for (wyra\enie poczÄ…tkowe; wyra\enie warunkowe; wyra\enie modyfikujÄ…ce)
{
instrukcje do wykonania;
}
Wyra\enie początkowe słu\y do zainicjowania zmiennej u\ywanej jako licznik pętli.
Wyra\enie warunkowe określa warunek, jaki musi być spełnionym, aby wykonać
kolejne przejście w pętli (następną iterację).
Wyra\enie modyfikujące słu\y zwykle do modyfikacji zmiennej będącej licznikiem.
Działanie pętli for zostanie pokazane na przykładzie programu for1.cpp, którego
zadaniem jest 10-krotne wyświetlenie napisu  C++ Language .
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 23
______________________________________________________________________
#include
using namespace std;
int main()
{
for (int i = 1; i <= 10; i++)
{
cout << "C++ Language" << endl;
}
system("pause");
return 0;
}
Program for1.cpp.
Objaśnienie działania instrukcji for:
1. Do zmiennej i postaw 1
2. Je\eli zmienna i jest większa od 10, to skocz do kroku 6
3. Wykonaj instrukcje w nawiasach klamrowych (cout << "C++ Language" <<
endl;)
4. Zwiększ wartość zmiennej i o 1
5. Przejdz do kroku 2
6. Zakończ instrukcję for.
Następny przykład (program for2cpp) pokazuje typowe wykorzystanie licznika pętli:
#include
using namespace std;
int main()
{
for (int i = 0; i < 10; i++) { cout << i << endl; }
system("pause");
return 0;
}
Program for2.cpp.
Objaśnienie działania instrukcji for:
1. Do zmiennej i postaw 0
2. Je\eli zmienna i jest większa lub równa 10, to skocz do kroku 6
3. Wyświetl wartość zmiennej i przejdz do nowego wiesza
4. Zwiększ wartość zmiennej i o 1
5. Przejdz do kroku 2
6. Zakończ instrukcję for.
©2008 Jerzy Kluczewski
24 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Pętla while
Pętla while słu\y do tego samego celu co pętla for, lecz stosuje się ją, gdy liczba
kroków pętli nie jest z góry znana.
Ogólna postać instrukcji while to:
while (wyra\enie warunkowe)
{
instrukcje do wykonania;
}
Wyra\enie warunkowe określa warunek, jaki musi być spełnionym, aby wykonać
instrukcje zawarte w pętli (w nawiasach klamrowych).
Działanie pętli while zostanie pokazane na przykładzie programu while1.cpp, którego
zadaniem jest 10-krotne wyświetlenie napisu  C++ Language .
#include
using namespace std;
int main()
{
int i = 1; // tutaj trzeba zainicjowac wartosc i
while (i <= 10)
{
cout << "C++ Language" << endl;
i++;
}
system("pause");
return 0;
}
Program while1.cpp
Objaśnienie działania instrukcji while:
1. Do zmiennej i postaw 1
2. Je\eli zmienna i jest większa od 10, to skocz do kroku 6
3. Wykonaj instrukcje w nawiasach klamrowych:
a. cout << "C++ Language" << endl;
b. zwiększ wartość zmiennej i o 1
4. Przejdz do kroku 2
5. Zakończ instrukcję while.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 25
______________________________________________________________________
Pętla do & while
Pętla do & while jest odmianą pętli while, która ró\ni się od niej tym, \e zawsze
bezwarunkowo wykonowany jest jej pierwszy krok, a potem, sprawdzany warunek
(warunek jest sprawdzany na jej końcu).
Ogólna postać instrukcji do & while to:
do {
instrukcje do wykonania;
} while (wyra\enie warunkowe)
Wyra\enie warunkowe określa warunek, jaki musi być spełnionym, aby przejść do
następnego kroku pętli (następnej iteracji).
Działanie pętli do & while zostanie pokazane na przykładzie programu while2.cpp,
którego zadaniem jest 10-krotne wyświetlenie napisu  C++ Language .
#include
using namespace std;
int main()
{
int i = 0; // tutaj trzeba zainicjowac wartosc i
do
{
cout << "C++ Language" << endl;
i++;
} while (i < 10);
system("pause");
return 0;
}
Program while2.cpp
Objaśnienie działania instrukcji do & while:
1. Do zmiennej i postaw 0
2. Wykonaj instrukcje w nawiasach klamrowych:
a. cout << "C++ Language" << endl;
b. zwiększ wartość zmiennej i o 1
3. Je\eli zmienna i jest mniejsza od 10, to skocz do kroku 2
4. Zakończ instrukcję while.
©2008 Jerzy Kluczewski
26 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Zad. 1. Zadanie do samodzielnego rozwiÄ…zania:
Ile razy wykona się następująca pętla?
#include
using namespace std;
int main()
{
int i = 0;
do {
cout << i << endl;
i++;
} while (true);
system("pause");
return 0;
}
Zad. 2. Zadanie do samodzielnego rozwiÄ…zania:
Ile razy wykona się następująca pętla?
#include
using namespace std;
int main()
{
int i = 0;
do {
cout << i << endl;
i++;
} while (false);
system("pause");
return 0;
}
Instrukcja break
Jak przerwać pętlę? Słu\y do tego instrukcja break. Wyjaśnienie jak ona działa
najlepiej przedstawić na przykładzie (patrz program break1.cpp) .
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 27
______________________________________________________________________
#include
using namespace std;
int main()
{
int i = 1;
while (i <= 10) {
if (i == 6) break;
else cout << i << endl;
i++;
}
system("pause");
return 0;
}
Program break1.cpp.
Zad. 3. Zadanie do samodzielnego rozwiÄ…zania:
Jakie liczby wyświetli program break1.cpp?
Instrukcja continue
Instrukcja break powodowała przerwanie pętli. U\ycie wewnątrz pętli instrukcji
continue spowoduje \e bie\ący krok zostanie przerwany i nastąpi przejście do
kolejnego kroku (iteracji), co obrazuje poni\szy przykład (patrz program continue1.cpp)
#include
using namespace std;
int main()
{
for (int i=1; i <= 20; i++)
{
if (i % 2 != 0) continue;
cout << i << endl;
i++;
}
system("pause");
return 0;
}
Program continue1.cpp.
Operator % słu\y do obliczenia reszty z dzielenia dwóch liczb całkowitych.
©2008 Jerzy Kluczewski
28 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Objaśnienie działania instrukcji for i continue w programie continue1.cpp:
1. Do zmiennej i postaw 1
2. Je\eli wartość zmiennej i jest większa od 20, to skocz do kroku 6
3. Je\eli wartość zmiennej jest niepodzielna przez 2 to skocz do kroku 2
4. Wyświetl wartość zmiennej i
5. Zwiększ wartość zmiennej i o 1
6. Przejdz do kroku 2
7. Zakończ instrukcję for.
Zad. 4. Zadanie do samodzielnego rozwiÄ…zania:
Jakie liczby wyświetli program continue2.cpp?
#include
using namespace std;
int main()
{
for (int i=1; i <= 10; i++)
{
if (i % 2 == 0) continue;
cout << " " << i;
i++;
}
cout << endl;
system("pause");
return 0;
}
Program continue2.cpp.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 29
______________________________________________________________________
VIII. Macierze w \yciu - wprowadzenie
W naszym codziennym \yciu bardzo często posługujemy się tabelkami, ró\nego
rodzaju siatkami, zeszytami w kratkÄ™, w grach planszowych i komputerowych
szachownicami, planszami, zonami, strefami a w geografii siatkami kartograficznymi.
Do tworzenia obrazów graficznych stosujemy tzw. rastry. Obrazy edytowane za
pomocÄ… programu Paint sÄ… nazywane rastrami.
Szachownica jest przykładem macierzy składającej się z 64 pól (8 wierszy x 8 kolumn).
A B C D E F G H
1
2
3
4
5
6
7
8
Gdy chcemy określić poło\enie jakiejś figury, podajemy współrzędne pola na którym
ona stoi, np. 3D.
Co to jest rozmiar macierzy?
W przypadku naszej szachownicy jest to liczba jej wierszy i kolumn, czyli 8 x 8.
Wiersze sÄ… ponumerowane kolejno od 1 do 8, a kolumny sÄ… oznaczone literami od A do
H.
Na pewno ka\dy z nas zna grę w statki. W tej grze te\ posługujemy się planszami
(macierzami) o rozmiarze 10 x 10. Wiersze sÄ… ponumerowane od 1 do 10, kolumny
literami od A do J. Za pomocą krzy\yków oznaczamy maszty.
A B C D E F G H I J
1
2 x x x x x
3
4 x x x x x
5 x x
6 x
7 x
8 x
9 x x x x
10 x
Podobnie jak w grze w szachy, pozycje masztów statków określamy za pomocą
współrzędnych np. maszty czteromasztowca znajdują się w polach: 4A, 4B, 5B, 5C.
Ta plansza jest macierzą o rozmiarze 10 x 10 (czyt. dziesięć na dziesięć).
©2008 Jerzy Kluczewski
30 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Aby zbli\yć się do języka matematyków, zamieńmy oznaczenia masztów w ten sposób,
\e liczba 1 oznacza maszt, a liczba 0 oznacza brak masztu (puste pole). Mo\na tak
zrobić poniewa\ nie zmieni to zasad gry.
Macierz o 10 wierszach i 10 kolumnach
A B C D E F G H I J
1 0 0 0 0 0 0 0 0 0 0
2 0 1 0 0 1 1 1 0 0 1
3 0 0 0 0 0 0 0 0 0 0
4 1 1 0 0 0 0 1 1 1 0
5 0 1 1 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 1 0
7 0 0 0 0 0 0 0 0 1 0
8 0 0 1 0 0 0 0 0 0 0
9 0 0 1 0 1 1 0 0 0 1
10 0 0 0 0 0 0 0 1 0 0
Nadal mamy macierz o wymiarach 10 x 10. Tak\e kolumny sÄ… oznaczone nadal literami
od A do J. Gdybyśmy zmienili numerację kolumn na liczbową od 1 do 10, to
uzyskalibyśmy prawdziwą macierz, taką jaką posługują się matematycy.
1 2 3 4 5 6 7 8 9 10
1 0 0 0 0 0 0 0 0 0 0
2 0 1 0 0 1 1 1 0 0 1
3 0 0 0 0 0 0 0 0 0 0
4 1 1 0 0 0 0 1 1 1 0
5 0 1 1 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 1 0
7 0 0 0 0 0 0 0 0 1 0
8 0 0 1 0 0 0 0 0 0 0
9 0 0 1 0 1 1 0 0 0 1
10 0 0 0 0 0 0 0 1 0 0
Teraz wiersze i kolumny ponumerowane sÄ… jednolicie, czyli od 1 d o10. W
prawdziwych macierzach posługujemy się właśnie liczbami.
W matematyce pola w macierzy nazywamy elementami (komórkami). Z kolei
numerowanie wierszy i kolumn nazywamy indeksowaniem elementów (pól).
Oto przykład innej macierzy:
Macierz A o 5 wierszach i 8 kolumnach
1 2 3 4 5 6 7 8
1 3 5 9 2 6 8 2 9
2 5 6 4 3 1 2 3 4
3 1 1 3 7 2 4 0 9
4 4 7 5 8 2 1 9 0
5 6 2 7 3 6 2 1 8
Oznaczymy jÄ… du\Ä… literÄ… A.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 31
______________________________________________________________________
Indeksowanie elementów macierzy
Element lub jak kto woli pole o współrzędnych [1, 3] przechowuje wartość 9. Najpierw
podajemy numer wiersza a potem numer kolumny. Mówimy, \e indeksujemy
elementy macierzy  pierwszym indeksem i = 1 do10 oznaczamy wiersze, a drugim
indeksem j = 1 do 10 oznaczamy kolumny.
j= j= j= j= j= j= j= j=
1 2 3 4 5 6 7 8
i= 1 3 5 9 2 6 8 2 9
i= 2 5 6 4 3 1 2 3 4
i= 3 1 1 3 7 2 4 0 9
i= 4 4 7 5 8 2 1 9 0
i= 5 6 2 7 3 6 2 1 8
Jak oznaczamy elementy macierzy w matematyce?
Element znajdujący się w miejscu przecięcia się wiersza 1 z kolumną 3 oznaczamy
A[1,3] albo a13  co czytamy następująco:  element macierzy A o indeksie (wierszu)
równym 1 i indeksie (kolumnie) równym 3 . Element A[1,3] równa się 9, co
zapisujemy następująco:
A[1,3] = 9
W matematyce posługujemy się oznaczeniami ogólnymi, szczególnie we wzorach.
Dlatego ogólne oznaczenie jakiegoś dowolnego elementu w macierzy A wygląda
następująco: A[i,j] albo aij  co czytamy następująco:  element macierzy A o wierszu i-
tym oraz kolumnie j-tej . Element A[i,j] znajduje się na przecięciu wiersza i-tego z
kolumnÄ… j-tÄ…. Symbole i , j sÄ… tzw. indeksami macierzy.
Macierze które mają tylko jeden wiersz nazywamy macierzami jednowymiarowymi, a
macierze majÄ…ce wiele wierszy i wiele kolumn nazywamy macierzami
dwuwymiarowymi.
Macierz jednowymiarowa
1 2 3 4 5 6 7 8
1 3 5 9 2 6 8 2 9
Macierz dwuwymiarowa
1 2 3 4 5 6 7 8
1 3 5 9 2 6 8 2 9
2 5 6 4 3 1 2 3 4
3 1 1 3 7 2 4 0 9
4 4 7 5 8 2 1 9 0
5 6 2 7 3 6 2 1 8
©2008 Jerzy Kluczewski
32 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Macierze w informatyce
Macierze w informatyce te\ istniejÄ…, tylko inaczej siÄ™ nazywajÄ…  nazywamy je
tablicami. Tablice są bardzo przydatne, bo jakbyśmy napisali program komputerowy
symulujÄ…cy np. grÄ™ w statki, czy w szachy.
Wyobrazmy sobie taką macierz, która przechowuje litery alfabetu łacińskiego oraz ma 6
wierszy i 9 kolumn. Macierz tÄ… oznaczmy literÄ… B.
Macierz B (o rozmiarach 6 x 9)
0 1 2 3 4 5 6 7 8
0 a j v n r l n r l
1 x b k s m i s m i
2 u t c n l p n l p
3 e f o d m o d m o
4 d p g h e n h e n
5 r c y a g f a g f
O ile w podręcznikach matematycznych nie spotkamy takiego przykładu, to w
informatyce występuje on często i jest jak najbardziej prawidłowy. Dzieje się tak
dlatego \e ka\dÄ… literÄ™ komputer przechowuje jako kod liczbowy (tzw. kod ASCII).
W języku C++ macierz B będzie nazywana tablicą B, a nawet mo\na ją nazwać
dwuwymiarowÄ… tablicÄ… znakowÄ….
Postać macierzy B w matematyce:
b11 b12 b13 b14 b15 b16 b17 b18 b19
îÅ‚ Å‚Å‚
ïÅ‚
b21 b22 b23 b24 b25 b26 b27 b28 b29 śł
ïÅ‚ śł
ïÅ‚ śł
b31 b32 b33 b34 b35 b36 b37 b38 b39
B =
ïÅ‚
b41 b42 b43 b44 b45 b46 b47 b48 b49 śł
ïÅ‚ śł
ïÅ‚
b51 b52 b53 b54 b55 b56 b57 b58 b59 śł
ïÅ‚ śł
b61 b62 b63 b64 b65 b66 b67 b68 b69 ûÅ‚
ïÅ‚ śł
ðÅ‚
Postać tablicy B w informatyce (jej odwzorowanie w języku C++):
char B [6] [9];
W języku C++ macierz B jest tablicą dwuwymiarową o indeksach 0..5 (czyt. od 0 do
5) oraz 0..8 (czyt. od 0 do 8)  zawiera 6 wierszy i 9 kolumn. Ka\dy element tablicy B
przechowuje wartość typu znakowego char (litery te\ są znakami).
Aby wyświetlić zawartość elementu tablicy B z 0 wiersza i 1 kolumny, nale\y
posłu\yć się instrukcją cout << B [ 0 ][ 1 ].
Natomiast \eby wstawić jakiś znak do tablicy B w 0 wierszu i 1 kolumnie, u\yjemy
instrukcji B [ 0 ][ 1 ] =  @ .
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 33
______________________________________________________________________
Wyobrazmy sobie taką macierz, która przechowuje liczby rzeczywiste oraz ma 4
wiersze i 2 kolumny. Macierz tÄ… oznaczmy literÄ… C.
Macierz C (o rozmiarach 4 x 2)
0 1
0
1.25 34.30
1
-0.45 63.70
2
45.90 14.60
3
23.00 -3.33
Postać tablicy C w języku C++:
float C [4] [2];
Tablica C jest tablicÄ… dwuwymiarowÄ… o indeksach 0..3 (czyt. od 0 do 3) oraz 0..1 (czyt.
od 0 do 1), czyli zawiera 4 wiersze i 2 kolumny. Ka\dy element tablicy C przechowuje
wartość typu rzeczywistego float.
Aby wyświetlić liczbę z tablicy C (np. z 3 wiersza i 1 kolumny), nale\y posłu\yć się
instrukcjÄ… cout << C [ 3 ][ 1] << endl;
Natomiast \eby wstawić liczbę do tablicy C w 3 wierszu i 1 kolumnie, u\yjemy
instrukcji
C [ 3 ][ 1 ] = 1.20;
Uwaga: w językach programowania zamiast przecinka oddzielającego część całkowitą
od ułamkowej (liczba 1,20) stosuje się kropkę (1.20). W arkuszu kalkulacyjnym (Excel
w wersji polskiej) stosuje się przecinek. Warto o tym pamiętać, \eby uniknąć błędów
podczas tworzenia programów w językach C++, Pascal, Delphi i innych.
Jak wyzerować macierz (tablicę) ?
Wyzerowanie tablicy polega na wstawieniu zer do jej wszystkich elementów. Nale\y
u\yć dwóch zagnie\d\onych pętli for:
for (int i = 0; i<4; i++)
for (int j = 0; j<2) C[ i ][ j ] = 0.0;
Po wykonaniu tych pętli, zawartość tablicy C będzie wyglądała następująco:
0 1
0.00 0.00
0
0.00 0.00
1
0.00 0.00
2
0.00 0.00
3
©2008 Jerzy Kluczewski
34 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
IX. Tablice i wskazniki
Mo\e to dziwne, ale tak to ju\ jest w języku C++ , \e nazwa tablicy jest wskaznikiem.
Wskaznik ten wskazuje na pierwszy jej element (jest to adres pierwszego elementu
tablicy).
Oznacza to, \e jeśli zastosujemy operator wyłuskania (dereferencji) * w stosunku do
nazwy tablicy, to otrzymamy wartość jej pierwszego elementu. Pokazuje to następujący
fragment kodu:
int tab[10];
int liczba;
tab[0] = 100;
liczba = *tab;
cout << "pierwszy element tablicy: "<< *tab << endl;
cout << "zawartosc zmiennej liczba: "<< liczba << endl;
Poniewa\ nazwa tablicy jest wskaznikiem do jej pierwszego elementu , to mo\na jÄ…
przypisywać do zmiennej wskaznikowej. Patrz program tablice2.cpp.
#include
using namespace std;
int main()
{
int tab[10];
int* ptab1; // wskaznik;
int* ptab2; // wskaznik
ptab1 = tab;
ptab2 = &tab[0];
cout << "zawartosc zmiennej ptab1: "<< ptab1 << endl;
cout << "zawartosc zmiennej ptab2: "<< ptab2 << endl;
system("pause");
return 0;
}
Program tablice2.cpp.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 35
______________________________________________________________________
Arytmetyka wskazników
Na wskaznikach mo\na wykonywać operacje arytmetyczne: dodawanie, odejmowanie,
inkremencję (zwiększanie o 1), dekremencję (zmniejszanie o 1).
Pozwala to na swobodny dostęp (adresowanie pamięci komputera) do elementów
tablicy. W poni\szym programie (tablice3.cpp) instrukcja tab+i oznacza przesuniecie
adresu od wskaznika o liczbÄ™ i, a instrukcja *(tab+i) oznacza element tablicy
wskazywany przez adres tab+i. Sam wskaznik nie jest modyfikowany.
#include
using namespace std;
int main()
{
char tab[12] = {'C','+','+',' ','L','a','n','g','u','a','g','e'};
for (int i=0; i<=11; i++)
{
cout << *(tab+i);
}
cout << endl;
system("pause");
return 0;
}
Program tablice3.cpp.
W następnym programie (tablice4.cpp) nastąpi modyfikacja samego wskaznika. Musi
on być jednak formalnie zadeklarowany jako typ wskazujący na inny typ. Nie mo\e to
być nazwa tablicy. Instrukcja char* ptab = tab; kopiuje adres pierwszego elementu
tablicy do wskaznika ptab. Instrukcja *(ptab++) oznacza element tablicy wskazywany
przez adres ptab. ptab++ oznacza przesuniecie wskaznika o 1.
#include
using namespace std;
int main()
{
char tab[12] = {'C','+','+',' ','L','a','n','g','u','a','g','e'};
char* ptab = tab;
for (int i=0; i<=11; i++) {
cout << *(ptab++);
}
cout << endl;
system("pause");
return 0;
}
Program tablice4.cpp.
©2008 Jerzy Kluczewski
36 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Program równowa\ny bez u\ycia wskazników, to program tablice5.cpp. Program ten
u\ywa indeksowania elementów tablicy.
#include
using namespace std;
int main()
{
char tab[12] = {'C','+','+',' ','L','a','n','g','u','a','g','e'};
for (int i=0; i<=11; i++)
{
cout << tab[i];
}
cout << endl;
system("pause");
return 0;
}
Program tablice5.cpp.
Niebezpieczne operacje
Podczas wykonywania operacji na wskaznikach nale\y bardzo uwa\ać, aby nie
przekroczyć dopuszczalnego zakresu pamięci. Bardzo łatwo wyjść poza obszar
zadeklarowanej tablicy.
#include
using namespace std;
int main()
{
char tab[12] = {'C','+','+',' ','L','a','n','g','u','a','g','e'};
char* ptab = tab;
for (int i=0; i<=12; i++) {
cout << *(ptab++);
}
cout << endl;
system("pause");
return 0;
}
Program tablice6cpp.
Program tablice6cpp wyświetli na ekranie o jeden znak za du\o.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 37
______________________________________________________________________
Przechowywanie napisów
Do przechowywania ciągów znaków (czyli przewa\nie tekstów, napisów), słu\ą
zmienne wskaznikowe typu char*. Przechowują one ciąg znaków ASCII zakończony
znakiem specjalnym  \0 . Natomiast zmienna wskaznikowa przechowuje adres
(wskaznik) który wskazuje na pierwszy znak tego ciągu.
Tak jak w przypadku tablic, w przypadku tekstów, mo\na te\ posługiwać się
wskaznikami i je modyfikować (z nale\ytą ostro\nością). Pokazuje to niniejszy
przykład  program tablice7.cpp.
#include
using namespace std;
int main()
{
char* text = "To jest trudne";
cout << text << endl;
text = text + 3;
cout << text << endl;
text = text + 5;
cout << text << endl;
system("pause");
return 0;
}
Program tablice7cpp.
Program wyświetli na ekranie:
To jest trudne
jest trudne
trudne
©2008 Jerzy Kluczewski
38 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
X. Dynamiczny przydział pamięci
W poprzednich rozdziałach występowały wyłącznie zmienne statyczne, czyli takie,
które istnieją przez cały czas \ycia programu (od jego uruchomienia do zakończenia).
Tworzenie zmiennych dynamicznych polega na dynamicznym przydziale pamięci dla
zmiennych. Kasowanie zmiennych dynamicznych polega na dynamicznym
zwalnianiu pamięci.
W celu utworzenia zmiennej dynamicznej nale\y u\yć operatora new. Jego wywołanie
ma ogólną postać:
new typ_danych;
Po wykonaniu takiego polecenia w pamięci powstanie zarezerwowanie obszaru pamięci
niezbędnego do przechowywania danych typu typ_danych (tzw. dynamiczna
zmienna typu typ_danych., a wywołanie operatora zwróci wskaznik do tego obszaru
(tej zmiennej). Na przykład, dla większości systemów 32-bitowych, wywołanie
new int;
powoduje zarezerwowanie w pamięci 4 bajtów i zwrócenie wskaznika do nich.
W przypadku typów obiektowych, oprócz zarezerwowania pamięci dla obiektu,
wywoływany jest dodatkowo jawny lub domyślny konstruktor tego obiektu.
Aby programista miał dostęp do zmiennej dynamicznej, nie wystarczy instrukcja
new int;
nale\y zastosować następującą konstrukcję:
int* pInt = new int;
Tak skonstruowana deklaracja zmiennej wskaznikowej oraz powołanie zmiennej
dynamicznej do \ycia mo\na ju\ wykorzystywać w programie:
#include
using namespace std;
int main()
{
int* pInt = new int;
*pInt = 100;
cout << *pInt << endl;
delete pInt; // zwolnienie obszaru pamięci
}
Program dynam1.cpp
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 39
______________________________________________________________________
W linii 5 wywołanie new int zwróciło wskaznik do nowo zarezerwowanego obszaru
pamięci, który będzie mógł przechowywać wartości typu int. Wskaznik został
przypisany zmiennej wskaznikowej pInt.
W linii 6, za pomocÄ… operatora * do obszaru wskazywanego przez pInt wstawiana jest
wartość 100.
W linii 7 wyświetlana jest wartość zmiennej dynamicznej pInt.
W linii 8 za pomocą operatora delete, następuje zwolnienie obszaru pamięci,
zarezerwowanego operatorem new.
Uwaga: Zawsze nale\y zwalniać pamięć, po tym jak ju\ nie jest potrzebna, bo
w przeciwnym razie nastąpi tzw. wyciek pamięci (memory leaks), powodując
zmniejszenie ogólnej ilości pamięci dostępnej w systemie i wiele problemów
zwiÄ…zanych z tym faktem.
Sztuczki ze wskaznikami
Czy mo\na przewidzieć, co wypisze na ekranie poni\szy program dynam2.cpp?
#include
using namespace std;
int main()
{
int* pInt = new int;
char* pChar = (char*) pInt;
*pInt = 100;
cout << *pInt << endl;
*pChar = 'a';
cout << *pChar << endl;
cout << *pInt << endl;
*(pChar + 1) = 'b';
*(pChar + 2) = 'c';
*(pChar + 3) = 0;
cout << pChar << endl;
cout << *pInt << endl;
delete pInt;
system("pause");
return 0;
}
Program dynam2.cpp
Język C++ jest bardzo elastyczny, bowiem pozwala na swobodną interpretację
wskazywanego fragmentu pamięci.
©2008 Jerzy Kluczewski
40 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
W programie dynamic2.cpp w linii 5, instrukcja int* pInt = new int;
Powoduje tworzenie wskaznika do danej typu int. Następna instrukcja tworzy nowy
wskaznik pChar, który wskazuje na dane typu char. Jednak operator = powoduje
przypisanie mu tego samego adresu, co wskaznik pInt (patrz Rys. 5).
pInt
obszar
zarezerwowany
pChar
Rys. 5. Wskazniki i obszar wskazywany
Po wykonaniu instrukcji w linii 6, oba wskazniki wskazujÄ… poczÄ…tek tego samego
obszaru. Ró\nica między nimi polega tylko na tym, \e odwołując się do tego obszaru,
inaczej traktujemy dane przechowywane w tym obszarze. W linii 7, obszar ten
potraktowano jako 4-bajtową liczbę równa 100.
Natomiast w linii 9, (instrukcja *pChar = 'a';), obszar zarezerwowany traktowany
jest jak ciąg 4 znaków. W pierwszy bajt tego obszaru jest wpisywany znak  a .
W linii 12, (instrukcja *(pChar + 1) = 'b';) następuje wpisanie znaku  b pod adres
o 1 większy od adresu znaku  a .
W linii 13, (instrukcja *(pChar + 2) = 'c';) następuje wpisanie znaku  c w następny
bajt obszaru. Na koniec do czwartego bajtu wpisywana jest liczba 0. Oznacza on
koniec ciągu znaków. Mamy więc do czynienia z podwójną interpretacją obszaru
danych (liczba  kolor czerwony, znaki  kolor niebieski), występuje on raz jako typ
int, a raz jako ciąg znaków zakończonych zerem (patrz Rys. 6).
100 0 0 0
97 98 99 0
Koniec ciągu znaków
Rys. 6. Obszar 4 bajtów jako typ int (czerwony) i jako typ char (niebieski)
Znaki przechowywane są w postaci kodów ASCII, dlatego gdy w linii 16 (instrukcja
cout << *pInt << endl;) wyświetlamy wartość typu int, wydaje się ona dziwna.
Wynosi ona 6513249.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 41
______________________________________________________________________
Wydaje się ona dziwna, ale wszystko jest w porządku. To tylko mały trik
programistyczny, który został ju\ wyjaśniony.
Stos i sterta
Wszystkie programy korzystają z segmentów pamięci: są to m. in. pamięć kodu (CODE
SEGMENT), pamięć stosu (STACK SEGMENT), pamięć sterty (HEAP MEMORY).
Zmienne statyczne rezerwowane są na tzw. stosie (ang. stack)  Rys. 7. Stos ma stały
rozmiar i nie mo\e być zwiększany w trakcie działania programu. Zazwyczaj jego
wielkość jest regulowana w opcjach kompilatora. W przypadku zmiennych
dynamicznych pamięć rezerwowana na dane znajduje się w obszarze tzw. sterty (ang.
heap). Wielkość sterty zale\y od tego, ile pamięci system operacyjny jest w stanie
przydzielić jednemu procesowi.
Wskaznik1
Obszar X
Wskaznik2
stos
Obszar Y
pamięć
sterta
Rys. 7. Obszary pamięci i ich wykorzystanie.
Wskazniki są przechowywane na stosie, dane wskazywane na stercie. Powoływanie do
\ycia oraz usuwanie zmiennej dynamicznej odbywa siÄ™ na stercie, a wskazniki po
usunięciu zmiennej dynamicznej, nadal istnieją, tylko, mo\na powiedzieć, \e wskazują
na przypadkowe dane. Dlatego u\ywanie wskaznika po usunięciu obszaru ze sterty, jest
bardzo nieodpowiedzialne.
©2008 Jerzy Kluczewski
42 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Dynamiczne tablice
Za pomocą operatora new mo\na te\ tworzyć dynamiczne tablice. Przykład tworzenia
takiej tablicy zaprezentowano w programie dynam3.cpp.
#include
using namespace std;
int main()
{
int* pTab = new int[10]; // 10 elementów
for (int i = 0; i < 10; i++)
{
pTab[i] = i + 1;
}
for (int i = 0; i < 10; i++)
{
cout << pTab[i] << " ";
}
cout << endl;
delete pTab;
system("pause");
return 0;
}
Program dynam3.cpp.
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 43
______________________________________________________________________
XI. Literatura
A. Majczak. C++ Przykłady praktyczne. Wydawnictwo Mikom, Warszawa 2003.
J. Liberty. C++ dla ka\dego. Wydawnictwo Helion, Gliwice 2002.
K. Loudon. C++ Leksykon kieszonkowy. Wydawnictwo Helion, Gliwice 2003.
A. Stasiewicz. C++ Ćwiczenia praktyczne. Wydawnictwo Helion, Gliwice 2004.
©2008 Jerzy Kluczewski
44 C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I.
______________________________________________________________________
Spis treści
I. Kompilacja i linkowanie........................................................................................... 2
Najprostszy program..................................................................................................... 2
Prawdziwy program...................................................................................................... 3
II. Rozpoznawanie błędów ............................................................................................ 3
Dziwny błąd linkera...................................................................................................... 4
Niezadeklarowana zmienna .......................................................................................... 5
Literówki....................................................................................................................... 5
Pliki nagłówkowe ......................................................................................................... 6
Przestrzenie nazw ......................................................................................................... 6
Koniec instrukcji........................................................................................................... 6
Cudzysłów .................................................................................................................... 7
Argumenty funkcji........................................................................................................ 7
III. Zmienne ................................................................................................................ 9
Inicjowanie zmiennych ................................................................................................. 9
Jak nazywać zmienne?................................................................................................ 10
Typ znakowy............................................................................................................... 10
Modyfikatory signed i unsigned ................................................................................. 10
Liczby zmiennoprzecinkowe ...................................................................................... 11
IV. Instrukcja warunkowa......................................................................................... 12
Instrukcja warunkowa zagnie\d\ona .......................................................................... 13
V. Rodzaje zmiennych................................................................................................. 14
Zmienne lokalne ......................................................................................................... 14
Zmienne globalne ....................................................................................................... 15
Zmienne modułowe ................................................................................................ 15
Przesłanianie zmiennych globalnych...................................................................... 16
VI. Wskazniki ........................................................................................................... 17
Typ wskaznikowy................................................................................................... 17
Wskazniki do funkcji.............................................................................................. 19
Wskazniki do funkcji na skróty .............................................................................. 20
Wskazniki do klas....................................................................................................... 20
Wskaznik do składowej klasy................................................................................. 21
VII. Iteracje czyli pętle............................................................................................... 22
Pętla for....................................................................................................................... 22
Pętla while................................................................................................................... 24
Pętla do & while......................................................................................................... 25
Instrukcja break....................................................................................................... 26
Instrukcja continue.................................................................................................. 27
VIII. Macierze w \yciu - wprowadzenie ..................................................................... 29
Co to jest rozmiar macierzy? .................................................................................. 29
Indeksowanie elementów macierzy........................................................................ 31
Jak oznaczamy elementy macierzy w matematyce?............................................... 31
______________________________________________________________________
©2008 Jerzy Kluczewski
C++. Programowanie obiektowe. Ćwiczenia podstawowe. Cz. I. 45
______________________________________________________________________
Macierze w informatyce ......................................................................................... 32
Jak wyzerować macierz (tablicę) ? ......................................................................... 33
IX. Tablice i wskazniki ............................................................................................. 34
Arytmetyka wskazników ............................................................................................ 35
Niebezpieczne operacje .............................................................................................. 36
Przechowywanie napisów........................................................................................... 37
X. Dynamiczny przydział pamięci .............................................................................. 38
Sztuczki ze wskaznikami........................................................................................ 39
Stos i sterta.............................................................................................................. 41
Dynamiczne tablice..................................................................................................... 42
XI. Literatura............................................................................................................. 43
©2008 Jerzy Kluczewski


Wyszukiwarka

Podobne podstrony:
Ćwiczenia z podstaw prawa cywilnego z umowami w administracji I
pas cwiczenia podstawowe cz2
Ćwiczenie 2 3 Podstawy użytkowania wiersza poleceń systemu Windows 2000;XP;2003
CWICZENIA Z PODSTAW RECEPTURY KOSMETYCZNEJ
Ćwiczenia Podstawy Fiz Fazy Skondensowanej
program cwiczen z podstaw informatyki 2
zestawy cwiczen przygotowane na podstawie programu Mistrz Klawia 6
podstawy automatyki ćwiczenia lista nr+
Podstawy prawa cywilnego z umowami w administracj ćwiczenia II
zestawy cwiczen przygotowane na podstawie programu Mistrz Klawia 8

więcej podobnych podstron