Celem tego kursu/wykładu jest nauka języka C++ poprzez pisanie i analizowanie kodu C++. Do rozważań teoretycznych odsyłam do bardzo dobrych książek na końcu tego artykułu, które zresztą polecam każdemu programiście C++.

Struktura programu w C++

Najlepszym sposobem nauki programowania jest nauka poprzez pisanie/analizowanie programów. Naukę rozpoczniemy od klasyka - programu "Hello, World!", który wyświetla ten napis na ekranie komputera.

1
2
3
4
5
6
7
8
9
10
11
12
13
/* Program P1 - Hello World!
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    cout << "Hello, World!" << endl; //wypisuje ciąg znaków Hello, World! na ekran

    return 0;
}

Linie 1-2:
/* Program P1 - Hello World!
* Wykonał Paweł Malinowski */


/* i */ - oznacza komentarz wieloliniowy. Wszystko co jest zapisane pomiędzy /* i */ jest traktowane jako komentarz i nie ma żadnego wpływu na zachowanie się programu. Programiści używają komentarzy w celu ułatwienia sobie pracy, poprzez komentowanie co w danym bloku kodu wykonują, jakie deklarują zmienne, itp. W tym przypadku komentarz dotyczy informacji o nazwie programu i jego autorze.

Linia 3:
Linia pusta

Linie takie nie mają żadnego wpływu na działanie programu. Używane są w celu poprawy czytelności kodu.

Linia 4:
#include <iostream>

Linie zaczynające się od znaku # są dyrektywami interpretowanymi przez preprocesor. Linie te są interpretowane zanim nastąpi kompilacja programu. W tym przypadku dyrektywa #include <iostream> przekazuje do preprocesora informację o dołączeniu do programu nagłówka biblioteki iostream, dzięki temu możemy wykonywać standardowe operacje wejścia/wyjścia, takie jak wypisanie na ekranie (Hello, World!).

Linia 6:
using namespace std;

Dyrektywa using udostępnia lokalnie całą zawartość standardowej przestrzeni nazw std. W standardowej przestrzeni nazw znajduje się obiekt cout, który wykorzystujemy w tym programie do wyświetlenia łąńcucha znaków "Hello, World!" na ekran. Więcej informacji o przestrzeniach nazw znajduje się w rozdziale Zasięg/przestrzenie nazw.

Linia 8:
int main( )

Linia ta inicjuje deklarację funkcji głównej (main). Funkcja to inaczej zestaw instrukcji, który posiada swoją nazwę - w tym przypadku main. Na początku każdej funkcji wpisujem typ danych, który funkcja zwraca, następnie podajemy jej nazwę, a w nawiasach podajemy argumenty funkcji (opcjonalnie). Więcej informacji o typach danych znajduje się w rozdziale Zmienne i typy danych. Więcej o funkcjach znajduje się w rozdziale Funkcje.

Linie 9 i 13:
{ , }

Nawias otwierający { wskazuje początek definicji funkcji głównej, nawias zamykający } oznacza koniec definicji funkcji. Wszystko pomiędzy tymi nawiasami to ciało funkcji, gdzie zdefiniowane jest, co się wydarzy po wywołaniu funkcji.

Linia 10:
cout << "Hello, World!" << endl; //wypisuje ciąg znaków Hello, World! na ekran

Ta linia jest instrukcją języka C++. Każda instrukcja jest to część kodu, która daje zamierzony efekt. Instrukcje wykonywane są w takim samym porządku jak są zapisane w kodzie programu. Obiekt cout character output z biblioteki iostream wskazuje urządzenie wyjścia (monitor komputera), na który wysyła łańcuch znaków "Hello, World!". << oznacza wysłanie danych do strumienia wyjściowego. Symbole wskazują kierunek przepływu informacji. endl (end line) - jest to manipulator, którego zadaniem jest zakończenie obecnej linii i przejście do nowej linii. Znaki // - oznaczają komentarz jednoliniowy.

Linia 12:
return 0;

Każda funkcja, gdzie przed nazwą występuje typ danych np. int, float, char, string, itp. z wyjątkiem void musi zwrócić po zakończeniu swojego działania dane z takim typem jak przy deklaracji funkcji. Funkcja main deklarowana była jako int main(), dlatego musi zwrócić liczbę całkowitę int - return 0.

Każda instrukcja w C++ kończy się znakiem ;. Średnik oznacza koniec każdej instrukcji. Dzięki niemu kompilator wie, gdzie instrukcja się zaczyna i gdzie kończy. Jednym z najczęściej popełnianych błędów na początku nauki programowania w C++ jest brak średnika na koncu każdej instrukcji.

Ten sam program można również napisać bez używania wcięć w kodzie, umieszczania instrukcji w osobnych liniach. Działanie programu jest identyczne, natomiast czytelność kodu źródłowego jest bardzo zła.

1
2
3
/* Program P1 - Hello World!* Wykonał Paweł Malinowski */#include <iostream>
using namespace std;int main(){cout << "Hello, World!" << endl; //wypisuje ciąg znaków Hello, World! na ekran
return 0;}


  1. Napisz program wypisujący w oddzielnych liniach Twoje imię, nazwisko, rok urodzenia, miejsce urodzenia, ulubiony kolor.
  2. Napisz program, który wyświetli na ekranie 3 razy "Bóg Honor Ojczyzna".
  1. W jaki sposób możemy dołączyć zewnętrzną bibliotekę do naszego programu?
  2. Jak możemy na ekran wypisać dowolny napis?

Podstawowe typy danych

Programowanie w C++ nie tylko ograniczone jest do wypisywania na ekran ciągów znaków, tak jak pokazał to program Hello, World!. Aby pisać bardziej funkcjonalne programy musimy poznać zmienne.

Co to jest zmienna?
Zmienna to konstrukcja programistyczna posiadająca trzy podstawowe atrybuty: symboliczną nazwę, miejsce przechowywania i wartość; pozwalająca w kodzie źródłowym odwoływać się przy pomocy nazwy do wartości lub miejsca przechowywania. Nazwa służy do identyfikowania zmiennej w związku z tym często nazywana jest identyfikatorem. Miejsce przechowywania przeważnie znajduje się w pamięci komputera i określane jest przez adres i długość danych. Wartość to zawartość miejsca przechowywania. Zmienna zazwyczaj posiada również czwarty atrybut: typ, określający rodzaj danych przechowywanych w zmiennej i co za tym idzie sposób reprezentacji wartości w miejscu przechowywania.
Miejsce przechowywania to wydzielony obszar pamięci o rozmiarze określonym przez typ danych. Aby można użyć zmiennych w programie, należy je najpierw zadeklarować.
Deklaracja zmiennej - to inaczej zarezerwowanie w pamięci miejsca o określonym rozmiarze (zależnym od typu danych i implementacji C++) i określonej nazwie. Np.

int a, x, y;
double b;
char c;

Każda zmienna deklarowana jest według następującej zasady. Najpierw podajemy typ danych, następnie unikatową nazwę z wyjątkiem zarezerwowanych słów kluczowych. Zmienne tego samego typu można również deklarować oddzielając je (,). Np. int a, x, y;
Zmienne można podczas deklaracji inicjalizować podając wartość zmiennej lub wyrażenie. Np.

int a = 1024;
double b(1.6180339887);
char c{'$'};
double d = b + a;
Znak = jest operatorem przypisania tzn. zmiennej po lewej stronie przypisuje wartość (wyrażenie) po prawej stronie. Drugi rodzaj inicjalizowania zmiennych to wykorzystanie nawiasów (), np. double b(.1.6180339887). Trzeci sposób inicjalizacji to wykorzystaniem nawiasów klamrowych {}, np. char c{'$'}.
Więcej o operatorach znajdziemy w rozdziale Operatory.

Prawidłowa nazwa zmiennej musi składać się z liter, cyfr i znaku podkreślenia (_). Spacje i inne znaki są wykluczone w budowaniu nazw zmiennych. Każda zmienna zawsze powinna zaczynać się od litery.
C++ rezerwuje listę słów kluczowych, których nie można wykorzystać podczas tworzenia nazw.

Słowa kluczowe:
alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq

Każda implementacja C++ może zawierać dodatkowe zarezerwowane sława kluczowe.

Język C++ to język programowania typu "case sensitive". Oznacza to, że zmienna napisana dużymi literami jest różna od zmiennej o tej samej nazwie napisanej małymi literami. Np.

Zmienna RESULT nie jest tą samą zmienną co Result czy result. Są to trzy różne zmienne.

Aby wyświetlić wartość zmiennej x na ekranie wystarczy użyć instrukcji:
cout << x;


Wartości zmiennych przechowywane są w pamięci komputera jako ciąg zer i jedynek. Nasz program nie potrzebuje znać dokładnej lokalizacji w pamięci, gdzie zmienne są przechowywane (z wykorzystaniem wskaźników wiemy dokładnie w którym miejscu w pamięci znajduje się nasza zmienna). Program odwołuje się do nazwy zmiennej i to wystarczy. Program potrzebuje wiedzieć jakiego rodzaju dane zmienna przechowuje. To nie to samo przechowywać zmienne całkowite, znaki, czy duże liczby zmiennoprzecinkowe (rzeczywiste). Zmienne te interpretowane są w inny sposób i mogą zajmować różną ilość pamięci.
Podstawowe typy danych to typy bazowe bezpośrednio zaimplementowane w język C++ i są podzielone na:


  • Typy znakowe - mogą reprezentować pojedynczy znak 'A', 'z'. Najbardziej podstawowym typem znakowym jest char, który potrzebuje do przechowywania danych 1 bajt - 8 bitów.
  • Typy całkowite - mogą przechowywać wartości całkowite takie jak 23, 2048. Typy całkowite istnieją w różnych rozmiarach i mogą to być typy ze znakiem i bez znaku, w zależności czy wspierają wartości ujemne czy nie.
  • Typy zmiennoprzecinkowe - reprezentują wartości rzeczywiste takie jak np. 1.618033, 3.141592 z różną dokładnością w zależności od jednego z trzech wybranych typów zmiennoprzecinkowych.
  • Typ bool - typ ten może reprezentować tylko dwa stany: prawda lub fałsz.

Podstawowe typy danych


Rodzaj danych Nazwa typu* Rozmiar/precyzja
Typy znakowe char 1 bajt. 8 bitów.
char16_t Nie mniejszy niż typ char. Co najmniej 16 bitów.
char32_t Nie mniejszy niż typ char16_t. Co najmniej 32 bity.
wchar_t Może reprezentować największy wspierany zestaw znaków.
Typy całkowite (ze znakiem) signed char Taki sam rozmiar jak typu char. Co najmniej 8 bitów.
signed short int Nie mniejszy niż typ char. Co najmniej 16 bitów.
signed int Nie mniejszy niż typ short. Co najmniej 16 bitów.
signed long int Nie mniejszy niż typ int. Co najmniej 32 bity.
signed long long int Nie mniejszy niż typ long. Co najmniej 64 bity.
Typy całkowite (bez znaku) unsigned char (taki sam rozmiar jak typy ze znakiem)
unsigned short int
unsigned int
unsigned long int
unsigned long long int
Typy zmiennoprzecinkowe float
double Dokładność nie mniejsza niż float.
long double Dokładność nie mniejsza niż double.
Typ logiczny bool
Typ void void

* Nazwy wybranych typów całkowitych mogą zostać skrócone. Można pominąć signed oraz int tylko w miejscach gdzie nie jest pogrubiona czcionka. Np. signed short int można zapisać jako short.
W każdej grupie typy danych różnią się rozmiarem. Pierwszy typ w każdej grupie ma najmniejszy rozmiar, a ostatni największy. Każdy typ w danej grupie ma takie same własnosci.

W powyższej tabeli żaden typ danych z wyjątkiem typu char, który ma dokładnie jeden bajt, nie ma dokładnie podanych wartości. Zamiast tego jest np. co najmniej 16 bitów.
Oznacza to, że typy te nie mają standardowego rozmiaru dla każdego kompilatora czy architektury komputera. Każdy kompilator języka C++ może dowolnie ustawiać rozmiar zmiennych by najlepiej dopasować go do aktualnej architektury komputera, na którym będzie uruchomiony. Ta właściwość daje dużą elastyczność w optymalnym doborze rozmiaru zmiennych.
Rozmiar typu danych podawany był w bitach. Poniższa tabela przedstawia reprezentację bitową oraz wartość dziesiętną.


Rozmiar Wartość Uwagi
8-bitów 256 = 28
16-bitów 65 536 = 216
32-bity 4 294 967 296 = 232
64-bity 18 446 744 073 709 551 616 = 264

Przykład:
16-bitowa zmienna typu unsigned int może przechowywać wartości od 0 do 65535, natomiast ta sama zmienna ze znakiem signed przechowuje wartości od -32768 do 32767.

W związku z tym, iż rozmiary typów danych podane są tak jak w tabeli Podstawowe typy danych, to aby dokładnie sprawdzić ile bitów przypada na dany typ danych, jaka jest minimalna i maksymalna wartość dla danego typu, itp. należy skorzystać z klasy numeric_limits z biblioteki <limits>

1
2
3
4
5
6
7
8
9
10
11
12
13
//Wykorzystanie klasy numeric_limits
#include <iostream>
#include <limits>

int main ()
{
    std::cout << std::boolalpha;
    std::cout << "Minimalna wartość dla int: " << std::numeric_limits<int>::min() << '\n';
    std::cout << "Maksymalna wartość dla int: " << std::numeric_limits<int>::max() << '\n';
    std::cout << "Czy typ int jest ze znakiem?: " << std::numeric_limits<int>::is_signed << '\n';
    std::cout << "Ilość bitów dla typu int: " << std::numeric_limits<int>::digits << '\n';
    return 0;
}

Wynik działania programu (wartości mogą się różnić w zależności od implementacji języka C++ oraz architektury komputera):

Minimalna wartość dla int: -2147483648
Maksymalna wartość dla int: 2147483647
Czy typ int jest ze znakiem?: true
Ilość bitów dla typu int: 31

Analiza programu

Linia 3:
#include <limits>

Dołączamy za pomocą dyrektywy #include bibliotekę limits, aby można wykorzystać potrzebną nam klasę numeric_limits.

Linia 6:
std::cout << std::boolalpha;

Jeśli flaga boolalpha jest ustawiona tak jak w powyższym zapisie oznacza to, że zmienne typu bool będą zapisywane w postaci true lub false, a nie 1 lub 0. By powrócić do poprzednich ustawień flagi boolalpha należy wykonać instrukcję:
std::cout << std::noboolalpha;

Konstrukcja std::cout oznacza wykorzystanie obiektu cout z biblioteki standardowej std. :: - jest to operator zasięgu. Więcej na ten temat znajdziemy w rozdziale Zasięg/przestrzenie nazw.

Linie 7-10:
W tych liniach wykorzystywana jest klasa numeric_limits. min(), max(), is_signed, digits, has_infinity oznaczają kolejno wartość minimalną, wartość maksymalną, czy typ danych jest ze znakiem, ilość bitów liczona od 0.

Ten sam program można również zapisać w taki sposób:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Wykorzystanie klasy numeric_limits
#include <iostream>
#include <limits>

using std::cout;
using std::boolalpha;
using std::numeric_limits;

int main () {
    cout << boolalpha;
    cout << "Minimalna wartość dla int: " << numeric_limits<int>::min() << '\n';
    cout << "Maksymalna wartość dla int: " << numeric_limits<int>::max() << '\n';
    cout << "Czy typ int jest ze znakiem?: " << numeric_limits<int>::is_signed << '\n';
    cout << "Ilość bitów dla typu int: " << numeric_limits<int>::digits << '\n';
    return 0;
}

Typy danych przedstawione powyżej (znakowe, całkowite, rzeczywiste i logiczne) znane są jako typy podstawowe.
C++ wspiera szeroką gamę typów bazujących na typach podstawowych i nazywa je typami złożonymi. Typy te stanowią siłę języka C++. Wybrane typy złożone przedstawione będą w kolejnych rozdziałach.

Stałe

Podczas tworzenia stałej musimy jej na początku nadać wartość. Stała jak sama nazwa wskazuje jest stała (niezmienna) przez czas życia programu. Stałą definiujemy w następujący sposób:
const [typ_stałej] nazwa_stałej = wartość; Np.
const float pi = 3.1415;
const double zlota_liczba = 1.6180339887
const int wzrost = 198;

  1. Napisz program, który deklaruje zmienną a jako int oraz zmienną b jako float. Zainicjalizuj zmienną a wartością 128. Do zmiennej b wpisz wartość 65.9876 z wykorzystaniem operatora przypisania. Wyświetl wartości zmiennych na ekranie.
  2. Napisz program, zadeklaruje zmienne a, b, c dowolnego typu oraz zainicjalizuje je przykładowymi wartościami z wykorzystaniem trzech typów inicjalizacji zmiennych. Wyświetl wartości tych zmiennych w osobnych liniach na ekranie.
  1. Co to jest zmienna?
  2. Co to jest deklaracja zmiennej?
  3. W jaki sposób można zainicjalizować zmienną (podaj wszystkie sposoby)?
  4. Co oznacza, że język C++ jest typu "case sensitive"?
  5. Jakie znasz podstawowe typy danych?
  6. Co oznaczają typy ze znakiem i bez znaku?
  7. Jak można sprawdzić ile bitów potrzeba dla typu long double?

Operatory

Jeżeli znamy już pojęcie zmiennych i stałych możemy z nimi pracować wykorzystując operatory.


Operator przypisania (=)


np.
x = 10;

Zmiennej x przypisana jest wartość 10. Operator przypisania działa od prawej do lewej strony czyli zmiennej po lewej stronie przypisana jest wartość lub wyrażenie po prawej stronie.

x = y;
Do zmiennej x przypisana jest teraz wartość zmiennej y. Należy rozważyć sytuację, że przypisujemy zmiennej x wartość zmiennej y, w momencie wykonania instrukcji przypisania. Dlatego jeśli wartość zmiennej y ulegnie zmianie, to wartość x będzie miała poprzednią wartość zmiennej y.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* Operator przypisania
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int a, b;         // a:?,  b:?
    a = 10;           // a:10, b:?
    b = 4;            // a:10, b:4
    a = b;            // a:4,  b:4
    b = 7;            // a:4,  b:7

    cout << "a:";
    cout << a;
    cout << " b:";
    cout << b;

    return 0;
}
a:4 b:7

y = 2 + (x = 5);
W tej instrukcji zmiennej y przypisana jest wartość wyrażenia 2 + (x = 5). Napotykamu tu kolejny operator przypisania x = 5. Powyższa instrukcja równoważna jest zapisowi:
x = 5;
y = 2 + x;
Wartością zmiennej y jest oczywiście liczba 7.

Poprawną instrukcją C++ jest również:
a = b = c = 64

W tej instrukcji wartość 64 przypisana jest do wszystkich 3 zmiennych a, b, c (od prawej do lewej).


Operatory arytmetyczne (+, -, *, /, %)


Operator Opis
+ dodawanie
- odejmowanie
* mnożenie
/ dzielenie
% modulo

Operacje dodawania, odejmowania, mnożenia, dzielenia korespondują z działaniami matematycznymi. Natomiast ostatni operator % daje jako wynik resztę z dzielenia np.
x = 16 % 3 //daje wynik 1, ponieważ 16/3 = 5 z resztą 1


Złożone operatory przypisania (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)


Złożone operatory przypisania modyfikują aktualną wartość zmiennej wykorzystując na niej operatację


Instrukcja Równoważna instrukcja
y += x; y = y + x;
x -= 5; x = x - 5;
y *= 3; y = y * 3;
x /= 12; x = x / 12;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Złożony operator przypisania
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int a, b=3;
    a = b;
    a+=2;             // zapis równoważny to a=a+2
    cout << a;
    return 0;
}

Operatory inkrementacji i dekrementacji

Niektóre instrukcje mogą być zapisane krócej za pomocą operatora ++ (inkrementacja) lub -- (dekrementacja). Jest to równoznaczne z zapisem +=1 lub -=1.
++x;
x += 1;
x = x + 1;

Powyższe instrukcje są równoznaczne i każda z nich zwiększa wartość zmiennej x o 1.
Cechą szczególną tych operatorów jest to, że mogą występować w dwóch odmianach w formie przedrostkowej (++x) lub przyrostkowej (x++). Jednakże te dwa zapisy mają różne znaczenie.


Przykład 1 Przykład 2
x = 3;
y = ++x;
// x = 4, y = 4
x = 3;
y = x++;
// x = 4, y = 3

Operatory porównania (==, !=, >, <, >=, <=)


Dwa wyrażenia mogą być ze sobą porównane z wykorzystaniem operatorów porównania


Operator Opis
== równy
!= różny
< mniejszy niż
> większy niż
<= mniejszy lub równy
>= większy lub równy
Przykłady
(7 == 5)     // wyrażenie fałszywe
(5 > 4)      // wyrażenie prawdziwe
(3 != 2)     // wyrażenie prawdziwe
(6 >= 6)     // wyrażenie prawdziwe
(5 < 5)      // wyrażenie fałszywe
Oczywiście porównywać można nie tylko wartości numeryczne, ale również wyrażenia, zmienne.
Załóżmy, że a = 2, b = 3, c = 6
(a == 5)     // wyrażenie fałszywe, ponieważ a nie jest równe 5
(a*b >= c)   // wyrażenie prawdziwe, ponieważ wyrażenie (2*3 >= 6) jest prawdziwe
(b+4 > a*c)  // wyrażenie fałszywe, ponieważ (3+4 > 2*6) jest fałszywe
((b=2) == a) // wyrażenie prawdziwe

UWAGA!
Bądź ostrożny. Operator przypisania (=) to nie to samo co operator porównania (==).


Operatory logiczne (!, &&, ||)


Operator ! oznacza negację. Ma on tylko jeden operand po swojej prawej stronie i odwraca wartość wyrażenia z true na false i odwrotnie.
!(5 == 5)     // wyrażenie fałszywe, ponieważ wyrażenie po prawej stronie jest prawdziwe
!(6 <= 4)   // wyrażenie prawdziwe, ponieważ wyrażenie (6 <= 4) jest fałszywe
!true  // wyrażenie fałszywe
!false // wyrażenie prawdziwe
Operatory && i || są używane dla dwóch operandów.

Tabela prawdy dla operatora &&
Operator &&
a b a && b
true true true
true false false
false true false
false false false
Tabela prawdy dla operatora ||
Operator ||
a b a || b
true true true
true false true
false true true
false false false
Przykład
((5 == 5) && (3 > 6))  // wyrażenie fałszywe ( true && false )
((5 == 5) || (3 > 6))  // wyrażenie prawdziwe ( true || false )
Gdy używamy operatorów logicznych, C++ wykonuje tylko niezbędne operacje, ignorując resztę. Np.
((5 == 5) || (3 > 6))
Kompilator C++ sprawdza wartość wyrażenia (5 == 5) i już nie musi sprawdzać wartości następnego wyrażenia, gdyż pierwsze daje true.
Operator
&& Jeśli wyrażenie po lewej stronie jest fałszywe, to całość daje wartość fałsz(wtedy wyrażenie po prawej stronie nie jest sprawdzane)
|| Jeśli wyrażenie po lewej stronie jest prawdziwe, to całość jest prawdziwa(wtedy wyrażenie po prawej stronie nie jest sprawdzane)

Rozważmy następujący przykład
if ((i < 10) && (++i < n))
Widzimy, że operand po prawej stronie (++i < n) inkrementuje wartość zmiennej i, ale tylko wtedy, gdy po lewej stronie jest warunek prawdziwy. W przeciwnym wypadku operand po prawej stronie nigdy nie zostanie wykonany.

Trójargumentowy operator warunkowy (?)


Operator ten sprawdza warunek i zwraca jedną wartość, gdy jest prawdziwy, a inną, gdy jest fałszywy.

warunek ? wynik1 : wynik2

Jeżeli warunek jest prawdziwy wykona się instrukcja wynik1, w przeciwnym wypadku wykona się instrukcja wynik2.

7==5 ? 4 : 3     // wynik jest równy 3, ponieważ 7 jest różne od 5.
7==5+2 ? 4 : 3   // wynik jest równy 4, ponieważ 7 jest równe 5 + 2.
5>3 ? a : b      // wynik jest równy a, ponieważ 5 jest większe od 3.

Przykład

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* Trójargumentowy operator warunkowy
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
     int a,b,c;

     a=2;
     b=7;
     c = (a>b) ? a : b;

     cout << c << '\n';
    return 0;
}

Operatory rzutowania


Operatory rzutowania pozwalają zamienić wartość z jednego typu na inny.
Przykład

int i;
float f = 3.14;
i = (int) f;

Kod ten konwertuje liczbę zmiennoprzecinkową 3.14 na wartość całkowitą 3. Reszta z tej liczby jest tracona poprzez konwersję. Drugi rodzaj rzutowania zapisujemy następująco:
i = int (f);

Operator sizeof


Operator ten zawiera jeden parametr, który może być typem danych lub zmienną i zwraca wielkość tego typu w bajtach.
x = sizeof(char);

x jest równe 1 bajt, gdyż typ char ma rozmiar 1 bajta.

Priorytety operatorów


Pojedyncza instrukcja może mieć kilka operatorów jednocześnie.
x = 5 + 7 % 2;

W C++ powyższa instrukja daje wartość 6, ponieważ operator modulo (%) ma wyższy priorytet od operatora dodawania (+). Dlatego, aby zmienić priorytety operatorów używa się nawiasów ().
x = 5 + (7 % 2);    // x = 6
x = (5 + 7) % 2;    // x = 0

  1. Napisz program, który sprawdza wartość wyrażenia (a * b) < 15, gdzie a = 5 i b = 4. W przypadku, gdy wartość wyrażenia jest prawdziwa wypisz na ekranie wartość a, w przeciwnym wypadku wypisz wartość b. (użyj trójargumentowego operatora warunkowego).
  2. Napisz program, który oblicza resztę z dzielenia (a * b)/(a + b), gdzie a = 5 i b = 4.
  3. Napisz program, który wypisuje wartość całkowitą zmiennej float a = 15.42 przy użyciu operatora rzutowania.
  1. Co to jest operator modulo (%)?
  2. Co to jest złożony operator przypisania, podaj przykład?
  3. Jak zapisujemy operator porównania?
  4. Napisz tabelę prawdy dla operatora &&.
  5. Napisz tabelę prawdy dla operatora ||.
  6. Co to jest operator rzutowania? Podaj przykład.
  7. Co to jest trójargumentowy operator warunkowy? Podaj przykład.
  8. Jak sprawdzić ile dana zmienna ma zarezerwowanych bajtów w pamięci komputera?

Strumień wejścia/wyjścia


C++ używa warstwy abstrakcji zwanej strumieniami by wykonywać operacje wejścia/wyjścia na ekran monitora, pobierać dane z klawiatury, wykonywać operacje na plikach. Programista nie musi znać dokładnej budowy strumieni. Wystarczy wiedzieć jak taki strumień zastosować i z jakich funkcji skorzystać. Wszystko co potrzebujemy wiedzieć o strumieniach to strumień jest wejściem lub wyjściem ciągu znaków dostarczanych sekwencyjnie (jeden po drugim).


Strumień Opis
cin Standardowy strumień wejścia
cout Standardowy strumień wyjścia
cerr Standardowy strumień błędów (wyjście)
clog Standardowy strumień logów (wyjście)

Strumień wyjścia (cout)


W większości środowisk standardowym wyjściem jest monitor komputera. Do formatowania operacji wyjścia poprzez obiekt cout używa się tzw. operatora wstawiania (przekierowania strumienia) <<.

cout << "Hello World"; // wypisuje na ekranie Hello World
cout << 120;               // wypisuje na ekranie liczbę 120
cout << 'A';               // wypisuje na ekranie znak A
cout << x;                 // wypisuje na ekranie wartość x

Zwróć uwagę, że ciąg znaków "Hello World" został umieszczony w cudzysłowiu ("), ponieważ ciągi znaków umieszcza się pomiędzy znakami " ". Natomiast pojedynczy znak umieszczamy pomiędzy apostrofami (').

cout << "Witaj";  // wypisuje na ekranie napis Witaj
cout << Witaj;    // wypisuje na ekranie wartość zmiennej Witaj
W jednej instrukcji można wielokrotnie wykorzystać przekierowanie strumienia (<<).
cout << "To " << " jest " << "prosta instrukcja C++";
W pojedynczej istrukcji możemy wysłać do strumienia wyjściowego połączenie łańcucha z wartościami zmiennych.
cout << "Mam " << wiek << " lat, a mój kod pocztowy to " << kod;

Zakładając, że zmienna wiek przechowuje wartość 30, a zmienna kod 32-345, to w wyniku wykonania powyższej instrukcji otrzymamy:
Mam 30 lat, a mój kod pocztowy to 32-345 Cout automatycznie nie przechodzi do następnej linii. Przykład:
cout << "To jest pierwsze zdanie.";
cout << "To jest drugie zdanie.";

W wyniku wykonania się tych dwóch instrukcji na ekranie zobaczymy:
To jest pierwsze zdanie.To jest drugie zdanie. Aby przejść do nowej linii należy zastosować znak nowej linii (\n).
cout << "To jest pierwsze zdanie.\n";
cout << "To jest drugie zdanie.\nTo jest trzecie zdanie"; 

W wyniku działania tych instrukcji na ekranie zobaczymy:
To jest pierwsze zdanie.
To jest drugie zdanie.
To jest trzecie zdanie. Można również zastosować manipulator endl.
cout << "To jest pierwsze zdanie." << endl;
cout << "To jest drugie zdanie." << endl << "To jest trzecie zdanie";

Wynik jest dokładnie taki jak poprzednio.

Strumień wejścia (cin)


W większości środowisk standardowym wejściem jest klawiatura. Do wprowadzania danych do strumienia wejściowego poprzez klawiaturę wykorzystuje się obiekt cin. Do przekierowania strumienia do np. zmiennej służy operator przekierowania strumienia (>>).

int wiek;
cin >> wiek;

W pierwszej linii zadeklarowana jest zmienna wiek typu całkowitego. W kolejnej linii program oczekuje wprowadzenia informacji o wieku i zapisuje ją w zmiennej wiek.


Napiszmy program Powitanie, który wczytuje Twoje imię i nazwisko z klawiatury, a następnie wyświetla spersonalizowane powitanie.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Program - Powitanie
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <string>

using namespace std;

string imie, nazwisko;

int main() {
    cout << "Podaj swoje imię: ";
    cin >> imie;
    cout << "Podaj swoje nazwisko: ";
    cin >> nazwisko;
    cout << "Witaj " << imie << " " << nazwisko <<  "! Życzę miłego dnia:)";

    return 0;
}

Wynikiem działania programu Powitanie jest:

Podaj swoje imię: Paweł
Podaj swoje nazwisko: Malinowski
Witaj Paweł Malinowski! Życzę miłego dnia:)

Kolorem zielonym oznaczono dane wprowadzone przez użytkownika. W każdym programie analizie podlegają tylko nowe rzeczy. Dlatego warto rozpocząć wykład od początku.


Analiza programu: Powitanie

Za pomocą instrukcji #include dołączana jest biblioteka string obsługująca łańcuchy (ciągi znaków). Nastepnie deklarowane są dwie zmienne globalne: imie oraz nazwisko typu string. Funkcja główna wypisuje na ekranie prośbę o podanie imienia. Instrukcja cin >> imie; wczytuje z klawiatury imię użytkownika i zapisuje je do zmiennej imie. cin jest to skrót od Console Input. To samo program wykonuje dla drugiej zmiennej nazwisko. Podane z klawiatury nazwisko zapisywane jest w zmiennej nazwisko. Następnie za pomocą instrukcji cout wypisywany jest łańcuch znaków oraz zmiennych.


Program Przeliczanie temperatury oczekuje podania przez użytkownika temperatury w stopniach Celcjusza, a jako wynik wypisuje temperaturę w stopniach Fahrenheita i Kelvina.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Program - Przeliczanie temperatury
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

float celsjusz, fahrenheit, kelvin;

int main()
{
    cout << "Proszę podać temperaturę (°C): ";
    cin >> celsjusz;
    fahrenheit = (celsjusz * 1.8) + 32;
    kelvin = celsjusz + 273.15;
    cout << "Temperatura w stopniach Fahrenheita wynosi: " << fahrenheit << endl;
    cout << "Temperatura w Kelvinach wynosi: " << kelvin;
    return 0;
}

Wynik działania programu Przeliczanie

Proszę podać temperaturę (°C): 100
Temperatura w stopniach Fahrenheita wynosi: 212
Temperatura w Kelvinach wynosi: 373.15

Analiza programu: Przeliczanie temperatury

W programie deklarowane są zmienne typu float o nazwach celsjusz, fahrenheit, kelvin. Następnie program pyta użytkownika o podanie temperatury w stopniach Celsjusza. Gdy użytkownik wprowadzi z klawiatury podaną wartość, program obliczy i wypisze temperatury w stopniach Fahrenheita oraz Kelvina.


Napiszmy program Średnia arytmetyczna, który pyta o trzy liczby całkowite i wylicza średnią arytmetyczną z podanych liczb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Program - Średnia arytmetyczna
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int a,b,c;
    float srednia;
    cout << "Prosze wprowadzic kolejno trzy liczby calkowite:" << endl;
    cout << "Podaj pierwsza liczbe: ";
    cin >> a;
    cout << "Podaj druga liczbe: ";
    cin >> b;
    cout << "Podaj trzecia liczbe: ";
    cin >> c;
    srednia = (float) (a + b + c)/3;
    cout << "Srednia arytmetyczna z podanych liczb wynosi: " << srednia;

    return 0;
}
Prosze wprowadzic kolejno trzy liczby ca│kowite:
Podaj pierwsza liczbe: 2
Podaj druga liczbe: 8
Podaj trzecia liczbe: 3
Srednia arytmetyczna z podanych liczb wynosi: 4.33333

Analiza programu: Średnia arytmetyczna

W programie deklarowane są trzy zmienne typu całkowitego oraz jedna typu float. Następnie program prosi o podanie wartości trzech liczb całkowitych i zapisuje je do zmiennych a,b,c. W kolejnym kroku oblicza średnią arytmetyczną i wypisuje jej wynik na ekranie.

Zwróćmy uwagę na linię 19 programu.
srednia = (float) (a + b + c)/3;
W linii zastosowano tzw. rzutowanie typów oznaczone jako (float). Chodzi o to, że gdyby nie było tego zapisu to nastąpiłoby dzielenie całkowite, a wynik nie byłby dokładną wartością.
Przykład: Proszę usunąć zapis (float) z kodu programu i wykonać program dla następujących liczb: 3, 3, 8.
Średnia arytmetyczna z tych liczb wynosi: 4.666. Natomiast program obliczy to jako 4. Dlatego musimy zastosować rzutowanie typów.


  1. Napisz program, który pyta o podanie odległości w milach morskich i zamienia ją na metry (1 mila morska to 1852 metry).
  2. Napisz program, który pyta użytkownika o wiek w latach i wypisuje wiek w miesiącach.
  3. Napisz program, który pyta użytkownika o wzrost w metrach i wagę w kilogramach i wypisuje wskaźnik BMI. (BMI = masa/wzrost2).
  1. Co to jest strumień wyjściowy?
  2. Co to jest strumień wejściowy?
  3. Jakiego obiektu używamy do wyprowadzenia danych na ekran monitora?
  4. Jakiego obiektu używamy do wprowadzania danych z klawiatury?
  5. Co oznaczają tzw. operatory przekierowania strumienia << lub >> ?

Instrukcje / sterowanie przepływem


Instrukcja warunkowa if

Instrukcja warunkowa służy do podejmowania decyzji w programie. Dzięki tej konstrukcji językowej, programy stają się bardziej złożone (rozbudowane). Instrukcja if działa następująco. Jeżeli warunek jest prawdziwy to zostaje wykonana instrukcja lub blok instrukcji. Jeżeli warunek jest fałszywy to nie zostanie wykonana żadna instrukcja.


Składnia instrukcji warunkowej if
if (warunek) instrukcja1;




Przykład:
if (a > 10) cout << "Zmienna a jest większa od 10";

if (b == 64)
{
a = 0;
b = 0;
}

Istnieje jeszcze druga odmiana instrukcji warunkowej:

if (warunek) instrukcja1;
else instrukcja2;




Przykład:
if (wiek >=18) cout << "Jesteś pełnoletni.";
else cout << "Jesteś niepełnoletni.";


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* Program - Instrukcja warunkowa
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int a,b,c;
    a = 15;
    b = 7;
    if (2 * b > a) cout << "2 * " << b << " jest większe od " << a;
    else cout << "2 * " << b << " jest mniejsze od " << a;

    return 0;
}
2 * 7 jest mniejsze od 15

Kolejna odmiana instrukcji warunkowej if:
if (warunek1) instrukcja1;
else if (warunek2) instrukcja2;
else instrukcja3;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* Program - Złożona instrukcja warunkowa
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int wzrost;
    cout << "Podaj swój wzrost (cm):";
    cin >> wzrost;

    if (wzrost > 180)
    {
        cout << "Możesz zostać koszykarzem. \n";
        cout << "==========================\n";
        if (wzrost <= 190) cout << "Mógłbyś być rozgrywającym\n";
        else if (wzrost <= 205) cout << "Mógłbyś grać na pozycjach rzucającego obrońcy, skrzydłowego lub silnego skrzydłowego\n";
        else cout << "Możesz być centrem.";

    }
    else
    cout << "Prawdopodobnie nie zostaniesz koszykarzem.";

    return 0;
}
Podaj swój wzrost (cm): 178
Prawdopodobnie nie zostaniesz koszykarzem.

Podaj swój wzrost (cm): 185
Możesz zostać koszykarzem.
==========================
Mógłbyś być rozgrywającym.

Podaj swój wzrost (cm): 198
Możesz zostać koszykarzem.
==========================
Mógłbyś grać na pozycjach rzucającego obrońcy, skrzydłowego lub silnego skrzydłowego.

Podaj swój wzrost (cm): 214
Możesz zostać koszykarzem.
==========================
Możesz być centrem.

Instrukcja wyboru switch


Składnia instrukcji switch:
switch(wyrażenie-całkowite)
{
case etykieta1: instrukcja(e)
case etykieta2: instrukcja(e)
case etykieta3: instrukcja(e)
...
default: instrukcja(e)
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Program - Instrukcja wyboru switch
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int ile_jezykow;
    cout << "Ile znasz języków: ";
    cin >> ile_jezykow;

    if (ile_jezykow > 0)
    {
        switch(ile_jezykow)
        {
            case 1: cout << "Jesteś bohaterem. Znasz swój ojczysty język.";
                    break;
            case 2: cout << "Oprócz języka ojczystego znasz dodatkowo język obcy.";
                    break;
            case 3: cout << "Możesz pochwalić się znajomością dwóch języków obcych.";
                    break;
            default: cout << "Brawo. Jesteś prawdziwym poliglotą.";

        }
    }

    return 0;
}

Ile znasz języków: 1
Jesteś bohaterem. Znasz swój ojczysty język.

Ile znasz języków: 2
Oprócz języka ojczystego znasz dodatkowo język obcy.

Ile znasz języków: 3
Możesz pochwalić się znajomością dwóch języków obcych.

Ile znasz języków: 5
Brawo. Jesteś prawdziwym poliglotą.

Pętle


Pętla for


Składnia pętli for:
for (inicjalizacja; warunek; aktualizacja)
{
instrukcje;
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Program - P«tla for
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int liczba;
    cout << "Podaj liczbę całkowitą (0 - 100): ";
    cin >> liczba;

    for (int i = 0; i < liczba; i++)
        {
            cout << "To jest liczba: " << i + 1 << endl;
        }
    return 0;
}
Podaj liczbę całkowitą (0 - 100): 10
To jest liczba: 1
To jest liczba: 2
To jest liczba: 3
To jest liczba: 4
To jest liczba: 5
To jest liczba: 6
To jest liczba: 7
To jest liczba: 8
To jest liczba: 9
To jest liczba: 10

Pętla while


Składnia pętli while:
while (warunek)
{
instrukcje;
}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* Program - Pętla for
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int liczba, i = 0;
    cout << "Podaj liczbę całkowitą (0 - 100): ";
    cin >> liczba;

    while (i < liczba)
    {
        cout << "To jest liczba: " << i + 1 << endl;
        i++;
    }
    return 0;
}

Podaj liczbę całkowitą (0 - 100): 10
To jest liczba: 1
To jest liczba: 2
To jest liczba: 3
To jest liczba: 4
To jest liczba: 5
To jest liczba: 6
To jest liczba: 7
To jest liczba: 8
To jest liczba: 9
To jest liczba: 10

Pętla do ... while


Składnia pętli do ... while:
do
{
instrukcje;
}
while (warunek);




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Program - Pętla do while
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int liczba, i = 0;
    cout << "Podaj liczbę całkowitą (0 - 100): ";
    cin >> liczba;

    do
    {
        cout << "To jest liczba: " << i + 1 << endl;
        i++;
    } while(i < liczba);

    return 0;
}

Podaj liczbę całkowitą (0 - 100): 10
To jest liczba: 1
To jest liczba: 2
To jest liczba: 3
To jest liczba: 4
To jest liczba: 5
To jest liczba: 6
To jest liczba: 7
To jest liczba: 8
To jest liczba: 9
To jest liczba: 10

Instrukcja break


Instrukcja break umożliwia programowi pominięcie części kodu. Instrukcja ta jest stosowana w instrukcjach wyboru (switch) oraz w pętlach. Kompilator po napotkaniu instrukcji break; opuszcza dany blok kodu zawarty w nawiasach {}.

Przykład:




Instrukcja continue


Instrukcja continue umożliwia ominięcie fragmentu kodu. Instrukcja ta stosowana jest w pętlach. Gdy kompilator napotka instrukcję continue przerywa wykonywane instrukcje i przechodzi do następnej iteracji pętli.

Przykład:




  1. Napisz program, który zapyta Cię o wiek. Jeśli jesteś pełnoletni na ekranie pojawi się napis - Witaj, jesteś pełnoletni. Jeśli nie masz 18 lat, program wypisze na ekranie - Niestety jeszcze nie jesteś pełnoletni.
  2. Napisz prosty program do logowania. Jeśli jako login podasz - Zenon, a jako hasło - G56y, to zostaniesz zalogowany i wyświetli się napis - Witamy w systemie. Jeśli wprowadzisz błędne dane logowania - program wyświetli napis - Niestety wprowadziłeś błędny login lub hasło.
  3. Napisz program, który zapyta cię ile masz dzieci. Na każde dziecko przypada 500zł. W zależności od ilości dzieci, program pokaże ile powinieneś otrzymać z programu 500+. Zastosuj instrukcję switch. Założenie: maksymalna ilość dzieci w programie - 5.
  4. Napisz program, który wypisze liczby od 10 do 20 za pomocą pętli for, while i do-while.
  5. *Napisz program, który wypisze liczby od 20 do 0 co dwie (20,18,16 ...) za pomocą pętli for, while, do-while.
  6. Napisz program, który wypisze liczby od 1 do 100. W środku pętli umieść warunek, że jeśli iterator będzie równy 23, opuść pętlę za pomocą instrukcji break.
  7. Napisz program, który wypisuje liczby od 1 do 20. Jeśli napotka liczbę 13 to opuść wykonanie pętli za pomocą instrukcji continue.
  1. Podaj składnię instrukcji warunkowej wraz z jej schematem blokowym.
  2. Podaj na przykładzie składnię instrukcji wyboru.
  3. Wymień jakie znasz rodzaje pętli, czym one się różnią, podaj schematy blokowe każdej z nich.
  4. Omów działanie instrukcji break, podaj schemat blokowy.
  5. Omów działanie instrukcji continue, podaj schemat blokowy.

Pliki tekstowe


Zapis do pliku tekstowego


W celu wykonania operacji zapisu danych do pliku należy wykonać następujące czynności:
  • utworzyć obiekt klasy ofstream do obsługi strumienia wyjściowego,
  • skojarzyć ten obiekt z plikiem,
  • używać tego obiektu w taki sam sposób jak obiektu cout - jedyną różnicą jest to, że dane wyjściowe są wysyłane do pliku, a nie na ekran.

W pierwszej kolejności dołączamy bibliotekę fstream, następnie tworzymy obiekt klasy ofstream - output file stream np.

ofstream fout;

W drugim kroku musimy skojarzyć ten obiekt z plikiem. Służy do tego metoda open().

fout.open("data.txt");

Te dwie instrukcje możemy zastąpić jedną:

ofstream fout("data.txt");

Od tego momentu możemy używać obiektu fout tak samo jak obiektu cout. Jeśli chcemy zapisać w pliku następujący łańcuch: "Informacje zapisane w pliku", to wystarczy użyć następującej instrukcji:

fout << "Informacje zapisane w pliku";

Możemy tak zrobić ponieważ klasą bazową klasy ofstream jest klasa ostream, włącznie z metodami i manipulatorami formatującymi.
Poniżej przykład programu zapisującego powitanie do pliku data.txt.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Program - ofstream - zapis
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    string imie;
    ofstream fout("data.txt");  //otwarcie pliku
    cout << "Zapis danych do pliku rozpoczęty\n";   //zapis do pliku
    cout << "Podaj swoje imię:";
    cin >> imie;
    fout << "Witaj, " << imie << endl;
    fout.close();   //zamknięcie pliku

    return 0;
}

Widzimy, że obiekt musimy otworzyć oraz zamknąć, aby zwolnić zasoby. Obiekt fout wykorzystany był dokładnie tak jak do tej pory korzystaliśmy z obiektu cout.


Poniższy program odczytuje zawartość pliku data.txt z wykorzystaniem obiektu klasy ifstream - input file stream, np.

ifstream fin;

Dalej musimy skojarzyć obiekt z plikiem data.txt, wykonując poniższą instrukcję:

fin.open("data.txt");

Te dwie instrukcje możemy zastąpić jedną:

ifstream fin("data.txt");


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Program - ofstream - odczyt
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    string imie;
    ifstream fin("data.txt");  //otwarcie pliku
    cout << "To jest zawartość pliku data.txt\n";
    char ch;
    while(fin.get(ch))  //odczytaj znak
        cout << ch;     //wypisz go na ekranie
    fin.close();    //zamknięcie pliku

    return 0;
}

Odczyt danych z pliku data.txt odbywa się znak po znaku.


Tryby otwarcia pliku


Tryb otwarcia pliku określa sposób, w jaki dany plik ma być używany: do odczytu, zapisu, plik binarny, itp. Do tej pory nie podawaliśmy drugiego argumentu w metodzie open czy podczas inicjalizacji obiektu strumienia plikowego z nazwą pliku.


Stała Znaczenie
ios::in Otwórz plik do odczytu.
ios::out Otwórz plik do zapisu.
ios::ate Po otwarciu pliku ustaw się na jego końcu.
ios::app Dołącz na koniec pliku.
ios::trunc Zredukuj rozmiar pliku do zera, jeśli istnieje.
ios::binary Plik binarny.

W metodzie open klasy ifstream domyślną wartością drugiego argumentu (tryb otwarcia pliku) jest ios::in (otwórz plik do odczytu), a w przypadku klasy ofstream domyślną wartością jest ios::out | ios::trunc (otwórz plik do zapisu i zredukuj rozmiar pliku do zera).
Dla obiektu klasy ofstream oznacza to, iż jeśli plik już istnieje, to nastąpi zredukowanie jego rozmiaru do zera - czyli usunięcie, a następnie zapisanie danych od początku pliku.
Aby można było dopisać dane na końcu pliku (wielokrotne otwieranie pliku w trybie do zapisu) należy użyć następującego trybu otwarcia pliku:
ios::out | ios::app


Pliki binarne


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* Program - ofstream - odczyt
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    char napis[30];
    ofstream fout("data.dat", ios::out | ios::app | ios::binary);  //otwarcie pliku binarnego
    cout << "Wpisz tekst, który chcesz zapisać w pliku binarnym\n";
    cin.get(napis,30);
    fout.write(napis, sizeof napis);
    fout.close();   //zamknięcie pliku

    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* Program - ofstream - odczyt
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    char napis[30];
    ifstream fin("data.dat", ios::in | ios::binary);  //otwarcie pliku binarnego

    while(fin.read(napis, sizeof napis))
        cout << napis;
    fin.close();   //zamknięcie pliku

    return 0;
}

Poniżej przykładowy plik binarny.




Przykład wykorzystania klasy fstream do zapisu i odczytu danych. Wykorzystanie metody open() na rzecz obiektu klasy fstream o nazwie plik.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* Program - fstream - zapis
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    fstream plik;
    string imie, nazwisko, miejsce_urodzenia, wojewodztwo;

    cout << "Podaj imie: ";
    cin >> imie;
    cout << "Podaj nazwisko: ";
    cin >> nazwisko;
    cout << "Podaj miejsce urodzenia: ";
    cin >> miejsce_urodzenia;
    cout << "Podaj z jakiego jesteś województwa: ";
    cin >> wojewodztwo;

    plik.open("/Users/pawelmalinowski/Documents/C++/q/dane.txt", ios::out | ios::app);

    plik << "Imię:\t\t\t" << imie << endl;
    plik << "Nazwisko:\t\t" << nazwisko << endl;
    plik << "Miejsce urodzenia:\t" << miejsce_urodzenia << endl;\
    plik << "Wojewodztwo:\t\t" << wojewodztwo << endl;


    return 0;
}
Imię:			Paweł
Nazwisko:		Malinowski
Miejsce urodzenia:	Prudnik
Województwo:		opolskie

Odczyt z pliku tekstowego


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/* Program - fstream - odczyt
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

int main()
{
    fstream plik;
    string imie, nazwisko, miejsce_urodzenia, wojewodztwo;

    plik.open("/Users/pawelmalinowski/Documents/C++/q/dane.txt", ios::in);

    if (plik.good() == true)
    {
        string linia;
        int licznik = 1;
        while(getline(plik, linia))
        {
            switch(licznik)
            {
                case 1: imie = linia; break;
                case 2: nazwisko = linia; break;
                case 3: miejsce_urodzenia = linia; break;
                case 4: wojewodztwo = linia; break;
            }
            licznik++;
        }

        cout << imie << endl;
        cout << nazwisko << endl;
        cout << miejsce_urodzenia << endl;
        cout << wojewodztwo << endl;
    }
    else
    {
        cout << "Plik nie istnieje!";
        exit(0);
    }

    return 0;
}
Imię:			Paweł
Nazwisko:		Malinowski
Miejsce urodzenia:	Prudnik
Województwo:		opolskie

  1. Napisz program, który zapyta cię o następujące informacje: imię, nazwisko, płeć, wykształcenie, zawód. Zapisz te informacje w pliku dane.txt.
  2. Napisz program, który odczyta z pliku dane.txt informacje o twoim imieniu, nazwisku, płci, wykształceniu oraz zawodzie i wyświetli je na ekranie.
  3. Napisz program, który zapisuje dowolny ciąg znaków podany z klawiatury do pliku w trybie binarnym.
  4. Napisz program, który odczytuje te dane z pliku binarnego.
  1. Co to jest klasa fstream?
  2. Co to jest klasa ifstream i ofstream?
  3. Jak zapisać dane do pliku?
  4. Jak odczytać dane z pliku?
  5. Jakie znasz tryby otwarcia pliku?
  6. Jak można otworzyć plik (binarny) w trybie do zapisu?
  7. Jak można otworzyć plik (binarny) w trybie do odczytu?

Funkcje


Funkcje to inaczej podprogramy. Koncepcja funkcji umożliwia napisanie jednej funkcji i wywołanie jej w programie setki razy. Dzięki temu oszczędzamy czas, porządkujemy kod, a jeśli chcemy zmienić ciało funkcji robimy to w jednym miejscu.
Aby użyć funkcji w C++ należy:
  • podać definicję funkcji,
  • podać prototyp funkcji,
  • wywołać funkcję.
Przykład 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* Program - funkcja
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void funkcja();     //prototyp funkcji

int main()
{
    funkcja();      //wywołanie funkcji
    funkcja();      //kolejne wywołanie funkcji
    return 0;
}

//definicja funkcji
void funkcja()
{
    using namespace std;
    cout << "Funkcja wykonała się.\n";
}

W powyższym przykładzie widzimy wszystkie trzy elementy tzn. definicja funkcji, prototyp funkcji oraz wywołanie funkcji.


Definicja funkcji - to inaczej ciało funkcji
Funkcje można podzielić na dwa typy:
  • Niezwracające wartości (procedury - typ void)
  • Zwracające wartość (funkcje)

Składnia funkcji niezwracającej żadnej wartości:


void nazwa_funkcji(listaParametrów)
{
instrukcja/e
}

listaParametrów określa liczbę i typy danych parametrów przekazywanych funkcji.

Przykład:

void witaj(string imie)
{
cout << "Witaj " << imie;
}
Wywołanie tej funkcji w programie może wyglądać tak:
witaj("Paweł");


Składnia funkcji zwracającej wartość:


typ_danych nazwa_funkcji(listaParametrów)
{
instrukcja/e
return wartość;
}

Przykład:

int suma(int a, int b)
{
return a + b;
}

Prototyp funkcji - to nazwa funkcji z zestawem argumentów poprzedzonych typem danych.

Składnia prototypu:
typ_danych nazwa_funkcji(typ_danych argument1, typ_danych argument2,...);

Przykład:
int suma(int a, int b);

Prototyp opisuje interfejs funkcji na potrzeby kompilatora, czyli mówi kompilatorowi, jaki jest typ wartości zwracanej przez funkcję, a także ile jest argumentów i jakie są ich typy.

Prototyp funkcji umieszczamy przed funkcją main(), aby funkcja główna wiedziała jakich funkcji może sie spodziewać, jaka jest ich budowa. Natomiast ciało funkcji - definicja umieszczana jest za funkcją główną main().

Definicja funkcji - mówi nam jak funkcja jest zbudowana (jakiego typu), jakie przyjmuje argumenty oraz jak wygląda ciało funkcji.

Wywołanie funkcji - jest to instrukcja wywołująca po nazwie funkcję wraz z argumentami. Dzięki wywołaniu możemy zobaczyć efekt działania funkcji.


Przykłady funkcji:
Przykład 1:
Funkcja, której zadaniem będzie przeliczanie temperatury ze stopni Celcjusza na Kelviny i stopnie Fahrenheita.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* Program - Przeliczanie temperatury - funkcja
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void temperatura(float c);  // prototyp funkcji

float celsjusz;

int main()
{
    cout << "Proszę podać temperaturę (°C): ";
    cin >> celsjusz;
    temperatura(celsjusz);  // wywołanie funkcji
    return 0;
}

void temperatura(float c)   // definicja funkcji
{
    float fahrenheit, kelvin;
    fahrenheit = (celsjusz * 1.8) + 32;
    kelvin = celsjusz + 273.15;
    cout << "Temperatura w stopniach Fahrenheita wynosi: " << fahrenheit << endl;
    cout << "Temperatura w Kelvinach wynosi: " << kelvin;
}


Przykład 2:
Funkcja, której zadaniem będzie obliczenie średniej arytmetycznej trzech podanych liczb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Program - Średnia arytmetyczna - funkcja
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int a, b, c;

float srednia(int x, int y, int z); // prototyp funkcji

int main()
{
    cout << "Prosze wprowadzic kolejno trzy liczby calkowite:" << endl;
    cout << "Podaj pierwsza liczbe: ";
    cin >> a;
    cout << "Podaj druga liczbe: ";
    cin >> b;
    cout << "Podaj trzecia liczbe: ";
    cin >> c;

    cout << "Srednia arytmetyczna z podanych liczb wynosi: " << srednia(a, b, c);   // wywołanie funkcji

    return 0;
}

float srednia(int x, int y, int z)  // definicja funkcji
{
    return (float) (x + y + z)/3;
}


Przykład 3:
Funkcja, której zadaniem będzie zrealizowanie petli for za pomocą funkcji.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* Program - Pętla for - funkcja
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void petla_for(int x);  // prototyp funkcji

int main()
{
    int liczba;
    cout << "Podaj liczbę całkowitą (0 - 100): ";
    cin >> liczba;

    petla_for(liczba);  // wywołanie funkcji
    return 0;
}

void petla_for(int x)   // definicja funkcji
{
    for (int i = 0; i < x; i++)
        {
            cout << "To jest liczba: " << i + 1 << endl;
        }
}


Przykład 4:
Funkcja, której zadaniem będzie zrealizowanie petli while za pomocą funkcji.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Program - Pętla for
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void petla_while(int x);    // prototyp funkcji

int main()
{
    int liczba;
    cout << "Podaj liczbę całkowitą (0 - 100): ";
    cin >> liczba;

    petla_while(liczba);    // wywołanie funkcji

    return 0;
}

void petla_while(int x)     // definicja funkcji
{
    int i = 0;
    while (i < x)
    {
        using namespace std;
        cout << "To jest liczba: " << i + 1 << endl;
        i++;
    }
}


Przykład 5:
Funkcja, której zadaniem będzie zrealizowanie petli do while za pomocą funkcji.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* Program - Pętla do while - funkcja
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void petla_do_while(int x); // prototyp funkcji

int main()
{
    int liczba;
    cout << "Podaj liczbę całkowitą (0 - 100): ";
    cin >> liczba;

    petla_do_while(liczba); // wywołanie funkcji

    return 0;
}

void petla_do_while(int x)  // definicja funkcji
{
    using namespace std;
    int i = 0;
    do
    {
        cout << "To jest liczba: " << i + 1 << endl;
        i++;
    } while(i < x);
}


Przykład 6:
Funkcja, której zadaniem będzie obliczenie wskaźnika BMI.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* Program - BMI - funkcja
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

float wzrost, waga;

float BMI(float wzr, float wag);    // prototyp funkcji

int main()
{
    int liczba;
    cout << "Podaj swój wzrost:";
    cin >> wzrost;
    cout << "Podaj swóją wagę:";
    cin >> waga;

    cout << "Twój wskaźnik BMI wynosi: " << BMI(wzrost, waga);  // wywołanie funkcji
    return 0;
}

float BMI(float wzr, float wag)     // definicja funkcji
{
    return wag/(wzr*wzr);
}

Przekazywanie parametrów przez wartość lub przez referencje


Wszystkie powyższe funkcje zawarte w tym rozdziale przekazywały argumenty przez wartość. Oznacza to, że do funkcji została przesłana kopia wartości parametru. Oryginalna wartość parametru pozostaje bez zmiany.
W tej części zostanie przedstawiony sposób przekazywania parametrów do funkcji poprzez tzw. referencje. Oznacza to, że do funkcji zostanie przesłana oryginalna wartość parametru, który może zostać zmieniony w trakcie działania funkcji.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* Program - zamiana - przekazywanie parametrów przez referencję
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void zamien(int & a, int & b);  //a i b to aliasy zmiennych przekazywanych do funkcji

int main()
{
    int z1 = 123;
    int z2 = 321;

    cout << "Wartość zmiennej z1 wynosi: " << z1 << endl;
    cout << "Wartość zmiennej z2 wynosi: " << z2 << endl;

    cout << "Wywołanie funkcji zamien!" << endl;
    zamien(z1, z2);
    cout << "Zmienna z1 ma teraz wartość: " << z1 << endl;
    cout << "Zmienna z2 ma teraz wartość: " << z2 << endl;

    return 0;
}

void zamien(int & a, int & b)
{
    int pomocnicza;
    pomocnicza = a;
    a = b;
    b = pomocnicza;
}

Przykład ten pokazuje, że funkcja zamień pracowała na oryginalnych wartościach i zamieniła pierwotne wartości zmiennych z1 oraz z2.


Przeciążanie funkcji


Przeciążanie funkcji - inaczej polimorfizm (wielopostaciowość) pozwala używać wielu funkcji o takiej samej nazwie. Korzystając z przeciążania funkcji (polimorfizmu) możemy zdefiniować całą rodzinę funkcji realizujących te same zadania, ale pracujących na różnych zestawach parametrów.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
43
43
44
45
46
/* Program - przeciążanie nazw funkcji
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

float pole(float r);        //pole koła
int pole(int a);            //pole kwadratu
int pole(int a, int b);     //pole prostokąta

int main()
{
    float promien;
    int a, b;
    cout << "Podaj promien koła: ";
    cin >> promien;
    cout << "Pole koła o promieniu " << promien << " wynosi: " << pole(promien) << endl;

    cout << "Podaj długość boku kwadratu: ";
    cin >> a;
    cout << "Pole kwadratu o boku " << a << " wynosi: " << pole(a) << endl;

    cout << "Podaj długość pierwszego boku prostokąta: ";
    cin >> a;
    cout << "Podaj długość drugiego boku prostokąta: ";
    cin >> b;
    cout << "Pole prostokąta o bokach " << a << " i " << b << " wynosi: " << pole(a,b);

    return 0;
}

float pole(float r)
{
    return 3.14 * r * r;
}

int pole(int a)
{
    return a * a;
}

int pole(int a, int b)
{
    return a * b;
}

Rekurencja


Rekurencja to inaczej wywoływanie funkcji wewnętrz samej siebie.


Przykład:

Algorytm obliczania silni w sposób rekurencyjny


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Program - obliczanie silni rekurencyjnie
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int silnia(int n);

int main()
{

    return 0;
}

int silnia(int n)
{
    if(n < 2)
        return 1;
    return n * silnia(n - 1);           
}

Przykład:

Wyznacz sumę kolejnych liczb naturalnych z wykorzystaniem algorytmu rekurencyjnego.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Program - obliczanie kolejnych liczb naturalnych - rekurencyjnie
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int suma(int n);

int main()
{

    return 0;
}

int suma(int n)
{
    if(n < 1)
        return 0;
    return n + suma(n - 1);           
}

  1. Napisz program, który obliczy średnią geometryczną trzech wczytanych liczb za pomocą funkcji.
  2. Napisz program, który wyświetli na ekranie pierwszych 10 znaków ciągu Fibonacciego.
  3. Napisz program, który obliczy wartość funkcji f(x) = 2x2 - 8x. Parametr przekaż do funkcji poprzez referencję.
  1. Co to jest funkcja?
  2. Co to jest prototyp, definicja i wywołanie funkcji?
  3. Jakie znasz typy funkcji?
  4. Co oznacza, że przekazujemy do funkcji argument/y?
  5. Jak przesyłamy do funkcji parametry przez wartość?
  6. Jak przesyłamy do funkcji parametry przez referencję?

Złożone typy danych


Tablice


Tablica - to struktura danych, która może przechowywać wiele wartości tego samego typu. Gdyby tablice nie istniały to musielibyśmy deklarować dziesiątki czy setki oddzielnych zmiennych w celu realizacji jakiegoś złożonego zadania. Ale na szczęście tablice istnieją i deklarujemy tylko jedną zmienną tablicową określonego typu, podając jednocześnie ilość elementów tablicy. Aby utworzyć tablicę, należy podać trzy elementy:

  • typ wartości elementów tablicy,
  • nazwę tablicy,
  • liczbę elementów tablicy.
Przykład: Deklaracja tablicy jednowymiarowej:

int miesiace[12];

Zmienna typu tablicowego o nazwie miesiace zawiera 12 szufladek na zmienne typu int. Aby dostać się do wartości poszczególnych szufladek używa się następującego zapisu:
  • miesiace[0] - pierwsza szufladka
  • miesiace[1] - druga szufladka
  • ................................
  • miesiace[11] - dwunasta szufladka
Cyfry podawane w nawiasach kwadratowych [ ] nazywamy indeksami tablicy. Zauważmy, że pierwszy element tablicy posiada indeks równy 0.
Tablicę można również zainicjalizować:
string miesiace[12] = {"styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień"};

Tablica jest typem złożonym, ponieważ zbudowana jest na bazie innego typu.



Ciąg arytmetyczny.


Przykład:
Napisz program, który oblicza n-ty wyraz ciągu arytmetycznego oraz oblicza sumę n-początkowych wyrazów tego ciągu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* Program - tablice
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void ciag_a(int p, int r);

int main()
{
    int p,r;
    cout << "Podaj pierwszy wyraz ciągu: ";
    cin >> p;
    cout << "Podaj różnicę ciągu: ";
    cin >> r;

    ciag_a(p,r);

    return 0;
}

void ciag_a(int p, int r)
{
    int tab_a[3][100] = {};   //deklaracja tablicy wyzerowanie wartości wszystkich komórek
    tab_a[0][0] = 1;
    tab_a[1][0] = p;
    tab_a[2][0] = p;

    for (int i = 1; i < 100; i++)
    {
        tab_a[0][i] = i + 1;
        tab_a[1][i] = tab_a[1][i - 1] + r;
        tab_a[2][i] = i * (p + tab_a[1][i]) / 2;
    }

    for (int i = 0; i < 100; i++)
    {
        cout << tab_a[0][i] << "\t" << tab_a[1][i] << "\t" << tab_a[2][i] << endl;
    }
}

Podaj pierwszy wyraz ciągu: 2
Podaj różnicę ciągu: 3
1	2	2
2	5	3
3	8	10
4	11	19
5	14	32
6	17	47
7	20	66
8	23	87
9	26	112
10	29	139
11	32	170
12	35	203
13	38	240
14	41	279
15	44	322
16	47	367
17	50	416
18	53	467
19	56	522
20	59	579
21	62	640
22	65	703
23	68	770
24	71	839
25	74	912
26	77	987
27	80	1066
28	83	1147
29	86	1232
30	89	1319
31	92	1410
32	95	1503
33	98	1600
34	101	1699
35	104	1802
36	107	1907
37	110	2016
38	113	2127
39	116	2242
40	119	2359
41	122	2480
42	125	2603
43	128	2730
44	131	2859
45	134	2992
46	137	3127
47	140	3266
48	143	3407
49	146	3552
50	149	3699
51	152	3850
52	155	4003
53	158	4160
54	161	4319
55	164	4482
56	167	4647
57	170	4816
58	173	4987
59	176	5162
60	179	5339
61	182	5520
62	185	5703
63	188	5890
64	191	6079
65	194	6272
66	197	6467
67	200	6666
68	203	6867
69	206	7072
70	209	7279
71	212	7490
72	215	7703
73	218	7920
74	221	8139
75	224	8362
76	227	8587
77	230	8816
78	233	9047
79	236	9282
80	239	9519
81	242	9760
82	245	10003
83	248	10250
84	251	10499
85	254	10752
86	257	11007
87	260	11266
88	263	11527
89	266	11792
90	269	12059
91	272	12330
92	275	12603
93	278	12880
94	281	13159
95	284	13442
96	287	13727
97	290	14016
98	293	14307
99	296	14602
100	299	14899

Process returned 0 (0x0)   execution time : 19.851 s
Press ENTER to continue.

Ciąg geometryczny.



Przykład:
Napisz program, który oblicza n-ty wyraz ciągu geometrycznego oraz oblicza sumę n-początkowych wyrazów tego ciągu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/* Program - tablice
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <cmath>

using namespace std;

void ciag_g(int p, float q);

int main()
{
    int p;
    float q;
    cout << "Podaj pierwszy wyraz ciągu: ";
    cin >> p;
    cout << "Podaj iloraz ciągu geometrycznego: ";
    cin >> q;

    ciag_g(p,q);

    return 0;
}

void ciag_g(int p, float q)
{
    float tab_g[3][20] = {};   //deklaracja tablicy wyzerowanie wartości wszystkich komórek
    tab_g[0][0] = 1;
    tab_g[1][0] = p;
    tab_g[2][0] = p;

    for (int i = 1; i < 20; i++)
    {
        tab_g[0][i] = i + 1;
        tab_g[1][i] = tab_g[1][i - 1] * q;
        tab_g[2][i] = p * (1 - pow(q,i+1)) / (1 - q);
    }

    for (int i = 0; i < 20; i++)
    {
        cout << tab_g[0][i] << "\t" << tab_g[1][i] << "\t\t" << tab_g[2][i] << endl;
    }
}

Podaj pierwszy wyraz ciągu: 3
Podaj iloraz ciągu geometrycznego: 2
1	3		    3
2	6		    9
3	12		    21
4	24		    45
5	48		    93
6	96		    189
7	192		    381
8	384		    765
9	768		    1533
10	1536		    3069
11	3072		    6141
12	6144		    12285
13	12288		    24573
14	24576		    49149
15	49152		    98301
16	98304		    196605
17	196608		    393213
18	393216		    786429
19	786432		    1.57286e+06
20	1.57286e+06	    3.14572e+06

Process returned 0 (0x0)   execution time : 2.662 s
Press ENTER to continue.

Ciąg Fibonacciego.



Przykład:
Napisz program, który oblicza n-ty wyraz ciągu Fibonacciego.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* Program - ciąg Fibonnaciego - iteracyjnie
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

void ciag_f();

int main()
{
    ciag_f();

    return 0;
}

void ciag_f()
{
    long tab_f[100] = {};   //deklaracja tablicy wyzerowanie wartości wszystkich komórek
    tab_f[0] = 1;
    tab_f[1] = 1;

    for (int i = 2; i < 100; i++)
    {
        tab_f[i] = tab_f[i - 1] + tab_f[i - 2];
    }

    for (int i = 0; i < 93; i++)
    {
        cout << i + 1 << "\t" << tab_f[i] << endl;
    }
}

1	1
2	1
3	2
4	3
5	5
6	8
7	13
8	21
9	34
10	55
11	89
12	144
13	233
14	377
15	610
16	987
17	1597
18	2584
19	4181
20	6765
21	10946
22	17711
23	28657
24	46368
25	75025
26	121393
27	196418
28	317811
29	514229
30	832040
31	1346269
32	2178309
33	3524578
34	5702887
35	9227465
36	14930352
37	24157817
38	39088169
39	63245986
40	102334155
41	165580141
42	267914296
43	433494437
44	701408733
45	1134903170
46	1836311903
47	2971215073
48	4807526976
49	7778742049
50	12586269025
51	20365011074
52	32951280099
53	53316291173
54	86267571272
55	139583862445
56	225851433717
57	365435296162
58	591286729879
59	956722026041
60	1548008755920
61	2504730781961
62	4052739537881
63	6557470319842
64	10610209857723
65	17167680177565
66	27777890035288
67	44945570212853
68	72723460248141
69	117669030460994
70	190392490709135
71	308061521170129
72	498454011879264
73	806515533049393
74	1304969544928657
75	2111485077978050
76	3416454622906707
77	5527939700884757
78	8944394323791464
79	14472334024676221
80	23416728348467685
81	37889062373143906
82	61305790721611591
83	99194853094755497
84	160500643816367088
85	259695496911122585
86	420196140727489673
87	679891637638612258
88	1100087778366101931
89	1779979416004714189
90	2880067194370816120
91	4660046610375530309
92	7540113804746346429
93	-6246583658587674878

Process returned 0 (0x0)   execution time : 0.016 s
Press ENTER to continue.

Przykład:

Wyznacz n-ty wyraz ciągu Fibbonaciego rekurencyjnie.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* Program - ciąg Fibbonaciego - rekurencyjnie
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

long long fib(int n);

int main()
{
    int n = 40;
    cout << fib(n);
    return 0;
}

long long fib(int n)
{
    if(n < 3)
        return 1;
    return fib(n - 2) + fib(n - 1);           
}

Liczby pseudolosowe.


rand() % ile_liczb + liczba_początkowa


Przykład:

Chcemy wygenerować liczby z zakresu (7 - 46)

Obliczanie zakresu:

ile_liczb = koniec_zakresu - początek_zakresu + 1

ile_liczb = 46 - 7 + 1

ile_liczb = 40

rand() % 40 + 7


Aby włączyć generator liczb pseudolosowych należy wpisać następującą instrukcję:

srand(time(NULL));

Aby tego dokonać należy dołączyć biblioteki cstdlib (srand, rand) oraz time.h (time)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* Program - tablice
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;

int main()
{
    int tab[100] = {};

    srand(time(NULL));

    for (int i = 0; i < 100; i++)
    {
        tab[i] = rand() % 100 + 1;
    }

    for (int i = 0; i < 100; i++)
    {
        cout << i + 1 << "\t" << tab[i] << endl;
    }

    return 0;
}

1	55
2	24
3	91
4	69
5	6
6	99
7	28
8	89
9	100
10	3
11	31
12	39
13	96
14	65
15	56
16	63
17	11
18	99
19	67
20	8
21	18
22	65
23	34
24	77
25	77
26	4
27	87
28	75
29	27
30	18
31	53
32	48
33	88
34	26
35	59
36	64
37	92
38	2
39	13
40	90
41	79
42	37
43	85
44	61
45	21
46	43
47	12
48	30
49	99
50	100
51	8
52	3
53	50
54	78
55	92
56	46
57	32
58	23
59	48
60	59
61	47
62	98
63	91
64	7
65	43
66	2
67	54
68	15
69	73
70	60
71	22
72	9
73	36
74	61
75	72
76	16
77	87
78	68
79	80
80	16
81	78
82	28
83	95
84	25
85	95
86	79
87	3
88	82
89	77
90	67
91	77
92	34
93	50
94	41
95	73
96	70
97	32
98	38
99	75
100	89

Process returned 0 (0x0)   execution time : 0.042 s
Press ENTER to continue.

Sortowanie bąbelkowe


Zasada działania sortowania bąbelkowego




Sortowanie bąbelkowe polega na porównywaniu par liczb ze sobą (zaznaczone na niebiesko). Jeżeli porównanie liczb jest fałszywe (na czerwono) to następuje zamiana liczb ze sobą. W przeciwnym przypadku liczby pozostają na swoim miejscu. Algorytm wykorzystuje dwie pętle for zewnątrzną oraz wewnętrzną oraz funkcję swap, która zamienia liczby ze sobą. Jeżeli algorytm przejdzie przez wszystkie iteracje tych pętli, oznacza to, że zbiór jest posortowany.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Program - sortowanie bąbelkowe
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <cstdlib>

using namespace std;

void sortowanie_babelkowe(int tab[],int n)
{
	for(int i = 0; i < n; i++)
		for(int j = 1; j < n - i; j++)
		if(tab[j - 1] > tab[j])
			swap(tab[j - 1], tab[j]);
}

int main()
{
	int *tab;

	tab = new int [100];

    srand(time(NULL));

    for (int i = 0; i < 100; i++)
    {
        tab[i] = rand() % 101;
    }

    cout << "Tablica liczb pseudolosowych" << endl;
    for(int i = 0; i < 100; i++)
          cout << tab[i] << " ";

	sortowanie_babelkowe(tab, 100);
    cout << endl << endl;
    cout << "Tablica posortowana metodą bąbelkową:" << endl;

	for(int i = 0; i < 100; i++)
          cout << tab[i] << " ";

  return 0;
}

Tablica liczb pseudolosowych
70 94 44 75 92 2 68 87 23 15 47 40 91 33 10 40 18 54 23 40 61 43 86 63 95 89 9 93 80 62 37 40 11 9 34 60 49 34 62 98 44 97 13 80 16 19 62 0 70 34 60 64 65 41 37 71 35 40 100 14 32 13 51 26 34 8 30 70 27 25 76 85 32 6 9 31 70 52 78 92 72 94 10 84 95 43 5 63 77 9 40 71 100 96 67 51 92 98 80 60

Tablica posortowana metodą bąbelkową:
0 2 5 6 8 9 9 9 9 10 10 11 13 13 14 15 16 18 19 23 23 25 26 27 30 31 32 32 33 34 34 34 34 35 37 37 40 40 40 40 40 40 41 43 43 44 44 47 49 51 51 52 54 60 60 60 61 62 62 62 63 63 64 65 67 68 70 70 70 70 71 71 72 75 76 77 78 80 80 80 84 85 86 87 89 91 92 92 92 93 94 94 95 95 96 97 98 98 100 100
Process returned 0 (0x0)   execution time : 0.017 s
Press ENTER to continue.

Sortowanie szybkie - Quicksort


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/* Program - sortowanie szybkie - quicksort
 * Wykonał Paweł Malinowski */

#include <iostream>
#include <cstdlib>

using namespace std;

void quick_sort(int *tab, int lewy, int prawy)
{
	if(prawy <= lewy) return;

	int i = lewy - 1, j = prawy + 1,
	pivot = tab[(lewy+prawy)/2];

	while(1)
	{
		while(pivot>tab[++i]);

		while(pivot<tab[--j]);

		if( i <= j)
			swap(tab[i],tab[j]);
		else
			break;
	}

	if(j > lewy)
	quick_sort(tab, lewy, j);
	if(i < prawy)
	quick_sort(tab, i, prawy);
}
int main()
{
    int *tab;

	tab = new int [100];

    srand(time(NULL));

    for (int i = 0; i < 100; i++)
    {
        tab[i] = rand() % 101;
    }

    cout << "Tablica liczb pseudolosowych" << endl;
    for(int i = 0; i < 100; i++)
          cout << tab[i] << " ";

    quick_sort(tab,0, 99);
    cout << endl << endl;
    cout << "Tablica posortowana metodą quicksort:" << endl;

	for(int i = 0; i < 100; i++)
          cout << tab[i] << " ";

  	return 0;
}

Tablica liczb pseudolosowych
32 100 5 76 31 81 58 71 68 47 39 47 18 31 36 84 2 90 60 44 57 13 72 75 57 76 33 4 64 57 29 79 55 7 68 77 67 7 58 25 9 90 8 61 48 79 19 94 7 42 16 33 13 49 79 74 62 30 19 30 85 48 15 25 75 4 18 61 27 17 49 12 3 44 23 21 26 50 89 19 21 96 44 91 76 93 31 97 64 65 59 26 75 59 21 20 22 2 14 49

Tablica posortowana metodą quicksort:
2 2 3 4 4 5 7 7 7 8 9 12 13 13 14 15 16 17 18 18 19 19 19 20 21 21 21 22 23 25 25 26 26 27 29 30 30 31 31 31 32 33 33 36 39 42 44 44 44 47 47 48 48 49 49 49 50 55 57 57 57 58 58 59 59 60 61 61 62 64 64 65 67 68 68 71 72 74 75 75 75 76 76 76 77 79 79 79 81 84 85 89 90 90 91 93 94 96 97 100
Process returned 0 (0x0)   execution time : 0.015 s
Press ENTER to continue.

Struktury


Poznaliśmy już tablice, które przechowują dużą ilość danych tego samego typu. Struktura to taki typ danych, która może przechowywać dane różnego typu. Jeśli chciałbyś napisać większy program przechowujący dane np. w bazie danych to operowanie na tablicach byłoby uciążliwe. Dlatego wymyślono wygodniejszy sposób realizacji tego typu zadań poprzez zastosowanie nowego typu danych - struktury. W ten sposób możemy zaprojektować na przykład tablicę struktur, którą będziemy wykorzystywać w naszym programie.


Przykład: Deklaracja struktury
struct samochod
{
    string marka;
    string model;
    float pojemnosc;
    float przyspieszenie;
};

Każda struktura, typ wyliczeniowy i klasa w języku C++ po nawiasie klamrowym zamykającym (}) zawsze musi mieć średnik (;).

Przykład:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* Program - struktura
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

struct koszykarz
{
    string imie;
    string nazwisko;
    int wzrost;
    float waga;
    string klub;
};

int main()
{
    koszykarz MJ = { "Michael", "Jordan", 198, 98, "Chicago Bulls" };

    cout << "Kto jest najlepszym koszykarzem wszechczasów?\n";
    cout << MJ.imie << " " << MJ.nazwisko << " reprezentujący klub " << MJ.klub << endl;

    return 0;
}

Unie


Unia - to złożony typ danych podobny trochę do struktury, gdyż w skład unii może wchodzić wiele zmiennych różnego typu. Unię odróżnia to, że w danym momencie możemy korzystać tylko z jednej zmiennej. Ilość bitów przeznaczona na unię określona jest wielkością największego elementu w unii.
Unie stosujemy wtedy, gdy nie mamy pewności jakiego typu element będzie nam potrzebny w danym momencie. Podobnie jak ze strukturami można utworzyć tablicę unii. Unie można również wykorzystywać w strukturach czy klasach.


Typy wyliczeniowe


Typ wyliczeniowy ze słowem kluczowym enum, to mechanizm za pomocą którego możemy tworzyć nowe typy danych. Składnia polecenia enum jest zbliżona do składni struktur.

enum position
{
    "Point quard", "Shooting quard", "Small forward", "Power forward", "Center"
};

Wskaźniki


Wskaźniki - to zmienne przechowujące adres innej zmiennej. Zanim przejdziemy do wskaźników, adres zmiennej możemy uzyskać przez tzw. operator adresu (&) - znak ampersand.

int gruszki;
Aby odwołać się do adresu zmiennej gruszki w programie wystarczy wpisać:
&gruszki;


Przykład:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Program - adresy zmiennych
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int truskawki = 12;
    string samochod = "Subaru";

    cout << "Wartość zmiennej truskawki wynosi " << truskawki << endl;
    cout << "Wartość zmiennej samochod = " << samochod << endl;

    cout << "Wielkość zmiennej truskawki wynosi " << sizeof(truskawki) << endl;
    cout << "Wielkość zmiennej samochod wynosi " << sizeof(samochod) << endl;

    cout << "Adres zmiennej truskawki to " << &truskawki << endl;
    cout << "Adres zmiennej samochod to " << &samochod << endl;

    return 0;
}
Wartość zmiennej truskawki wynosi 12
Wartość zmiennej samochod = Subaru
Wielkość zmiennej truskawki wynosi 4
Wielkość zmiennej samochod wynosi 24
Adres zmiennej truskawki to 0x7ffeecd36a30
Adres zmiennej samochod to 0x7ffeecd36a18

Wskaźniki jak sama nazwa mówi wskazują na obszar w pamięci komputera innej zmiennej. Wskaźnik nie pokazuje wartości zmiennej, ale miejsce gdzie dana zmienna przechowywana jest w pamięci.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* Program - wskaźniki
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int truskawki = 12;
    int *w_truskawki;

    w_truskawki = &truskawki;   // przypisanie wskaźnikowi adresu zmiennej truskawki

    // pokazanie wartości zmiennej truskawki na dwa sposoby
    cout << "Pokazanie wartości zmiennej truskawki na dwa sposoby" << endl;
    cout << "Wartość zmiennej truskawki wynosi (truskawki) " << truskawki << endl;
    cout << "Wartość zmiennej truskawki wynosi (*w_truskawki) " << *w_truskawki << endl << endl;

    // pokazanie adresu zmiennej truskawki na dwa sposoby
    cout << "Pokazanie adresu zmiennej truskawki na dwa sposoby" << endl;
    cout << "Adres zmiennej truskawki to (&truskawki) " << &truskawki << endl;
    cout << "Adres zmiennej truskwaki to (w_truskawki) " << w_truskawki << endl << endl;

    // wykorzystanie wskaźnika do zmiany wartości zmiennej truksawki
    cout << "Za pomocą wskaźnika można zmienić wartość zmiennej truskawki:" << endl;
    *w_truskawki += 1;
    cout << "Wartość zmiennej truskawki wynosi teraz " << truskawki;

    return 0;
}

Pokazanie wartości zmiennej truskawki na dwa sposoby:
Wartość zmiennej truskawki wynosi (truskawki) 12
Wartość zmiennej truskawki wynosi (*w_truskawki) 12

Pokazanie adresu zmiennej truskawki na dwa sposoby:
Adres zmiennej truskawki to (&truskawki) 0x7ffee21b9a18
Adres zmiennej truskwaki to (w_truskawki) 0x7ffee21b9a18

Za pomocą wskaźnika można zmienić wartość zmiennej truskawki:
Wartość zmiennej truskawki wynosi teraz 13

Zapamiętaj!.
Zmienna truskawki i wskaźnik *w_truskawki są równoważne i pokazują wartość zmiennej truskawki.
&truskawki i w_truskawki są równoważne i pokazują adres zmiennej truskawki.


Użycie operatora new do alokowania pamięci

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Program - wskaźniki - operator new
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int *wsk = new int;
    *wsk = 23;
    int w = 33;

    cout << "Wartość " << *wsk << endl;
    cout << "Adres " << wsk << endl;

    cout << "Wartość " << w << endl;
    cout << "Adres " << &w << endl;

    return 0;
}
Wartość 23
Adres 0x7f986cc00690
Wartość 33
Adres 0x7ffee91d1a6c

W programie został zadeklarowany wskaźnik na typ int alokowany operatorem new.
Zmienne przechowywane są w pamięci zwanej stosem (stack), natomiast obiekty danych alokowane za pomocą operatora new przechowywane są w pamięci zwanej stertą (heap) albo w puli wolnej pamięci (free store). Dlatego adresy widoczne na listingu powyżej nie znajdują się koło siebie.


Zwalnianie pamięci za pomocą operatora delete. Operator delete umożliwia zwolnienie pamięci zaalokowanej operatorem new. Jest to ważna zasada w dobrym wykorzystaniu pamięci.
Przykład:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* Program - wskaźniki - operator new
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int *wsk = new int;
    *wsk = 23;

    cout << "Wartość " << *wsk << endl;
    cout << "Adres " << wsk << endl;

    delete wsk;

    cout << "Wartość " << *wsk << endl;
    cout << "Adres " << wsk << endl;

    return 0;
}

Wartość 23
Adres 0x7f8e05c00690
Wartość 23
Adres 0x7f8e05c00690

Pomimo, że operator delete zwolnił pamięć przydzieloną operatorem new, to wskazywana wartość oraz adres nie uległy zmianie. Oznacza to, że wskaźnik dalej wskazuje na to samo miejsce w pamięci, ale pamięć ta nie należy już do programu.


Użycie operatora new do dynamicznego tworzenia tablic


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* Program - wskaźniki - dynamiczne tworzenie tablicy
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

int main()
{
    int rozmiar;
    cout << "Podaj rozmiar tablicy: ";
    cin >> rozmiar;
    int *tab = new int[rozmiar];

    for (int i = 0; i < rozmiar; i++)
    {
        tab[i] = i + 1;
        cout << tab[i] << endl;
    }

    delete [] tab;

    return 0;
}

Podaj rozmiar tablicy: 10
1
2
3
4
5
6
7
8
9
10

Użycie operatora new do tworzenia struktur dynamicznych


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* Program - wskaźniki - dynamiczne tworzenie struktury
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

struct koszykarz
{
    string imie;
    string nazwisko;
    string klub;
    int wzrost;
    int waga;
};

int main()
{
    koszykarz *MJ = new koszykarz;
    cout << "Kto jest najlepszym koszykarzem wszechczasów?\n";
    cout << "Podaj imię: ";
    getline(cin,MJ->imie);

    cout << "Podaj nazwisko: ";
    getline(cin,MJ->nazwisko);

    cout << "Klub sportowy: ";
    getline(cin,MJ->klub);

    cout << "Podaj wzrost: ";
    cin >> MJ->wzrost;

    cout << "Podaj wagę: ";
    cin >> MJ->waga;

    cout << endl << MJ->imie << " " << MJ->nazwisko << " wzrost: " << MJ->wzrost << ", waga: " << MJ->waga << " reprezentujący klub " << MJ->klub << endl;

    delete MJ;

    return 0;
}

Kto jest najlepszym koszykarzem wszechczasów?
Podaj imię: Michael
Podaj nazwisko: Jordan
Klub sportowy: Chicago Bulls
Podaj wzrost: 198
Podaj wagę: 98

Michael Jordan wzrost: 198, waga: 98 reprezentujący klub Chicago Bulls

Zasięg zmiennych / przestrzenie nazw


Zasięg zmiennych


Pisząc programy staramy się nadawać unikatowe nazwy wszystkim zmiennym. Każda zmienna widoczna jest w ramach pewnego zasięgu. Zasięg ten wyznaczony jest poprzez blok kodu zawarty w nawiasach klamrowych {,}. Istnieją zmienne o zasięgu globalnym tzn. widoczne w całym programie oraz przez cały okres działania programu. Deklaruje się je po dołączeniu plików nagłówkowych, a przed funkcją główną main(). Natomiast zmienne lokalne widoczne są tylko w tym bloku kodu, w którym zostały zadeklarowane.

Przykład:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* Program - zasięg zmiennych
 * Wykonał Paweł Malinowski */

#include <iostream>

using namespace std;

// Deklaracja zmiennej globalnej i jej inicjalizacja
int x = 90;

int main()
{
    // Wypisanie zmiennej globalnej
    cout << "Wartość zmiennej x wynosi: " << x << endl;

    for (int i = 0; i < 2; i++)
    {
        int j = 156;
        // Wypisanie zmiennej globalnej
        cout << "Wartość zmiennej x wynosi: " << x << endl;

        // Wypisanie zmiennej lokalnej
        cout << "Wartość zmiennej j wynosi: " << j << endl;
    }

    // Wypisanie zmiennej globalnej
    cout << "Wartość zmiennej x wynosi: " << x << endl;

    // Wypisanie zmiennej lokalnej
    cout << "Wartość zmiennej j wynosi: " << j << endl; //error: use of undeclared identifier 'j'

    return 0;
}

Można zauważyć, że zmienne globalne widoczne są w każdym bloku kodu. Natomiast wyświetlenie zmiennej lokalnej poza blokiem kodu, w którym została zadeklarowana nie może zostać zrealizowane. Kompilator zgłasza błąd: error: use of undeclared identifier 'j'

Przestrzenie nazw


Do tej pory w większości programów stosowaliśmy zapis using namespace std;. Zapis ten oznacza, że korzystamy ze wszystkich metod przestrzeni nazw std, na przykład: cout, cin, endl, itd. Dobrą praktyką przy pisaniu programów jest wskazanie dokładnie których metod, obiektów będziemy używać w naszym programie, np. using std::cout i/lub using std::cin.

Tworzenie włanej przestrzeni nazw


namespace moja_nazwa
{
    int liczba;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Program - zasięg zmiennych
 * Wykonał Paweł Malinowski */

#include <iostream>

namespace pole
{
    double prostokat(int a, int b)
    {
        return(a * b);
    }
}

int main()
{
    using std::cout;
    using std::cin;

    int x, y;
    cout << "Podaj pierwszy bok prostokąta:";
    cin >> x;
    cout << "Podaj drugi bok prostokąta:";
    cin >> y;

    cout << "Pole prostokata wynosi: " << pole::prostokat(x,y);

    return 0;
}
  1. Napisz program, który obliczy pole i obwód kwadratu dla x = 15 i wypisz je na ekranie.
  2. Napisz program, który obliczy pole i obwód koła dla r = 4 i wypisz je na ekranie.
  3. Napisz program, który obliczy pole i obwód trójkąta dla a = 3, b = 4, c = 5 i wypisz je na ekranie.
  4. Napisz program, który obliczy pole powierzchni i objętość kuli o promieniu 3.
  5. Napisz program, który obliczy pole powierzchni i objętość prostopadłościanu (podstawa 3, 5) wysokość 8.
  6. Napisz program, który obliczy resztę z dzielenia (2x2 - 2x) / (2x - 1) dla x = 4.
  7. Napisz program, który pyta o podanie odległości w milach morskich i zamienia ją na metry (1 mila morska to 1852 metry).
  8. Napisz program, który pyta użytkownika o wzrost w metrach i wagę w kilogramach i wypisuje wskaźnik BMI. (BMI = masa/wzrost2).
  9. Napisz program, który zapyta Cię o wiek. Jeśli jesteś pełnoletni na ekranie pojawi się napis - Witaj, jesteś pełnoletni. Jeśli nie masz 18 lat, program wypisze na ekranie - Niestety jeszcze nie jesteś pełnoletni.
  10. Napisz program do logowania. Jeśli jako login podasz - admin, a jako hasło - Admin, to zostaniesz zalogowany i wyświetli się napis - Witamy w systemie. Jeśli wprowadzisz błędne dane logowania - program wyświetli napis - Niestety wprowadziłeś błędny login lub hasło.
  11. Napisz program, który zapyta Cię ile masz dzieci. Na każde dziecko przypada 500zł. W zależności od ilości dzieci, program pokaże ile powinieneś otrzymać z programu 500+. Zastosuj instrukcję switch. Założenie: maksymalna ilość dzieci - 5.
  12. Napisz program, który zapyta użytkownika o odległość w latach świetlnych i zwróci odległość w jednostkach astronomicznych. Rok świetlny to 63240 jednostek astronomicznych.
  13. Napisz program, który wypisze liczby od 10 do 20 za pomocą pętli for, while i do-while.
  14. Napisz program, który wypisze liczby od 20 do 0 co dwie (20,18,16 ...) za pomocą pętli for, while, do-while.
  15. Napisz program, który wypisze liczby od 1 do 100. W środku pętli umieść warunek, że jeśli iterator będzie równy 23, opuść pętlę za pomocą instrukcji break.
  16. Napisz program, który wypisuje liczby od 1 do 20. Jeśli napotka liczbę 13 to opuść wykonanie pętli za pomocą instrukcji continue.
  17. Napisz program, który zapyta użytkownika o długość geograficzną w stopniach, minutach i sekundach, a następnie wyświetli tą długość w formacie dziesiętnym.
  18. Napisz program, który zapyta cię o następujące informacje: imię, nazwisko, płeć, wykształcenie, zawód. Zapisz te informacje w pliku dane.txt.
  19. Napisz program, który odczyta z pliku dane.txt informacje o twoim imieniu, nazwisku, płci, wykształceniu oraz zawodzie i wyświetli je na ekranie.
  20. Napisz program, który zapisuje dowolny ciąg znaków podany z klawiatury do pliku w trybie binarnym.
  21. Napisz program, który odczytuje te dane z pliku binarnego.
  22. Napisz program, który obliczy średnią geometryczną trzech wczytanych liczb za pomocą funkcji.
  23. Napisz program, który wyświetli na ekranie pierwszych 10 elementów ciągu Fibonacciego.
  24. Napisz program, który obliczy wartość funkcji f(x) = 2x2 - 8x. Parametr przekaż do funkcji poprzez referencję.
  25. Napisz program, który obliczy średnią ważoną dla następujących liczb: 2, 4, 8, 1, 12 o następujących wagach 1, 3, 3, 2, 1.
  26. Napisz program, który obliczy średnią harmoniczną dla następujących liczb 23, 19, 48, 15.
  27. Napisz program, który poprosi użytkownika o podanie liczby sekund, a wynik pokaże w dniach, godzinach, minutach i sekundach.
  28. Napisz program, który poprosi użytkownika o podanie populacji światowej oraz populacji Polski. Program powinien wyświetlić procent jaki populacja Polski stanowi w populacji świata.