Utworzenie projektu w kompilatorze Dev C++
Aby napisać program, musimy stworzyć nowy projekt.
Plik -> Nowy -> Projekt. -> Wybór szablonu np.: "Empty Project" -> Podajemy nazwę projektu i klikamy OK. Następnie wybieramy folder, w którym będą zapisane pliki naszego projektu.
Dodajmy do projektu nowy plik źródłowy.
Menu -> Plik -> Nowy -> Plik źródłowy.
Menu -> Plik -> Zapisz jako... -> Zapiszmy go pod nazwą main.cpp, najlepiej w tym samym folderze, w którym zapisaliśmy plik naszego projektu.
Projekt składa się wówczas z dwóch plików:
1) *.dev - Główny plik naszego projektu, każdy projekt powinien być uruchamiany poprzez uruchomienie tego pliku. Są w nim zapisywane informacje o całym projekcie.
2) *.cpp - Plik w którym jest przechowywany kod naszego programu w projekcie.
Po pierwszej kompilacji programu dojdą nowe pliki do projektu:
1) main.o - wywodzi się z pliku z kodem źródłowym, natomiast Makefile.win jest plikiem zawierającym informacje o kompilacji, jest wykorzystywany do przyspieszania kolejnych kompilacji.
2) Projekt.exe - to właśnie rezultat naszej pracy, aplikacja windowsowa z rozszerzeniem *.exe
Pierwszy program napisany w języku c++
Konstrukcja pierwszego programu wypisującego na ekranie słowa Hello World! Oraz oczekującego na wciśnięcie klawisza Enter:
#include <iostream>
main ()
{ //To jest komentarz - pierwszy program w C++
std::cout << "Hello World!\n";
std::cin.get();
return 0;
};
Podstawowe typy zmiennych w języku c++
int - Jest to zmienna przechowująca w pamięci liczby całkowite. W systemach 32 bitowych int zajmuje 4B (bajty), czyli 32 bity. Zajmuje 4 kolejne komórki w pamięci (dane zapisane w 4 komórkach obok siebie). Int zawiera 2 do potęgi 32, czyli 4294967296 możliwych kombinacji liczb. Zakres int wynosi: od -2147483648 do 2147483647.
float - zmienna przechowująca liczby ułamkowe(tzw. zmiennoprzecinkowe). Float zajmuje 4 bajty (4 komórki pamięci)
double - zmienna również przechowuje liczby ułamkowe, jednak zajmuje 8 bajtów, , czyli ilość możliwych kombinacji równa jest 2 do potęgi 64.
char - zmienna przechowuje liczby całkowite a zajmuje 1 bajt (jedną komórkę pamięci). W 1 bajcie można zmieścić tylko 256 kombinacji (2 do potęgi 8), czyli jej zakres to -128 do 127.Umownie zmienna ta przechowuje także litery
bool - zmienna ta przechowuje wartość logiczną, czyli prawda (true) lub fałsz (false). Zajmuje 1 bajt (jedną komórkę). Jej zakres składa się z dwóch wartości true (1) albo false(0). True to po prostu każda wartość niezerowa a false to wartość 0.
void – zmienna nie mająca określonego typu. Stosowany tylko i wyłącznie w przypadku funkcji.
Przedrostki (zwane modyfikatorami):
unsigned - piszemy go przed typami: char i int. Przedrostek ten powoduje, że w zakresie zmiennej nie ma liczb ujemnych, korzystamy tylko z liczb dodatnich. To oddaje 1 bit, który mówi o znaku, więc zakres zmiennej dwukrotnie podwaja się. I tak na przykład unsigned int ma zakres od 0 do 4294967296 a unsigned char ma zakres od 0 do 255.
long - piszemy go przed typami: int i double. Przedrostek ten powiększa zmienną o 2 bajty (dwie kolejne komórki), przy czym oczywiście zwiększa się zakres zmiennej. Zmienna long int zajmuje 4+2=6 bajtów, a long double 8+2=10 bajtów.
short - jest przeciwieństwem long. Zmniejsza rozmiar zmiennej dla int i double o 2 bajty. Short int będzie zajmował 4-2=2 bajty a short double 8-2=6 bajtów.
const - możemy go napisać przed wszystkimi typami zmiennych. Powoduje, że zmienna ma stałą wartość, tzn. nie można zmienić jej wartości podczas działania programu. Wartość nadajemy podczas tworzenia zmiennej. Taka zmienna zostaje utworzona w bloku pamięci programu tylko do odczytu.
register - możemy go także użyć dla dowolnej zmiennej. Powoduje, że zmienna zostaje utworzona i przechowywana w rejestrze procesora a nie w pamięci. Przyspiesza to czas korzystania ze zmiennej, bo nie trzeba jej kopiować z pamięci do procesora. Powinniśmy korzystać z tego przedrostka tylko, jeżeli bardzo często używamy zmiennej, np. w intensywnej pętli.
extern - oznacza, że zmienna jest utworzona, w innej jednostce programu, w innym pliku *.cpp naszego projektu.
Deklaracja zmiennych
W celu deklaracji zmiennej należy najpierw napisać typ zmiennej, potem napisać nazwę i zakończyć średnikiem. Każda zmienna musi mieć swoją nazwę. W nazwie nie może być polskich znaków ani spacji oraz nazwa zmiennej nie może rozpoczynać się od cyfry. Kompilator C++ rozróżnia także duże i małe litery. Oczywiste jest chyba, że nie można powtarzać nazw zmiennych.
Przypisywanie wartości do zmiennych:
Aby zmiennej przypisać (nadać) jakąś wartość trzeba po nazwie zmiennej napisać znak równa się "=" i po nim konkretną wartość, przy czym należy pamiętać, że wartość nie może wykraczać poza zakres zmiennej. Proces ten nazywa się inicjalizacją zmiennej. Gdy mamy do czynienia ze zmienną z przedrostkiem const w trakcie działania programu nie można zmienić jej wartości. Należy ją nadać podczas tworzenia zmiennej. Każdą zmienną przed użyciem powinno się zainicjować, bo po utworzeniu nie wiadomo jaką wartość będzie miała.
Przykład:
#include <iostream>
int main(int argc,char* argv[])
{
int Integer_Number;
float Fractional_Number;
double Fraction;
char Sign;
bool LogicValues;
const int Constant = 123456;
register bool RegisterVar;
unsigned long int LongInteger;
register unsigned short int LoopIndex;
Integer_Number = 10;
Fractional_Number = 0.005;
Sign = ‘A’;
return 0;
}
Deklaracja własnych typów zmiennych
Każdemu typowi zmiennej można przypisać własną nazwę. Robi się to przy pomocy instrukcji typedef.
Przykład:
#include <iostream>
int main(int argc,char* argv[])
{
typedef long int number;
number MyInteger;
return 0;
}
Operatory
Operatory arytmetyczne - Służą do wykonywania podstawowych działań matematycznych, takich jak dodawanie, odejmowanie, mnożenie i dzielenie.
- dodawanie: +
- odejmowanie: -
-mnożenie: *
-dzielenie: / - daje wynik ułamkowy dla dzielenia dwóch liczb typu float oraz double oraz całkowity dla liczb typu int.
-dzielenie modulo: % - służy do dzielenia liczb całkowitych, daje resztę z dzielenia.
Przykład:
#include <iostream>
#include <Windows.h>
int main(int argc,char* argv[])
{
int N1;
int N2;
std::cout << "Podaj liczbe 1:\n";
std::cin >> N1;
std::cout << "Podaj liczbe 2:\n";
std::cin >> N2;
std::cout << "Dodawanie N1 + N2 = " << N1 + N2 << std::endl;
std::cout << "Odejmowanie N1 - N2 = " << N1 - N2 << std::endl;
std::cout << "Mnożenie N1 * N2 = " << N1 * N2 << std::endl;
std::cout << "Dzielenie N1 / N2 = " << N1 / N2 << std::endl;
std::cout << "Dzielenie modulo N1 % N2 = " << N1 % N2
<<std::endl;
std::cout << "Dzielenie N1 / N2 = " << (float)N1 / N2
<< std::endl;
system("pause");
return 0;
}
Inne operatory arytmetyczne:
operator ++ powiększa wartość zmiennej całkowitej o 1, inkrementacja
operator -- zmniejsza wartość zmiennej całkowitej o 1; dekrementacja
operator += zwiększa wartość zmiennej całkowitej o podaną ilość.
operator -= zmniejsza wartość zmiennej całkowitej o podaną ilość.
Przykłady:
i++ i = i+1
a+=2 a = a +2
Operator przypisania
- znak ‘=’, służy do przypisywania wartości do zmiennej. Nie może być mylony z operatorem porównania (‘==’)
Operatory porównania
Operatory te służą do porównywania wartości zmiennych. Zwykle używa się ich w parze z instrukcjami warunkowymi.
Operator ==
Nazwa matematyczna: równa się.
Służy do sprawdzania czy wartości dwóch zmiennych są równe. Jeżeli tak to zwraca 1(true), jeżeli nie to zwraca 0(false).
Operator !=
Nazwa matematyczna: nie równa się
Służy do sprawdzania czy wartości dwóch zmiennych nie równają się. Jeżeli wartości nie są równe to zwraca 1(true), jeżeli są równe to zwraca 0 (false).
Operator >
Nazwa matematyczna: większy
Służy do sprawdzania czy wartość zmiennej po lewej stronie jest większa niż wartość zmiennej po prawej stronie operatora. Jeżeli wartość po lewej stronie jest większa zwraca 1(true), jeżeli większa jest po prawej stronie zwraca 0 (false)
Operator <
Nazwa matematyczna: mniejszy
Służy do sprawdzania czy wartość zmiennej po lewej stronie jest mniejsza niż wartość zmiennej po prawej stronie operatora. Jeżeli wartość po lewej stronie jest mniejsza zwraca 1(true), jeżeli mniejsza jest po prawej stronie zwraca 0 (false)
Operator >=
Nazwa matematyczna: większy lub równy
Służy do sprawdzania czy wartość zmiennej po lewej stronie jest większa lub równa niż wartość zmiennej po prawej stronie operatora. Jeżeli wartość po lewej stronie jest większa lub równa zwraca 1(true), jeżeli większa jest po prawej stronie zwraca 0 (false)
Operator <=
Nazwa matematyczna: mniejszy lub równy
Służy do sprawdzania czy wartość zmiennej po lewej stronie jest mniejsza lub równa niż wartość zmiennej po prawej stronie operatora. Jeżeli wartość po lewej stronie jest mniejsza lub równa zwraca 1(true), jeżeli mniejsza jest po prawej stronie zwraca 0(false)
Operatory logiczne
Służą do formułowania wyrażeń logicznych. Zwykle używa się ich w instrukcjach warunkowych.
Operator &&
Nazwa potoczna: operator iloczynu logicznego (AND)
Służy do sprawdzania czy wszystkie wyrażenia logiczne połączone przez niego mają wartość logiczną 1 (true). Jeżeli wszystkie wynoszą 1 to operator zwraca 1, jeżeli chociaż jeden nie spełnia warunków(wynosi 0) to zwraca 0 (false).
Operator ||
Nazwa potoczna: operator sumy logicznej (OR)
Służy do sprawdzania czy chociaż jedno wyrażenie logiczne połączone przez niego wynosi 1 (true). Jeżeli chociaż jedno wynosi 1 to operator zwraca 1, jeżeli wszystkie wynoszą 0 to zwraca 0 (false).
Operator !
Nazwa potoczna: operator zaprzeczenia (NOT)
Służy do zmiany wartości logiczne na odwrotną. Jeżeli wyrażenie wynosi 1 (true) to zmienia je w 0 (false), jeżeli wynosi 0 (false) to zmienia je w 1 (true).
Inne operatory
operator & - operator referencji (adresu). Służy do uzyskiwania adresu pamięci danej zmiennej.
operator * - operator dereferencji (wyłuskania). Jest przeciwieństwem operatora &. Służy do zwracania wartości zmiennej na którą wskazuje wskaźnik
operator sizeof() - zwraca nam rozmiar podanej zmiennej lub innego obiektu w bajtach.
Instrukcje warunkowe
Instrukcja if … else…
Ogólna postać instrukcji:
if (warunek) instrukcja;
Instrukcja if sprawdza czy warunek w nawiasie jest spełniony (jego wartość logiczna jest równa 1) . Jeżeli tak to program wykona określone polecenie, które jest po nawiasie. Instrukcję warunkową if można rozszerzyć dodając dodatkowy fragment programu po słowie kluczowym else. Jeżeli warunek nie jest spełniony to wykona się instrukcja, która jest po else.
If (warunek)
instrukcja_jeżeli_prawda;
else
instrukcja_jeżeli_nie_prawda;
Jeżeli chcemy wykonać kilka instrukcji w jednym warunku if, to należy wziąć je w klamry {}:
Przykład:
#include <iostream>
#include <windows.h>
int main(int argc,char* argv[])
{
int liczba1,liczba2;
std::cout << "Podaj dwie liczby\n";
std::cin >> liczba1>>liczba2;
if(liczba1==liczba2)
{
std::cout << "Liczby sa rowne\n";
}
else
{
std::cout << "Liczby nie sa rowne\n";
}
system("PAUSE");
return 0;
}
Instrukcja switch… case…
Instrukcję stosuje się gdy istnieje skończona możliwość wartości jaką może przyjmować zmienna sterująca instrukcją. Przykładem może być wykonanie menu wyboru w programie – w zależności od wartości liczby całkowitej jaką wpisze użytkownik w programie wykonywane są różne operacje.
Fragment kodu wykorzystując instrukcję switch… case…
switch(liczba) {
case 1:
//jeżeli liczba wynosi 1 - Operacje1
break;
case 2:
//jeżeli liczba wynosi 2 – Operacja 2
break;
case 3:
//jeżeli liczna wynosi 3 – Operacja 3
break;
case 4:
//jeżeli liczba wynosi 4 – Operacja 4
break;
default:
//liczba nie ma żadnej poprzednich z wartości - Operacja default
}
system("PAUSE");
return 0;
}
Polecenie break po każdym elemencie instrukcji case jest konieczne, aby po znalezieniu przez instrukcję właściwej wartości zmiennej sterującej, program przestał sprawdzać wszystkie pozostałe przypadki. Gdy kluczowe słowo się nie pojawi, instrukcja sprawdza wszystkie przypadki po kolei aż do końca instrukcji. Operacja pojawiająca się po słowie default zostaje wykonana jeżeli żaden z warunków case nie został spełniony. W przypadku gdy po słowie case: ma zostać wykonane kilka różnych instrukcji należy użyć nawiasów klamrowych {}.
Pętle programowe
- Pętla while
Ogólna postać pętli:
while (warunek) instrukcja;
Gdy kilka instrukcji ma zostać wykonane to należy je wziąć w klamrę:
while (warunek)
{
instrukcja 1;
instrukcja 2;
...
instrukcja X;
}
Pętla ta sprawdza czy warunek jest spełniony, jeżeli tak, to wykonuje polecenia w pętli, następnie, znowu sprawdza ten warunek i tak cały czas, dopóki warunek nie będzie spełniony lub sami nie przerwiemy wykonywania pętli.
Przykładowy program:
#include <iostream>
int main(int argc,char* argv[])
{
int poczatek;
int koniec;
std::cout << "Podaj liczbe od jakiej mamy zaczac:\n";
std::cin >> poczatek;
std::cout << "Podaj liczbe do jakiej bedzie trwac wypisywanie\n";
std::cin >> koniec;
std::cout << std::endl;
//Petla wypisuje liczby od wartości początek do wartości koniec
while(poczatek <= koniec)
{
std::cout << poczatek << std::endl;
poczatek++;
}
system("PAUSE");
return 0;
}
- Pętla do… while…
Ogólna postać pętli:
do instrukcja; while(warunek);
lub jeżeli mamy kilka instrukcji:
do
{
instrukcja 1;
instrukcja 2;
...
instrukcja X;
}
while (warunek);
W pętli najpierw są wykonywane instrukcje a dopiero potem sprawdzany jest warunek. W ten sposób mamy pewność, że pętla "do" wykona się przynajmniej raz, nawet gdy warunek nie będzie spełniony. Pętla będzie wykonywana aż do niespełnienia warunku lub zatrzymania jej.
- polecenia break and continue w pętlach
Instrukcja break umożliwia wyjście z pętli w dowolnym jej momencie (zatrzymanie pętli).
Instrukcja continue służy do przerywania danego obiegu pętli. Jeżeli pętla napotka na swojej drodze "continue", zakończy wykonywanie poleceń w tym obiegu pętli i rozpocznie nowy obieg.
Przykład:
#include <iostream>
int main(int argc,char* argv[])
{
int poczatek;
int koniec;
std::cout << "Podaj liczbe od jakiej mamy zaczac:\n";
std::cin >> poczatek;
std::cout << "Podaj liczbe do jakiej bedzie trwac wypisywanie\n";
std::cin >> koniec;
std::cout << std::endl;
while(poczatek <= koniec)
{
if(poczatek > 10) break;
std::cout << poczatek << std::endl;
poczatek++;
}
system("PAUSE");
return 0;
}
- pętla programowa for
Ogólna postać pętli:
for (typ zmienna; warunek; krok) instrukcja;
lub
for (typ zmienna; warunek; krok)
{
instrukcja 1;
instrukcja 2;
...
instrukcja X;
}
Pętla służy głownie do wykonywania pewnych instrukcji ściśle określoną ilość razy. Podczas uruchamiania pętli zostaje utworzona zmienna sterująca pętlą, jej indeks najczęściej oznaczany ‘int i’ i sprawdzony warunek kontynuacji (najczęściej sprawdzenie czy indeks pętli osiągnął określoną wartość). Jeżeli jest on spełniony pętla wykonuje instrukcje w swoim wnętrzu i zmienia wartości indeksu (najczęściej inkrementacja czyli zwiększenie o jeden). Następnie warunek jest sprawdzany ponownie. Pętli działa do momentu w którym warunek przestaje być prawdziwy albo nastąpi wcześniejsze jej opuszczenie instrukcją break.
Przykład:
#include <iostream>
int main(int argc,char* argv[])
{
std::cout << "Wypisanie liczb od 1 do 10:\n";
for (int i= 1;i <=10; i++) std::cout << i << std::endl;
system("PAUSE");
return 0;
}
Wskaźniki
Wskaźnik to specjalna zmienna, która przechowuje adres komórki pamięci. W systemach 32 bitowych adresy komórek pamięci to liczby 32 bitowe a w systemach 64 bitowych pamięć jest podpisana adresami o wartościach 64 bitowych.
Przykład ilustruje w jaki sposób utworzyć wskaźnik do danego typu zmiennej i jak przypisać do niego adres zmiennej a następnie wydobyć wartość zmiennej korzystając jedynie ze wskaźnika na nią wskazującego.
#include <iostream>
int main(int argc,char* argv[])
{
//Opis programu
//utworzenie zmiennej typu int
//utworzenie wskaźnika na zmienne typu całkowitego (int)
//wskaźnikowi przypisujemy adres zmiennej o nazwie zmienna
//Następnie wypisywane są wartości:
//adresu zmiennej przechowywanego we wskaźniku
//wartości zmiennej na którą wskazuje wskaźnik
int zmienna;
int* wskaznik;
wskaźnik = &zmienna;
std::cout << "Adres zmiennej na która wskazuje wskaźnik: " << wskaznik << std::endl;
std::cout << "Wartość zmiennej na którą wskazuje wskaźnik: "
<< *wskaznik << std::endl;
system("PAUSE");
return 0;
}
Referencja
Jest to zmienna, która "podszywa się" pod inną zmienną.
Przykład utworzenia referencji do zmiennej:
int liczba; //zwykła zmienna int
int& referencja = liczba; //zmienna referencyjna
Podczas deklaracji zmiennej referencyjnej trzeba ją od razu zainicjować. W przykładzie zmienna „referencja” jest tym samym, co zmienna "liczba". Zmienna referencyjna nie zajmuje żadnego miejsca w pamięci. To tak jakbyśmy zmiennej nadali dwie nazwy: liczba i referencja. Zmienne "liczba" i "referencja" są tak naprawdę tą samą zmienną, obie zajmuje dokładnie te same komórki pamięci (mają ten sam adres). Gdy zmieniamy wartość jednej z nich, automatycznie zmienia się wartość drugiej.
FUNKCJE
Funkcja to oddzielna część programu (blok programu) który można wywołać w dowolnym momencie wykonywania programu. Aby móc użyć funkcji należy ją zadeklarować przed głównym programem, czyli funkcją main().
- deklaracja funkcji: Deklaracja informuje o tym, że użyta w programie nazwa będzie odnosić się do funkcji. Należy w niej podać typ zwracany przez funkcję, jej nazwę oraz listę argumentów przyjmowanych przez funkcję (w nawiasach okrągłych). Jej ogólna postać jest następująca:
typ_funkcji nazwa_funkcji (argumenty funkcji);
-definicja funkcji: zawiera instrukcje, które mają zostać wykonane w przypadku gdy funkcja zostanie wywołana z programu głównego. Instrukcje nazywane są ciałem funkcji. Jej ogólna postać jest następująca:
typ_funkcji nazwa_funkcji (argumenty funkcji)
{ …instrukcje
return wartosc_zwracana
};
Definicja funkcji może pojawić się przed funkcją main() lub po jej zakończeniu. W pierwszym przypadku wcześniejsza jej deklaracja nie jest konieczna.
Przykład: funkcja dodająca do siebie dwie liczby:
#include <iostream>
//Deklaracja i definicja funkcji
int licz(int liczba1,int liczba2)
//funckja licz typu int z dwoma argumentami typu int
{
return liczba1+liczba2;
}
//program główny
int main(int argc,char* argv[])
{
int licz1,licz2,wynik;
std::cout << "DODAWANIE\nPodaj pierwsza liczbe:\n";
std::cin >> licz1;
std::cout << "Podaj druga liczbe:\n";
std::cin >> licz2;
//wywołanie funkcji w programie
wynik = licz(licz1,licz2);
std::cout << "Wynik: "<< wynik << std::endl;
system("PAUSE");
return 0;
}
Typ void jest używany w funkcjach, gdy funkcja nie zwraca wartości. Jest to tzw. typ pusty. W takiej funkcji nie musimy pisać return, aczkolwiek napotkanie return w każdej funkcji kończy jej wykonywanie.
Przekazywanie wartości do funkcji:
Wartości można przekazywać do funkcji różne sposoby: można przekazywać zmienne bezpośrednio przez wskaźniki lub referencje.
W pierwszym przypadku wewnątrz funkcji tworzone są kopie zmiennych i na nich funkcja wykonuje działania. Oryginalne zmienne pozostają nienaruszone. W przypadku przekazywania wartości zmiennej poprzez wskaźnik do funkcji przekazywany jest jedynie adres zmiennej. Funkcja wykonuje obliczenia na oryginalnych zmiennych zadeklarowanych w funkcji main() i może bezpośrednio zmieniać ich wartości.
Przykład przekazywania wartości funkcji przez wskaźnik:
#include <iostream>
//definicja funkcji
int licz(int* liczba1,int* liczba2)
{
return *liczba1 + *liczba2;
}
int main(int argc,char* argv[])
{
int licz1,licz2,wynik;
std::cout << "DODAWANIE\nPodaj pierwsza liczbe:\n";
std::cin >> licz1;
std::cout << "Podaj druga liczbe:\n";
std::cin >> licz2;
// wywołanie funkcji i przekazanie do niej wskaźników
wynik = licz(&licz1,&licz2);
std::cout << "Wynik: "<< wynik << std::endl;
system("PAUSE");
return 0;
}
W ostatnim przypadku do funkcji przekazuje się zmienne referencyjne, tzn. zmienne o innych nazwach od tych istniejących już w programie, ale fizycznie zajmujące te same komórki pamięci (patrz rozdział o zmiennych referencyjnych). Podobnie jak w pierwszym przypadku wewnątrz funkcji tworzona są kopie zmiennych do niej przekazywanych, ale są to zmienne referencyjne.
#include <iostream>
//definicja funkcji
int licz(int& liczba1,int& liczba2)
{
return liczba1+liczba2;
}
int main(int argc,char* argv[])
{
int licz1,licz2,wynik;
std::cout << "DODAWANIE \nPodaj pierwsza liczbe:\n";
std::cin >> licz1;
std::cout << "Podaj druga liczbe:\n";
std::cin >> licz2;
wynik = licz(licz1,licz2);
std::cout << "Wynik: "<< wynik << std::endl;
system("PAUSE");
return 0;
}
Zasięg zmiennych
Zmienne globalne – zmienne widoczne w całym programie. Tworzy się je poza funkcjami, w głównym ciele programu (poza wszystkimi funkcjami).
Zmienne lokalne – Zmienna istniejąca tylko w funkcji w której została utworzona. Czas życia tej zmiennej trwa do momentu zakończenia funkcji. Po wyjściu z funkcji pamięć jej przydzielona zostaje zwolniona.
Tablice
Tablice to obszar pamięci służący do przechowywania dużej ilości zmiennych danego typu (homogenicznych). Statyczną tablicę deklaruje się podając jej typ oraz rozmiar (maksymalna ilość elementów – pojedynczych zmiennych danego typu). Na przykład:
int tablica[4]; - deklaracja tablicy czteroelementowej do przechowywania liczb całkowitych
Do każdego z elementów tablicy odwołuje się po jej indeksie zaczynając numerację od ZERA tzn. element o indeksie zero jest pierwszym i tak dalej aż do elementu o indeksie n -1, gdzie n jest zadeklarowanym rozmiarem tablicy.
tablica[0] = 1;
tablica[1] = 2;
tablica[2] = 3;
tablica[3] = 4;
Istnieje możliwość przypisania wartości do każdego z elementów tablicy podczas jej deklaracji używając nawiasów klamrowych.
int tablica[4] = {1,2,3,4};
Przykład inicjalizacji tablicy przy pomocy pętli for (wyzerowanie jej wartości):
for (int i = 0; i < 10; i++) tablica[i] = 0;
Nazwa tablicy to wskaźnik na pierwszy element w tablicy. Gdy w zapisie używamy [], automatycznie oznacza to, że odwołujemy się do wartości tego elementu.
W powyższym przykładzie:
tablica - to wskaźnik na pierwszy element w tablicy,
tablica[0] - wartość pierwszego elementu (o indeksie 0) w tablicy.
Tablice wielowymiarowe:
Tablica może posiadać więcej wymiarów niż jeden, może być na przykład tablicą dwuwymiarową czyli macierzą. Wówczas każdy z elementów tablicy o wymiarze m sam jest tablicą o wymiarze n. Przykład deklaracji tablicy dwuwymiarowej:
int matrix[10][10] – macierz liczb całkowitych o rozmiarze 10 x 10. Posiada 100 elementów.
Operacje na znakach
Łańcuchem znaków nazywamy tablicę typu char. Oto przykładowy łańcuch znaków:
char ASCII[256];
Każdy znak (np. litera) ma swój numer w danym systemie znakowym. Dlatego char jest w rzeczywistości liczbą, ale taka liczba ma swój odpowiednik w znaku. Domyślnie w programie wyświetlają nam się litery, czyli odpowiedniki wartości char w danym systemie znakowym.
ASCII
Przykładowym system kodowania znaków jest system ASCII (American Standard Code for Information Interchange), ten system jest systemem znaków w systemie Windows. System ten składa się z 256 znaków(unsigned char). Wyróżnia się następujące typy znaków:
a) znaki drukowane- są to znaki które są dostępne na klawiaturze i wyświetlane na ekranie. Ich numeracja mieści się w przedziale od 32-127.
b) znaki rozszerzone- znaki, które są rozszerzeniem zwykłych znaków. Zawierają się w przedziale od 128-255
c) znaki sterujące- używa się ich np. w drukarkach, służą do sterowania tekstem, nie mają swoich odpowiedników graficznych.
Inicjacja tablicy znaków:
char napis[12] = "Hello World";
Podczas deklaracji napisów należy pamiętać, aby tablica mogła pomieścić tyle znaków ile zajmuje napis, dla przykładu w tekście "Hello World" jest 11 znaków(każdy znak trzeba liczyć, nawet spacje, entery), więc minimalna wielkość tablicy, która może pomieścić ten tekst to właśnie 12. Trzeba pamiętać, aby dodać 1 dodatkowy znak na zakończenie tekstu, czyli dla 11 znaków tablica musi być 12 elementowa. Gdy tworzymy łańcuch znaków i od razu go inicjujemy nie musimy określać długości tablicy, kompilator zrobi to za nas.
Wypisywanie łańcucha znaków na ekranie:
#include <iostream>
int main(int argc,char* argv[])
{
char napis[]="Hello World!";
std::cout<<napis<<std::endl;
system("PAUSE");
return 0;
}
Tablicę można zainicjować tylko raz, podczas jej tworzenia, nie możemy zainicjować istniejącej tablicy! Potem możemy jedynie zmieniać pojedyncze zmienne, czyli litery.
char napis[]="Hello World!";
napis[0]='J';
Znaki specjalne
Znak '\n' - Oznacza przejście do następnej linii, tzw. enter.
Znak \r - oznacza on "skok na początek linii". Jest on używany np. w drukarkach, gdzie aby przejść do następnej linijki należy użyć znaków '\n' i '\r'
Znak \t - Jest to znak tabulacji poziomej.
Znak \v -Jest to znak tabulacji pionowej.
Znak \f -W drukarkach ten znak oznacza wysunięcie strony. W niektórych programach konsolowych może oznaczać wyczyszczenie ekranu.
Znak \" - gdy chcemy w tekście wstawić znak ", musimy napisać \", bo sam znak " w kodzie źródłowym oznacza początek lub koniec łańcucha znaków.
Znak \' - Tak jak wyżej, tyle że ze znakiem '.
Znak \\ - Sam znak \ oznacza, że wstawiamy znak specjalny, jeżeli chcemy w tekście wstawić znak \ w tekście, musimy użyć znaku specjalnego \\.
Znak \0 - stawiamy go, gdy chcemy zakończyć łańcuch znaków. Każdy łańcuch znaków musi kończyć się znakiem \0! Gdy inicjujemy łańcuch podczas tworzenia gotowym tekstem, kompilator automatycznie wstawi znak \0
Zmiana tekstu w tablicy char przy pomocy funkcji memcpy
Prototyp funkcji wygląda następująco:
void* memcpy(void* destination,const void* source, size_t num);
Funkcja ta kopiuje blok pamięci z jednego miejsca w drugie. Pierwszy argument "destination", to wskaźnik gdzie ma zostać przekopiowany tekst (lub inne dane). Drugi argument "source" to także wskaźnik, ale na to co ma zostać skopiowane. Trzeci parametr to ilość kopiowanych danych w bajtach (komórkach pamięci, na przykład kopiowana długość tablicy).
Przykład zastosowania funkcji do kopiowania zawartości tablicy znaków:
#include <iostream>
int main(int argc,char* argv[])
{
char napis[256]; //tablica do której skopiujemy tekst
memcpy(napis,"Hello World!",13);
std::cout << napis << std::endl;
//tym razem podajemy wskaźnik na tablicę jako drugi parametr
char tablica[]="tekst w tablicy.";
memcpy(napis,tablica,17);
std::cout<<napis<<std::endl;
system("PAUSE");
return 0;
}
Struktury
Struktura to połączenie wielu zmiennych w którym połączone zmienne mogą być różnych typów np. pierwsza będzie typu int, druga będzie typu char, trzecia bool. Oczywiście zmienne te nadal będą obok siebie w pamięci w takiej kolejności, w jakiej będą ułożone w strukturze.
Przed wykorzystaniem struktury w programie należy ją zadeklarować to znaczy podać jej budowę wewnętrzną. Na przykład:
struct struct_example
{
int number1,number2;
bool logic;
char sign;
};
Deklaracja zmiennej typu strukturalnego jest analogiczna do deklaracji zmiennych innego typu:
typ nazwa_zmiennej;
struct_example struktura;
Po utworzeniu struktury należy zainicjować wartości każdego z jej pól. Aby dostać się do danego pola struktury należy użyć operatora ‘.’
struktura.number1 = 123;
struktura.number2 = -1234;
struktura.logic = true;
struktura.sign = 'r';
Do elementów struktury można odwoływać się przez wskaźnik do niej, na przykład:
struct_example struktura;
struct_example* struct_pointer = &struktura;
struktura.number1 = 34;
//odwołujemy się do elementu poprzez strukturę w pamięci
struct_pointer -> number1 = 23;
//odwołujemy się do elementu struktury poprzez wskaźnik
Dyrektywy preprocesora
Preprocesor jest to oddzielna część programu kompilującego, która działa przed prawdziwą kompilacją. Jego zadaniem jest zmiana kodu zanim kompilator zacznie go tłumaczyć na kod maszynowy. Do sterowania preprocesorem używa się tzw. dyrektyw preprocesora. Każda dyrektywa zaczyna się znakiem # a kończy wraz z końcem linii
Dyrektywa #include - Jej zadaniem jest dołączenie jakiegoś pliku do naszego programu, czyli rozszerzenie go o zewnętrzne elementy (funkcje, struktury, klasy, definicje zmiennych, itd.), które są napisane w innym pliku. Gdy chcemy dobrać się do pliku nagłówkowego, który znajduje się w folderze w którym jest nasza aplikacja zamiast <> należy napisać " ":
#include "main.h"
Dyrektywa #define -służy do nadawania wartościom nazw. Przykładowo:
#define PI 3.14
#define PREDKOSC_DZWIEKU 332
Przydatne funkcje
Konwersja łańcucha znaków na liczbę (plik csdlib)
int atoi(const char* tekst);
//służy do konwersji łańcucha znaków do zmiennej typu int
int atol(const char* tekst);
//konwersja łańcucha znaków do zmiennej typu long int
int atof(const char* tekst);
//konwersja łańcucha znaków do zmiennej typu float
Konwersja liczby na łańcuch znaków (plik csdlib):
char* itoa(int konwertowana_liczba, char* wskaznik_do_tablicy, int system_liczb);
// system_liczb oznacza system liczb w jakim ma być wyświetlony wynik
char* gcvt(double liczba, int iloscCyfr, char* wskaznik_do_tablicy);
// iloscCyfr – do jakiej ma być zaokrąglony wynik
Generator liczb losowych (plik csdlib)
Przed używaniem funkcji generującej liczby losowe należy zainicjować generator liczb losowych dowolną wartością. Przy każdym uruchomieniu programu generator powinien być zainicjowany inną liczbą, zapobiegnie to powtarzaniu się losowanych liczb.
void srand(unsigned int liczba_inicjująca); //inicjalizuje generator
Funkcja losująca liczbę z określonego przedziału liczb, początkiem przedziału jest zawsze liczba 0. Na przykład:
rand()%10; // zakres obejmuje 10 liczb, pierwsza z nich to 0 a ostatnia 9.
Przykład – rzut kostką do gry:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
cout << "Podaj jakas liczbe do inicjacji jadra liczb losowych:\n";
int i;
cin >> i;
srand(i);
cout << "Rzucamy kostka...\n";
system("PAUSE");
cout << "Wylosowana liczba na kostce: " <<(rand()%6)+1 << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Funkcje matematyczne (plik cmath, csdlib):
int abs (int liczba);
Funkcja "abs" służy do obliczania wartości bezwzględnej. Jako argument podajemy liczbę całkowitą do obliczenia, zwracaną wartością jest wynik wartości bezwzględnej.
double ceil (double liczba);
Funkcja "ceil" służy do zaokrąglania w górę liczb ułamkowych.
double cos (double kat);
Funkcja "cos" zwraca cosinus kąta zmiennej kat(w radianach).
double fabs (double liczba);
Funkcja "fabs" służy do obliczania wartości bezwzględnej z liczb ułamkowych.
double floor (double liczba);
Funkcja "floor" służy do zaokrąglania w dół liczb ułamkowych.
double pow (double liczba,double potega);
Funkcja "pow" służy do podnoszenia liczb do potęgi, jako pierwszy argument podajemy wartość podnoszonej liczby, natomiast jako drugi argument potęgę, do której będziemy podnosić.
double sin (double kat);
Funkcja "sin" zwraca sinus kąta zmiennej kat(w radianach).
double sqrt (double liczba);
Funkcja "sqrt" zwraca pierwiastek drugiego stopnia zmiennej liczba.
double tan (double kat);
Funkcja "tan" zwraca tangens kąta zmiennej kat(w radianach).
Funkcja systemowe (plik csdlib):
system ("PAUSE");
To polecenie zatrzymuje pracę programu, wyświetla napis "Aby kontynuować, naciśnij dowolny klawisz . . ."" (pod innymi systemami może wyświetlać się inny tekst) i czeka na naciśnięcie jakiegoś przycisku(sygnału z klawiatury).
system("CLS");
Polecenie "CLS" czyści ekran konsoli(czarnego tła w programie).
system("TIME");
Polecenie pobiera bieżący czas w systemie