Oldal kiválasztása

C++ nyelv

C++ programozás kezdőknekMogi.bme C++Programing hubw3Schools
cplus2programingw3schools
SololearnProgramozás
Programozás

BEVEZETÉS – ALAPFOGALMAK

A szabványos C++ nyelv azon hagyományos programozási nyelvek közé tartozik, ahol a program megírása a program teljes szövegének begépelését is magában foglalja. A program szövegének (forráskódjának) beírása során figyelnünk kell néhány megkötésre:

  • A program alapelemei csak a hagyományos 7-bites ASCII kódtábla karaktereit (lásd A.1. szakasz függelék) tartalmazhatják, azonban a karakter- és szöveg konstansok, illetve a megjegyzések tetszőleges kódolású (ANSI, UTF-8, Unicode) karakterekből állhatnak. Néhány példa:/* Értéket adunk egy egész, egy karakteres és egy szöveges (sztring) változónak (többsoros megjegyzés) */ int valtozo = 12.23; // értékadás (megjegyzés a sor végéig) char jel = ‘Á’; string fejlec = „Öröm a programozás”
  • A C++ fordító megkülönbözteti a kis- és a nagybetűket a programban használt szavakban (nevekben). A nyelvet felépítő nevek nagy többsége csak kisbetűket tartalmaz.
  • Bizonyos (angol) szavakat nem használhatunk saját névként, mivel ezek a fordító által lefoglalt kulcsszavak (lásd A.2. szakasz függelék).
  • Saját nevek képzése során ügyelnünk kell arra, hogy a név betűvel (vagy aláhúzás jellel) kezdődjön, és a további pozíciókban is csak betűt, számjegyet vagy aláhúzás jelet tartalmazzon. (Megjegyezzük, hogy az aláhúzás jel használata nem ajánlott.)
  • Még egy utolsó szabály az első C++ program megírása előtt, hogy lehetőleg ne túl hosszú, azonban ún. beszédes neveket képezzünk, mint például: ElemOsszegmereshatardarabGyokKereso.

A C++ programozás lehetséges módjai

  • fejlesztői környezet használata
  • a kód megírása szövegszerkesztővel, majd fordítás parancssorban
  • böngészőben futó online fordító használata (egyszerűbb kódok kipróbálásához)

Tipp: ki lehet próbálni több fejlesztői környezetet is akár, de nem kell mindegyiket kipróbálni, illetve ki lehet próbálni a parancssoros fordítást, de annak is több módja van, nem kell megtanulni minden operációs rendszeren minden lehetőséget a parancssoros fordításra. Ezekkel nagyon el tud menni az idő, anélkül, hogy az ember elkezdene ténylegesen programozni. Idővel úgyis kialakul, hogy ki milyen eszközökkel szeret programozni.

továbbiak erről a témáról>

Az első program

A legelső program, ami általában a programozás tanfolyamokon szóba kerül mindössze annyit csinál, hogy kiír a képernyőre (pontosabban a parancssorba) egy szöveget. Ebben a fejezetben néhány kiíratással kapcsolatos alapvető tudnivalóról lesz szó.

Nézzük tehát annak a programnak a C++ forráskódját, ami kiírja a parancssorba, hogy Hello World!

//1. peldaprogram forraskodja

#include <iostream>
using namespace std;

int main() {
	cout << "Hello World!" << endl;
	return 0;
}

Könnyű megtalálni a kiíratásért felelős utasítást, mivel abban szerepel a Hello World! szöveg:

cout << "Hello World!" << endl;

Habár ez egy nagyon egyszerű program, nem elég ezt az egyetlen utasítást tartalmaznia, mert a kiíratáshoz (és adatbekéréshez, melyről a következő fejezetben lesz szó) használható dolgok (például cout, cin, printf, scanf, getline, endl, satöbbi) deklarációit/definícióit a programunk alapból nem tartalmazza (hiszen nincs minden programban szükség parancssorba való kiíratásra, vagy onnan történő adatbekérésre).
Az #include <iostream> utasítás helyére az úgynevezett preprocesszor (előfordító) beilleszti az iostream nevű header fájl tartalmát, még a fordítás megkísérlése előtt, melyben többek között a parancssorba történő kiíratás, és az onnan történő beolvasáshoz használt dolgok (objektumok és függvények mint például cout, cin, printf) deklarációi találhatóak.
Ha ez az utasítás nem szerepelne a forráskódban, akkor a program nem fordulna le, egy arra vonatkozó hibaüzenettel, hogy a fordító nem ismeri a cout-ot.

Minden C++ nyelven írt program kódjában szerepelnie kell main függvénynek, mivel a main függvény a program belépési pontja. A C++ programok érdemi tartalma a main függvény blokkjában lévő első utasítással kezdődik.
Az első néhány fejezet példaprogramjainak az összes érdemi utasítása a main függvényben fog szerepelni, vagyis ez azt jelenti, hogy az első néhány fejezet példaprogramjainak a main függvény lesz az egyetlen függvénye, ezekben a programokban nem hozunk létre új függvényeket.

int main() {
	/*ez itt a main függvény blokkja
	a nagyon egyszerű programok érdemi utasításait ide írhatjuk*/
}

A cout után << operátorral (műveleti jellel) választhatjuk el egymástól a paramétereket (minden paraméter előtt szerepelnie kell a << operátornak).
Egyetlen utasításban nyugodtan megadhatunk sok paramétert is, de szétbonthatjuk őket több utasításra is:

cout << "Hello World!";
cout << endl;

Észrevehettük, hogy a cout paraméterei közt szerepel egy endl nevű elem is. Ez majdnem teljesen egyenértékű az újsor karakterrel, a kettő közti különbséget kezdőként nem lényeges tudni (az endl üríti az output buffert), az egyszerű programok szempontjából egyenértékűnek tekinthetjük az újsor karakterrel. Az újsor karaktert a \n-nel jelöljük. Ha idézőjelek közé írjuk, a kiírandó szöveg bármely részén elhelyezhetjük, nem kell egy újabb << operátorral elválasztani a szövegtől.

cout << "Hello\nWorld!\n";

Illetve mint ahogy más karaktereket is, így az újsor karaktert is írhatjuk aposztrófok közé, de csak akkor, ha önálló karakterként szerepel a kódban (nem pedig egy több karakterből álló szöveg részeként):

cout << '\n';

Megjegyzések (kommentek) a programkódban

Az egyik kommentelésre használható jelölés a //, ami egy adott sor végéig tart (nem tekintendő sor végének, ha például egy szövegszerkesztő csak azért tördeli a szöveget, mert az nem fér ki egy sorba, például azért mert túl kicsi a szövegszerkesztő ablaka, vagy túl nagy a betűméret), a másik pedig a /*, ami a következő */-ig  tart, legyen az akár több sorral később is (a */ hiánya esetén a programkód végéig tart a /* hatása). Egyiket sem kötelező sor elején kezdeni. Példák:

/*Az első programom.
Nevem: Kovács Ádám*/

cout << "Hello World!\n"; //<< endl;

Ügyeljünk viszont arra, ha a /* */ jeleket használjuk kommenteléshez, akkor egy kommenten belül ne helyezzünk el újabb /* */ jeleket, de legalábbis */ jelet ne, mert akkor azt fogja a fordító a komment végének tekinteni, és így az újabb hátralévő */ fordítási hibát okoz.

// Hibás kód:
/*cout << "Hello World!" << endl;
/*cout << "Hello\nWorld!\n";*/
return 0;*/

továbbiak erről a témáról>

Változók definiálása, kezdőértékek

Amikor egy változót definiálunk (létrehozunk), jelezzük a fordítóak, hogy a számítógép memóriájában szeretnénk lefoglalni valamennyi helyet, azért, hogy egy előre meghatározott típusú (szám, szöveg, karakter, logikai) értéket tárolhassunk, mely értéket a program futása során többször felhasználhatunk, megváltoztathatunk.
(A számítógép merevlemezén többnyire a későbbi használat céljából tárolunk adatokat, a feldolgozás alatt lévő adatokat a gyorsabb kezelhetőség érdekében a számítógép memóriájában tároljuk.)
Egy változó egyszerre csak egy érték tárolására alkalmas. Egyidejűleg több érték tárolásához például tömböket használhatunk.

A változók értékét tetszőleges alkalommal megváltoztathatjuk, akár egy általunk (a program forráskódjában) megadott konkrét értékre (az ilyen értékeket literáloknak nevezzük), akár egy másik (hasonló típusú) változó értékére, akár egy olyan értékre, amit a felhasználó adhat majd meg a program futása közben (jelen feladatokban parancssorban történő begépeléssel), akár egy függvény által visszaadott értékre, akár egy fájlból beolvasott értékre, vagy valamilyen összetett kifejezés értékére

Egy változó definiálása például így néz ki:

int b;

Vagyis egyszerűen leírjuk a típusát, a nevét, és nem felejtünk el az utasítás végére pontosvesszőt tenni. Jelen példa esetén a típus int (egész szám), a név pedig b.

C++-ban nem változtathatjuk meg egy változó típusát. Vagyis ha definiáltunk egy egész szám típusú változót, abban nem tárolhatunk például szöveget.
Ez ugyan kényelmetlennek tűnhet más programnyelvekkel szemben, viszont C++-ban sokkal gyorsabban működő programokat írhatunk (ha jól használjuk a nyelvi elemeket).

Ügyeljünk arra, hogy C++-ban egy változót mindig definiálni kell a használata előtt, és egy adott blokkon belül nem lehet két változót azonos névvel definiálni.

A változók neve betűkből, számokból, és alsóvonalból ( _ ) állhat, nem kezdődhet számmal, nem tartalmazhat szóközt, valamint nem egyezhet meg a C++ nyelv kulcsszavaival (pl. if, while, double, class, typedef,..satöbbi).
A változók nevében számít a kis- és nagybetű (case sensitivity). Például az int b; és int B; utasítások különböző változót definiálnak. Egyes fordítók csak a nevek első 32 karakterét veszik figyelembe.
Ezek a megkötések nem csak a változók neveire vonatkoznak, hanem tömbök, függvények, osztályok, objektumok és egyéb dolgok neveire is. Az elnevezéseket összefoglaló néven azonosítóknak nevezzük a programozási nyelvekben.

A C++ adattípusok csoportosítása

Az adattípus meghatározza a tárolásra használt memóriaterület (változó) bitjeinek darabszámát és értelmezését. Az adattípus hatással van az adatok feldolgozására is, hisz a C++ nyelv erősen típusos, így nagyon sok mindent ellenőriz a fordítóprogram.

A C++ adattípusait (röviden típusait) sokféle módon csoportosíthatjuk. Szerepeljen itt most a Microsoft VC++ nyelvben is alkalmazott felosztás . E szerint vannak alaptípusaink, amelyek egy-egy érték (egész szám, karakter, valós szám) tárolására képesek. Vannak azonban származtatott típusaink is, amelyek valamilyen módon az alaptípusokra épülve bonyolultabb, akár több értéket is tároló adatstruktúrák kialakítását teszik lehetővé.

Típusmódosítók

C++ nyelvben az egész alaptípusok jelentését típusmódosítókkal pontosíthatjuk. A signed/unsigned módosítópárral a tárolt bitek előjeles vagy előjel nélküli értelmezését írhatjuk elő. A short/long párral pedig a tárolási méretet rögzíthetjük 16 illetve 32 bitre. A legtöbb C++ fordító támogatja a 64-bites tárolást előíró long long módosító használatát, ezért könyvünkben ezt is tárgyaljuk. A típusmódosítók önmagukban típuselőírásként is használhatók. Az alábbiakban összefoglaltuk a lehetséges típuselőírá­sokat. Az előírások soronként azonos típusokat jelölnek.

charsigned char  
short intshortsigned short intsigned sh o rt
intsignedsigned int 
long intlongsigned long intsigned long
long long intlong longsigned long long intsigned long long
unsigned char   
unsigned short intunsigned short  
unsigned intunsigned  
unsigned long intunsigned long  
unsigned long long intunsigned long long  

Inicalizálás

Inicializálásnak nevezzük, ha a változók definiálásakor megadjuk a kezdőértéküket is:

int b = 0;
float f = -2.17;
char c = 'y';
string s = "szoveg";

Egy utasításban akár több azonos típusú változót is definiálhatunk:

int a=-2, b, c=7;

Értékadások és műveletek 

Természetesen ugyanazokat a kifejezéseket használhatjuk, amikor egy változónak kezdőértéket adunk, illetve amikor később megváltoztatjuk az értékét.

Például így adhatunk értéket szám alapú (int, float, és hasonló típusú) változóknak:

b = -3;
a = b;
a = b = c;

c(4); //ugyanaz, mint c = 4;
/* A tananyag későbbi részeiben előfordulhat, hogy egyes dolgokat, csak így adhatunk értékül.
Pl. az a = nullptr kifejezés helyett az a(nullptr) kifejezés az elfogadott .*/

a = b = c esetén a és b változók értéke c változó értékével lesz egyenlő. Az értékadások jobbról balra lesznek kiértékelve, vagyis először b = c értékelődik ki, ezt követően a = b

a = b * -c; //ebben az utasításban a csillag karakter szorzásjel
a += b; //jelentése: a = a + b;

Az összeadáson kívül egyéb műveletek is rövidíthetők ily módon (pl: -=, *=, /=, %=), viszont ügyeljünk arra, hogy a kifejezést alkotó két műveleti jel közé ne tegyünk szóközt, különben a program nem fog lefordulni.

++c; //vagy c++; /*1-el növeljük a c változó értékét*/
--c; //vagy c--; /*1-el csökkenjük a c változó értékét*/
b = ++c; /*c változó értékét 1-el növeljük, és ezt értékül adjuk b változónak*/
b = c++; /*b változónak c meg nem növelt értékét adjuk értékül, majd 1-el növeljük c változó értékét*/

Egy változó értékének 1-el való megnövelését inkrementálásnak, csökkentését pedig dekrementálásnak nevezzük (magyarul léptetésnek szokták fordítani).
Fontos: a c++ vagy ++c kifejezések jelentése nem c + 1, hanem c = c + 1.

/* Teszt */
int a, b;
int i = 1, j = 1;

a = i++; //a értéke 1 lesz, majd i értéke 2 lesz
b = ++j; //j értéke 2 lesz, majd b értéke 2 lesz

/* kiíratjuk az a és b változók értékét (szóközzel elválasztva): */
std::cout << a << " " << b;

Így könnyű megjegyezni: ha a léptető operátor a változónév előtt szerepel, akkor az értékének az összetett kifejezésben való felhasználása előtt meg lesz növelve az értéke, ha pedig utána szerepel, akkor csak azt követően.

Amikor char (karakter) típusú változónak adunk értéket (a kezdőértéket is beleértve), akkor idézőjelek helyett aposztrófokat használunk:

c = '3';
c = '\n';

Ha aposztrófok helyett mégis idézőjelet használunk karakter típusú változó értékének megadásakor, a program nem fog lefordulni.

Ha esetleg pont egy aposztrófot szeretnénk értékül adni egy karakter típusú változónak, akkor azt escape karakterrel tehetjük meg:

c = '\'';

A ‘\” kifejezés végén nem egy idézőjel, hanem két aposztróf szerepel.

Idézőjelek között adjuk meg azonban a string (karakterlánc) típusú változók értékét. Az értékként megadható szövegben speciális karakterek is szerepelhetnek.

s = "tobb szobol es\ntobb sorbol allo szoveg";

Két string típusú változó értékét összefűzhetjük (ezt a műveletet konkatenációnak hívjuk):

s1 = "egyik szoveg";
s2 = "masik szoveg";
s3 = s1 + " " + s2;

String típusú változók bizonyos szakaszait is felhasználhatjuk:

s4 = s1.substr(0,4) + ", " + s2.substr(0,4);

Például az s1.substr(0,4) kifejezésben a substr tagfüggvény visszaadja az s1-ben tárolt szöveg első karakterétől az ötödik karakteréig tartó részét (értelemszerűen a 0 paraméter jelenti az első karaktert, a 4 pedig az ötödiket). Így ezen kifejezés értéke jelen példa esetén „egyik” lesz. Ennek alapján könnyen kikövetkeztethető, hogy az s4 változó értékéül adott kifejezés értéke „egyik, masik” lesz.

Ha csak egyetlen karaktert szeretnénk felhasználni egy string értékéből, akkor például a valtozonev[0] kifejezést használhatjuk. Itt a 0 szintén a legelső karaktert jelenti, és például a 12 a tizenharmadikat.

string s5 = "tetszoleges";
cout << "s5 elso karaktere: " << s5[0] << endl;
s5[1] = '3';
s5[s5.length()-1] = '5';
cout << "s5 modositott erteke: " + s5 << endl;

Egy string értékébe be is szúrhatunk valamilyen szöveg típusú értéket, például:

string s6 = "aaa";
s6.insert( 2, "bb"); //ekkor s6 erteke erre modosul: aabba

Adott szövegrész törlésével is egybeköthetjük a beszúrást (felülírás), ekkor meg kell adni, hogy mettől meddig töröljük az aktuális érték egy részletét. A 0 szintén az első karaktert jelenti.

string s7 = "szoveg";
s7.replace( 1, 4, "qwert" ); //s7 erteke ezt kovetoen: sqwertg

Hasonlóan működik az erase tagfüggvény is. Értelemszerűen csak két paramétert vár, hogy mettől meddig töröljük az adott string típusú változó értékét.

A string típusú változók méretét a length() vagy size() tagfüggvénnyel adhatjuk meg.
Például a cout << „s4 karaktereinek szama: ” << s4.size() << endl; utasítással kiíratjuk az s4 változóban tárolt érték karaktereinek számát.
Illetve a length() vagy size() tagfüggvény által visszaadott értéket valamilyen szám típusú változónak értékül is adhatjuk. Például:

int s4_merete = s4.size();

A string típusú változók további tagfüggvényei, és a használatukat bemutató példák például ezen az oldalon találhatóak.

A string típusú változók használatához szükség lehet a program elején elhelyezett #include <string> utasításra. Bizonyos fordítók használata esetén előfordulhat, hogy a program enélkül az utasítás nélkül is lefordul, és ugyanúgy működik, mintha az utasítás szerepelne a program elején. Ki lehet próbálni, hogy mi történik, ha lehagyjuk, de mindenesetre a végleges programjainkban biztonság kedvéért érdemes szerepelnie (pl. előfordulhat, hogy odaadjuk valakinek a forráskódot, aki más fordítóval készíti el a futtatható állományt).

Változók értékeinek kiíratása (parancssorba)

Változók értékeit például cout-tal írathatjuk ki a parancssorba. Bármilyen értéket kiírathatunk, amit egy változóban tárolni tudunk, de bizonyos speciális karaktereknek parancssorban nem biztos, hogy értelmezve lesz a jelentésük (pl. függőleges tabulátor). Olyan esettel is találkozunk majd, hogy nem az az érték íródik ki, amit a programkódban látunk (pl. ha kiíratjuk egy logikai változó értékét, akkor nem true vagy false íródik ki, hanem jó eséllyel 1 vagy 0).
Ha valamilyen értéket csak egyszer használunk a programunkban, akkor természetesen megfontolható, hogy eltároljuk-e egy változóba, vagy rögtön kiírassuk/feldolgozzuk.

cout << "b valtozo erteke: " << b << ", b valtozo abszoluterteke: " << abs(b) << endl;

Természetesen ha nem csak gyakorlásképp írunk programokat, hanem a programunkat valóban használni fogja rajtunk kívül valaki, akkor nem szükséges az egyes változók pontos neveit közölni a felhasználóval.

Változók értékeinek bekérése a felhasználótól (parancssorban)

Ha azt szeretnénk, hogy a program a felhasználótól kérje be egy adott változó értékét, akkor például a cin utasítást használhatjuk:

cin >> b;

Érdemes felhívni a felhasználó figyelmét arra, hogy éppen milyen típusú érték megadását várja el a program, így minden bekérés előtt cout segítségével kiírathatunk egy erre vonatkozó szöveget.
Amikor majd valaki futtatja a programot, és a program eljut egy bekérést tartalmazó utasításig, akkor az illető egy, a lentebbi képen láthatóhoz hasonló parancssoros ablakban írhatja be az értékeket, és szokás szerint az enter billentyű megnyomásával fejezheti be egy adott érték beírását. Természetesen ekkor nem kell idézőjelek vagy aposztrófok közé tenni a begépelt szöveget.

Egyszerre több változó értékét is bekérhetjük egy utasításban. A program futtatásakor ezt több egymás utáni bekérésnek fogjuk érzékelni. Ennek a nyilvánvaló hátránya, hogy a bekérések közé nem tudunk egyéb utasításokat beilleszteni (például kiírásokat arra vonatkozóan, hogy milyen érték megadását várja el a program).

cin >> a >> b;

Konstansok (állandók)

Ha olyan értékeket szeretnénk tárolni, melyeket nem szeretnénk a program futása során megváltoztatni, akkor erre a célra a konstansokat érdemes használni.
Konstansokat hasonlóan definiálhatunk mint változókat.

const int b2 = 123;
const char c = 'a';

Ne felejtsünk el (kezdő)értéket adni nekik, különben a program nem fog lefordulni.

/* Hibás kód: */
const float d; //kezdőérték megadásának hiánya fordítási hibát okoz

továbbiak erről a témáról>

Matematikai függvények

Amennyiben a fenti alapműveleteken túlmenően további matematikai műveletekre is szükségünk van, a szabványos C++ könyvtár matematikai függvényeit kell használnunk. A függvények eléréséhez a cmath deklarációs állományt szükséges beépíteni a programunkba.. A könyvtár minden függvényt három változatban bocsát rendelkezésünkre, a három lebegőpontos típusnak (floatdoublelong double) megfelelően.

Példaként tekintsük a mindenki által jól ismert egyismeretlenes, másodfokú egyenlet megoldóképletét, ahol ab és c az egyenlet együtthatói!

  
Másodfokú egyenlet megoldóképlete

A megoldóképlet C++ programban:

#include <iostream>
#include <cmath>
using namespace std;
 
int main() 
{
    double a = 1, b = -5, c =6, x1, x2;
    x1 = (-b + sqrt(b*b-4*a*c))/(2*a);
    x2 = (-b - sqrt(b*b-4*a*c))/(2*a);
    cout << x1 << endl;
    cout << x2 << endl;

Néhány gyakran használt matematikai függvény

HasználatTípusaFüggvényInclude fájl
abszolút érték képzésevalósfabs(valós x)cmath
abszolút érték képzéseegészabs(egész x)cstdlib
szög (radián) koszinuszavalóscos(valós x)cmath
szög (radián) szinuszavalóssin(valós x)cmath
szög (radián) tangensevalóstan(valós x)cmath
az argumentum arkusz koszinusza (radián)valósacos(valós x)cmath
az argumentum arkusz szinusza (radián)valósasin(valós x)cmath
az argumentum arkusz tangense (radián)valósatan(valós x)cmath
az y/x arkusz tangense (radián)valósatan(valós x, valós y)cmath
természetes alapú logaritmusvalóslog(valós x)cmath
tízes alapú logaritmusvalóslog10(valós x)cmath
ex  valósexp(valós x)cmath
hatványozás (xy)valóspow(valós x, valós y)cmath
négyzetgyökvalóssqrt(valós x)cmath
véletlen szám 0 és RAND_MAX közöttvalósint rand(void)cstdlib
π értékevalós4.0*atan(1.0)cmath

Ahol a valós típus a floatdouble és a long double típusok egyikét jelöli, míg az egész az int és long típusok valamelyikét.

Elágazások, logikai változók

Elágazások

Utasítások feltételhez kötésének legalapvetőbb módja az elágazás (if-else), melynek segítségével megadhatjuk, hogy milyen utasítások hajtódjak végre akkor, ha egy általunk (a program forráskódjában) meghatározott feltétel (logikai kifejezés) teljesül, illetve akkor, ha a feltétel nem teljesül (ez utóbbi opcionális).
Ha a feltételben nem egyértelmű kifejezés is szerepel, például egy változó, akkor annak az értéke a feltétel kiértékelésekor (vagyis amikor a program futása ehhez a ponthoz ér) aktuális érték lesz. Bizony nem olyan könnyű nyomon követni, hogy egy változó értéke egy program futása során mikor és milyen értékre módosul, ezért nem biztos, hogy csupán a forráskódot nézegetve el tudjuk dönteni, hogy egy feltétel kiértékelésekor mi lesz egy, a feltételben szereplő változó értéke. Például erre valók az úgynevezett debuggerek (nyomkövetők), hogy egy változó egy feltétel kiértékelésekor aktuális értékét kiírassuk.

Íme egy kódrészlet, amivel az if-else alapvető működését szeretném szemléltetni. Amikor ilyen kódrészletet helyezünk el a programkódunkban, a /*feltétel*/ komment helyére egy logikai kifejezést írhatunk (pl. a>-1, c<=d, e==f, g!=h), vagy egy logikai változót (melyeket általában logikai kifejezések eredményének tárolására használunk), de ha bármely más (nem logikai) kifejezést írunk (pl. a+b vagy getline(fajl, valtozonev) vagy esetleg cout << „Hello”), akkor a kifejezés logikai értékké konvertálódik (mégpedig olyan módon, hogy ha a kifejezés értéke 0-val egyenértékű, akkor hamis (false) értékké konvertálódik (ekkor az else ágban lévő utasítások fognak végrehajtódni), ha pedig 0-val nem egyenértékű a /*feltétel*/ helyére írt kifejezés (ekkor pedig true értékké konvertálódik, és az első blokkban lévő utasítások fognak végrehajtódni).

if ( /*feltétel*/ ) {
	//az ide írt utasítások hajtódnak végre, ha a feltétel igaz
} else {
	//az ide írt utasítások hajtódnak végre, ha a feltétel hamis
}

Egy elágazás végrehajtásra kerülő utasításblokkja csak egyszer fog lefutni. Adott utasítás vagy utasításblokk többszöri végrehajtása ciklusokkal (for, while, do-while) végezhető el, mely a következő fejezet témája.

Kiegészítő információ: elsőre szokatlannak tűnhet, hogy egy if vagy valamilyen ciklus paramétereként nem egy logikai kifejezés van megadva, hanem mondjuk egy egyszerű utasítás (mint például a getline(fajl, valtozonev)), de bizony előfordulhat, hogy ilyennel találkozunk egy forráskódban. Nyilván ezeknek is megvan a maga értelme, a getline(fajl, valtozonev) kifejezés például false értéket ad vissza, ha a feldolgozás elérte az adott fájl végét.

Logikai változók, logikai értékek

A logikai kifejezések eredménye vagy true (igaz) vagy false (hamis) lehet. A true és a false a C++ nyelvben literálnak minősülnek, hasonlóképp ahogy például az 5 egy int típusú literál, vagy a „szoveg” egy sztringliterál. A true és a false literálok típusa bool (logikai).

A logikai kifejezések eredményét eltárolhatjuk logikai (bool típusú) változókban (például annak érdekében, hogy többször hivatkozhassunk rájuk):

int a;
cout << "Kerem adjon meg egy negativ szamot" << endl;
cin >> a;

bool c = a < 0; //c értéke true, ha az a-ba beolvasott érték negatív

Egy if elágazásban így használhatunk egy logikai változót:

if(c) {
	//végrehajtódó utasitasok ha c értéke true
} else {
	//végrehajtódó utasitasok ha c értéke false
}

A feltételt persze így is megfogalmazhattuk volna: c == true, ami teljesen egyenértékű azzal, ha csak c-t írunk helyette. Noha szintaktikailag helyes, nem szokás ezt a hosszú alakot használni.

Egy logikai változó vagy literál értékének ellentettjét a ! operátorral kaphatjuk meg. Például:

bool e, f, g;

e = true;
f = !e; //f változó értéke false lesz
g = !false; //g változó értéke true lesz

A logikai változókat gyakran false értékkel inicializáljuk:

bool c = false;

Ha egy logikai változónak nem logikai, hanem egyéb típusú értéket adunk értékül, akkor az az érték false értékké konvertálódik, ha 0-val egyenértékű, és true értékké konvertálódik, ha 0-val nem egyenértékű.

bool b = false;
/* A következő utasítások végrehajtását követően b értéke szintén false lesz*/
b = 0;
b = 0.0;
b = '\0';
b = NULL;
b(nullptr);

bool c = true;
/* A következő utasítások végrehajtását követően c értéke szintén true lesz*/
c = -1;
c = '0';
c = "szoveg";
c = "";

Ha logikai értékeket konvertálunk számmá, akkor a false érték nullává, a true érték eggyé konvertálódik.

int a = false; //a értéke 0 lesz
int b = true; //b értéke 1 lesz

bool c = false;
int d = c; //d értéke 0 lesz

Példa: egy szám paritása

A következő példában a felhasználó által megadott szám paritását (páros vagy páratlan) íratjuk ki. Egy egész szám páros, ha kettővel elosztva 0 maradékot ad, és páratlan, ha 1-et, vagy -1-et (lényegtelen, hogy hányszor van meg benne a 2, csak a maradék a lényeg). (Nem egész szám nem lehet se páros, se páratlan, mivel, ha el is osztanánk őket maradékosan, a maradék se 0, se 1 nem lenne).
Egész számot kérünk be a felhasználótól, de ha mégis racionális számot ad meg (pl. -4.33), akkor azt a program átkonvertálja egész számmá (mivel egy int típusú változóba kérjük be az értéket a felhasználótól). Ezt akár le is ellenőrízhetjük, ha kiíratjuk a bekért értéket is.

A maradék megállapításához a % operátort használhatjuk. Például a 7 % 3 kifejezés eredménye 1, mivel a 7-ben 2-szer van meg a 3, és 1 a maradék. Másképp fogalmazva 3*2 + 1 = 7.
A % operátor operandusai csak egész szám típusú (int, vagy ahhoz hasonló: pl. short int, unsigned long int… stb.) értékek lehetnek. Ha lebegőpontos szám típusú (float, double, long double) változókkal próbáljuk használni, a program nem fog lefordulni.

Két érték egyenlőségének a vizsgálatára az == operátort használhatjuk (nem csak számok esetén). Az így kapott logikai kifejezés igaz lesz, ha az == operátor bal, és jobb oldalán szereplő kifejezések eredménye/értéke megegyezik.
Pl. b == 0 logikai kifejezés jelentése: b változó értéke egyenlő-e 0-val.

Ügyeljünk arra, hogyha esetleg két különböző típusú, de egyenértékű dolgot hasonlítunk össze, akkor az összehasonlítás eredménye true (igaz) érték lesz. Pl. 0 == ‘\0’ vagy 0 == NULL vagy 0 == nullptr kifejezések értéke true.

#include <iostream>
using namespace std;

int main () {

	int b;
	cout << "Kerem adjon meg egy (nem tul sok szamjegybol allo) egesz szamot" << endl;
	cin >> b;

	cout << "A megadott szam (" << b << ") ";

	if (b % 2 == 0) { //b valtozo erteket kettovel elosztva 0 maradekot kapunk-e
		cout << "paros" << endl;
	} else {
		cout << "paratlan" << endl;
	}
	
    return 0;
}

Egy elágazásnak természetesen nem csak két ága lehet, hanem több is. Például ha egymásba ágyazzuk az egyes if-else elágazásokat (if-elseif-elseif-…-else).

Példa: kisbetű esetén nagybetűsítés és fordítva

Az előző példa alapján könnyen írhatunk egy olyan programot, ami kiírja a felhasználó által megadott karaktert, de betűk esetén kisbetűsít, illetve nagybetűsít, attól függően, hogy kis- vagy nagybetűt adott meg a felhasználó.
Az ASCII táblában megfigyelhetjük, hogy ha egy kisbetűs karakter ascii kódjából levonunk 32-t, akkor megkapjuk a neki megfelelő nagybetű ascii kódját, valamint ugyanez fordítva is érvényes (ha egy nagybetű ascii kódjához 32-t hozzáadunk, megkapjuk a neki megfelelő kisbetű ascii kódját).

Tegyük fel, hogy ennél a bekérésnél a felhasználó egy kisbetűt (pl. b) ad értékül:

cin >> karakter;

Ha a cout << karakter – 32; utasítást használjuk, akkor a program nem a nagybetűsített karaktert fogja kiírtni, hanem annak az ASCII kódját. Ha magát a karaktert szeretnénk kiíratni, akkor használjuk a static_cast<char>( karakter – 32) kifejezést, vagy pedig külön utasításban végezzük el a karakter – 32 műveletet, majd a coutnak a char típusú változó nevét (jelen esetben karakter) adjuk csak paraméterül.

#include <iostream>
using namespace std;

int main () {
	char karakter;
	cout << "Kerem adjon meg egy tetszoleges karaktert: " << endl;
	cin >> karakter;

	if (64 < karakter && karakter < 91) {
		cout << "A megadott ertek kisbetusitve: " 
		<< static_cast<char>(karakter += 32);
	} else if (96 < karakter && karakter < 123) {
		cout << "A megadott ertek nagybetusitve: "
		<< static_cast<char>(karakter -= 32);
	} else {
		cout << "A megadott ertek: " << karakter;
	}

	return 0;
}

továbbiak erről a témáról>

switch-case (esetkiválasztásos szelekció)

A többágú elágazások egy speciális változata a switch-case (esetkiválasztásos szelekció), amit csak akkor használhatunk, ha egy változó értékét vizsgáljuk, és a változó értékétől függően szeretnénk további utasításokat megadni. 
Ez tulajdonképpen helyettesíthető egymásba ágyazott if-else-if… elágazásokkal, amikben minden esetben ugyanarra a változóra vonatkozó egyenlőségvizsgálat van feltételnek megadva (pl. x == 1, x == -3, satöbbi). A switch esetén az egyenlőségvizsgálat nem helyettesíthető más logikai kifejezéssel, továbbá csak egész szám típusú változók (pl. int, char, short int) értékeit vizsgálhatjuk switch segítségével. Tehát ha például float vagy string típusú változók értékét próbáljuk meg switchhel vizsgálni, akkor a program nem fog lefordulni.

Egy szemléltető kódrészlet a switch-case típusú elágazás működéséről:

switch (vizsgalt_valtozo_neve) {
case 1:
	//az ide írt utasítások hajtódnak végre, ha a vizsgált változó értéke 1
	break;
case 2:
	//az ide írt utasítások hajtódnak végre, ha a vizsgált változó értéke 2
	break;
case 3:
	//az ide írt utasítások hajtódnak végre, ha a vizsgált változó értéke 3
	break;
default:
	/*az ide írt utasítások hajtódnak végre, ha a vizsgált változó értéke a fenti értékek közül egyikkel sem egyezik*/
}

Ha a vizsgált változó char típusú, akkor az egyes vizsgálandó értékeket aposztrófok között kell megadni (lásd példaprogram).

Fontos: ha az egyik ágban (kivéve a default ágat) elhelyezett utasítások végére nem tesszük ki a break; utasítást, akkor azon ág utasításainak végrehajtásakor az egyel alatta lévő ág utasításai is végre fognak hajtódni. Ez akár hasznos is lehet bizonyos esetekben, de erre mindig figyeljünk, ha switch-case típusú elágazást használunk.

Ternáris operátor

Egy elágazást tömörebben leírhatunk a ? : ternáris operátor segítségével. A ternáris jelentése: három operandusú. (Két operandusú (bináris) operátor például az összeadás (+), értékadás (=), vagy az egyenlőségvizsgálat (==) hiszen ezen operátorok két oldalán két kifejezés állhat, illetve egy operandusú (unáris) például a – vagy a ++ operátor).
A ternáris operátor első operandusa a feltétel (általában logikai kifejezés, vagy logikai változó) a kérdőjel előtt, másik két operandusa pedig az elágazás két ága (az igaz és a hamis ág), a kettőspont előtt és után.

A ternáris operátor használatának szemléltetése:

/*feltétel*/ ? /*utasítás vagy kifejezés, ha a feltétel igaz*/ : /*utasítás vagy kifejezés, ha a feltétel hamis*/

Lényeges különbség az ifhez képest, hogy a ternáris operátor egyes ágaiban nem csak utasítások, hanem kifejezések is állhatnak. (Nyilván ha a ternáris operátor egyik ágában kifejezés áll, akkor a másik ágában is kifejezés kell hogy álljon, és ez ugyanígy igaz utasítás esetén is). Ha a ternáris operátor egyes ágaiba kifejezéseket írunk, akkor magát a ternáris operátoros kifejezést például értékül adhatjuk egy változónak (a változó értéke pedig a feltételtől függően az egyik ágban, vagy a másik ágban lévő kifejezés értéke lesz), vagy kiírathatjuk cout-tal (ekkor a feltételnek megfelelő ágban lévő kifejezés értékét írja ki a cout). Mindkettőre nézünk példát.

példaprogram ternáris operátorral:

#include <iostream>
using namespace std;

int main () {
	int b;
	cout << "Kerem adjon meg egy (nem tul sok szamjegybol allo) egesz szamot" << endl;
	cin >> b;
	cout << "A megadott szam (" << b << ") ";
	cout << (b % 2 == 0 ? "paros" : "paratlan") << endl;

	return 0;
}

Tömbök

A tömb (angolul array) a legegyszerűbb olyan adatszerkezet, amely sok azonos típusú érték egyidejű tárolására szolgál. A benne tárolt értékekre egyetlen névvel/azonosítóval hivatkozhatunk (a tömb nevével), így nem kell minden egyes tárolni kívánt érték számára külön-külön változókat definiálni.
A tömb sok esetben logikai csoportosítás is. Általában logikailag összetartozó elemek tárolására használunk egy-egy tömböt. Pl. ha 15 szám átlagát, és másik 20 szám összegét szeretnénk kiszámolni, akkor nem egy 35 elemű tömbben szokás elhelyezni az értékeket, hanem egy 15 elemű és egy 20 elemű tömbben.

C++-ban egy tömbben csak azonos típusú elemek szerepelhetnek (szemben például a Javascripttel). Különböző típusú értékek egyidejű tárolásához struct vagy class adatszerkezeteket szokás használni, melyekről majd egy későbbi fejezetben lesz szó.

Előfordulhat, hogy más tananyagokban a tömböket vektoroknak nevezik. Ebben a tananyagban nem így járunk el, mivel a vektor elnevezés könnyen összekeverhető a C++ Standard Template Library (STL) vector adatszerkezetével (melyet az #include <vector> utasítással használhatunk).

A C++ szabvány kétfajta (hagyományos) tömb használatát teszi lehetővé: statikus és dinamikus. A statikus tömböt akkor használjuk, ha a forráskódban megadjuk egy tömb mindenkori méretét, a dinamikus tömböt pedig akkor, ha például a felhasználótól kérjük be, vagy fájlból olvassuk be a tömb méretét, mely a program futása során akár meg is változtatható.
(Szót ejtünk majd az STL std::vector adatszerkezetéről is, mely lényegében egy kényelmi funkciókkal ellátott dinamikus tömb (pl. könnyen módosítható és lekérdezhető az elemszáma)).

Statikus tömb definiálása

Egy statikus tömb mérete egész szám konstans (pl. const int, const unsigned int) segítségével adható meg:

const int elemszam = 5;
float tomb[elemszam]; //5 darab float típusú érték tárolására alkalmas tömb definiálása

Vagy ha nem adjuk meg a tömb méretét a tömb definíciójában, de megadjuk a kívánt mennyiségű elemek kezdőértékét, akkor a megadott elemek darabszámából a fordító kikövetkezteti a tömb méretét.

int tomb_2[] = {5, -2, 3, 128}; /*4 darab int típusú érték tárolására alkalmas tömb definiálása, kezdőértékekkel*/

Megjegyzés: ha egy statikus tömb méretét nem egész szám konstans segítségével adjuk meg, hanem például a felhasználótól vagy fájlból kérjük be, a kód nem lesz szabványos, ami egyrészt azzal jár, hogy nem biztos, hogy minden fordító támogatja, másrészt pedig azzal, hogy ha a fordítót -pedantic kapcsolóval paraméterezzük, akkor a kód nem szabványos részét hibaüzenetként (warningként) jelzi a fordító.

/* Nem szabványos kód: */
int elemszam;
cout << "Kerem adja meg az elemszamot: " << endl;
cin >> elemszam;
double tomb_3[elemszam];

Dinamikus tömb definiálása

Kezdőknek dinamikus tömbök helyett inkább az std::vector használatát ajánlom, de a dinamikus tömböknek is szerepelnie kell a tananyagban, hiszen aki többet foglalkozik C++-szal, biztos, hogy találkozni fog velük.

Ha egy tömb méretét a felhasználótól kérjük be, vagy fájlból olvassuk be, vagy később meg szeretnénk változtatni akkor a dinamikus tömb a szabványos megoldás, ami viszont nagyobb odafigyelést is igényel, mivel a programozó feladata, hogy a tömb számára lefoglalt memóriaterületet felszabadítsa (amely nem biztos, hogy olyan egyszerű, ha a program sok vezérlési szerkezetet tartalmaz, mivel könnyen elfelejthetjük az egyik blokkban elhelyezni az erre vonatkozó utasítást), illetve kivételkezelést is igényel (melyről későbbi fejezetben lesz szó), mivel pl. azt az esetet is kezelni kell, ha nem érhető el elegendő szabad memóriaterület.

int elemszam;
cout << "Kerem adja meg az elemszamot: " << endl;
cin >> elemszam;
double * tomb_4 = new double[elemszam]; //elemszam darab double típusú elem tárolására alkalmas tömb definiálása

Egy tömb elemszámának bekérésénél érdemes ügyelni arra, hogy a felhasználó érvénytelen (pl. nem szám típusú) értéket is megadhat. A későbbiekben erre is nézünk egy megoldást.
(Ha a felhasználó tört számot ad meg, akkor az egész számmá konvertálódik, mivel egy int típusú változóba lesz bekérve, így ebből nem adódik gond.)

Dinamikus tömböknél akkor is meg kell adnunk az elemszámot, ha a forráskódban megadjuk a tömb elemeinek kezdőértékét. Az elemszámnak értelemszerűen legalább akkorának kell lennie, mint a megadott kezdőértékek száma. Például:

int * tomb_5 = new int[3] {128, 0, -20}; //3 darab int típusú elem tárolására alkalmas tömb definiálása (kezdőértékekkel)

Ha már nincs szükségünk egy dinamikus tömb tartalmára, így szabadíthatjuk fel a számára lefoglalt memóriaterületet:

delete[] tomb_4;

Ha erről megfeledkezünk, a tömb számára lefoglalt memóriaterület a program futásának végéig nem szabadul fel.

A delete[] operátor használata esetén csak a tömb elemei törlődnek, így ugyanazzal a névvel létrehozhatunk egy eltérő méretű tömböt. Például:

tomb_4 = new int[elemszam+1];

…vagy például:

tomb_4 = new int[elemszam*2];

Nyilván ha csak módosítani szeretnénk a tömb méretét az elemei értékének a megtartásával, akkor a törlés előtt létre kell hoznunk egy vele azonos méretű tömböt, amelybe biztonsági másolatot készítünk az eredeti tömb elemeiről, majd miután azokat visszamásoltuk a módosított méretű tömbbe, törölhetjük az ideiglenesen létrehozott tömb elemeit delete[] operátorral.

Hogyan tudunk hivatkozni egy tömb elemeire?

Ha például a legelső elem értékét szeretnénk módosítani (egy t nevű, int típusú tömb esetén):

t[0] = 53;

Illetve kiíratni:

cout << t[0] << endl;

Fontos, hogy a 0 indexű (sorszámú) elem a tömb legelső eleme, tehát a t[1] már a második elem. Ennek megfelelően pedig az utolsó elem az elemszámnál egyel kisebb indexű elem, vagyis pl. egy 5 elemű (t nevű) tömb esetén a t[4] az utolsó elem. Ha túlindexeljük a tömböt (pl. t[4] helyett t[5]-öt írunk valahol a programkódban), akkor a program jó eséllyel nem fog lefordulni.

Egy 20 elemű (t nevű) tömb utolsó elemének így kérhetünk be értéket a felhasználótól:

/* Ha t egy 20 elemű tömb, akkor t[19] az utolsó eleme */
cin >> t[19];

C++-ban asszociatív tömb (melynek az indexei nem számok) például a Standard Template Library map adatszerkezetével valósítható meg, de erről ebben a fejezetben nem lesz szó.

Ciklusok

For ciklus (elöltesztelős, számlálós ciklus)

Egy nagy elemszámú tömb esetén már hosszú lenne, ha minden egyes elem kezeléséhez külön-külön utasítást használnánk. Például ennek rövidítésére való a for ciklus.
Íme egy rövid kódrészlet, melyben definiálunk egy 20 elemű (statikus) tömböt, majd kérjük be a felhasználótól az egyes elemek értékeit:

const int elemszam = 20;
int t[elemszam];

for (int i = 0; i < elemszam; ++i) {
	cout << "Kerem adja meg a(z) " << i+1 << ". szamu elemet: " << endl;
	cin >> t[i];
}

Ennek a végeredménye ugyanaz, mintha külön-külön utasításokkal kértük volna be a tömb 20 elemének értékét. (Azzal az apró kivétellel, hogyha egyenként kérjük be őket, akkor a bekérésre vonatkozó kiírt szövegben a névelőt nem kell a(z)-nak írnunk, hanem egyenként megadhatjuk például úgy, hogy „az elso”, „a masodik”…stb.
Ezt persze a for ciklus esetén is megtehetjük, mondjuk például ha egy külön erre a célra létrehozott tömbben nullákat vagy egyeseket tárolunk, a nulla jelentheti az a névelőt, az egyes pedig az az névelőt, és egy elágazással kiértékeljük ennek a tömbnek az éppen aktuális elemét.)

A for ciklusban az i változó tartalmazza azt az értéket, amivel azt tarjuk számon, hogy hányadik lépésnél tart a ciklus (ennek az értéknek nem szükséges 0-tól egyesével haladnia egy pozitív számig).
A fenti példában az i változó képviseli például a tömb indexének aktuális értékét. Ezt úgy kell elképzelni, hogy a ciklusmag (a ciklus kapcsos zárójelei közötti utasítások sorozata) a jelen példa esetén 20-szor fut le, az első lefutásnál az i értéke 0, a másodiknál 1, a harmadiknál 2, és az utolsó lefutásnál pedig 19, illetve a ciklusmag utolsó lefutását követően az i értéke meg lesz növelve 20-ra, de ekkor a ciklusmag már nem fut le, mivel a ciklus második paraméterében megfogalmazott feltétel (i < elemszam, ezesetben 20 < 20) ekkor már nem teljesül.
Amikor pedig a bekérésre vonatkozó üzenetet íratjuk ki (cout << „kerem adja meg a(z) << i+1 << „. szamu elemet: „;), akkor az i egyel megnövelt értékét íratjuk ki, csak hogy az első elem bekérésénél ne az legyen kiírva, hogy „kerem adja meg a(z) 0. elemet”, és így tovább a többi elem esetében is.
Az i változót ciklusváltozónak, vagy iterált változónak is szokták nevezni. Fontos, hogy a ciklusváltozó csak a ciklusmagban (a ciklus kapcsos zárójelei közt) érhető el. Ha a ciklus blokkján kívül hivatkozunk rá, akkor a program nem fog lefordulni.

Egy tömb elemeinek a kiíratása is a fenti példához hasonló (cin >> t[i]; helyett pl. cout << t[i] << endl; vagy pedig cout << t[i] << ” „; utasítást használhatunk), illetve bármilyen módosítást is elvégezhetünk így a tömb elemein (pl. t[i] *= 2;), de természetesen nem csak tömbök feldolgozásához használhatunk for ciklust, hanem egyéb előre meghatározható lépésszámú műveletekhez. A leggyakoribb internetes példa az egész számok kiíratása mondjuk 0-tól 99-ig (cout << i << ” „;).

Egy for cikluson belül természetesen egyéb utasításokat is elhelyezhetünk, akár elágazást vagy egy másik for ciklust. Ezekre majd a tananyag későbbi részében láthatunk példát.

Elnagyoltan szemléltetve így működik a for ciklus:

for (/*honnan induljon*/; /*meddig tartson*/; /*merre haladjon, milyen léptékben*/) {
	/*utasítások, melyekben felhasználhatjuk a ciklusváltozó (jellemzően i nevű változó) aktuális értékét*/
}

for ciklus első paraméterében definiáljuk a ciklusváltozót. Nem muszáj i-nek elnevezni, de így szokás, illetve több egymásba ágyazott ciklus esetén i, j, k-nak szokták nevezni az egyes ciklusok ciklusváltozóit. Ennek a definíciónak a lényege inkább az, hogy mi legyen a ciklusváltozó kezdőértéke. Jelen példa esetén 0, de szükség esetén lehetne más is.

for ciklus második paraméterében adjuk meg azt a feltételt, amelynek teljesülése esetén a ciklusmag még lefut. Jelen példa esetén i < elemszam, vagyis effektíve i < 20 (mivel az elemszam értéke jelen példa esetén 20). Ha az itt megadott feltétel nem teljesül, a ciklus véget ér, vagyis a ciklusmagban lévő utasítások már nem futnak le. Jelen példa esetén ez akkor lesz, ha i értéke eléri a 20-at. Amikor i értéke 20, a ciklusmagnak már nem is szabad lefutnia, különben túlindexelnénk a tömböt (ha t húsz elemű, akkor t[19] az utolsó eleme).

A for ciklus harmadik paraméterében adjuk meg, hogy mennyivel növeljük/csökkentjük a ciklusváltozót a ciklusmag minden egyes lefutását követően.
Az i++ vagy ++i esetén 1-el növeljük az i változó értékét (a ciklus szempontjából mindkét kifejezés egyenértékű), az i– vagy –i esetén 1-el csökkentjük az i változó értékét. Illetve például az i += 2 kifejezéssel pedig kettőt adunk hozzá az i értékéhez. (Az i += 2; utasítás egyenértékű az i = i + 2; utasítással, viszont a for ciklus harmadik paraméterében szintaktikailag csak az előbbi használata helyes).

Continue utasítás

Ha azt szeretnénk, hogy egy általunk megadott feltétel teljesülése esetén a ciklusmag hátralévő utasításait hagyja ki a ciklus annál a lépésnél, ahol éppen tart (de utána folytatódjon tovább a következő lépéssel), akkor a continue; utasítást használhatjuk.
Ez például akkor lehet hasznos, ha például egy tömb elemeinek feldolgozásánál bizonyos típusú elemeket, vagy akár egy bizonyos elemet ki szeretnénk hagyni.

Szintaktikát szemléltető példa:

for (int i = 0; i < elemszam; i++ ) {
  //mindenképp végrehajtandó utasítások
  if ( /* feltétel */ ) {
    continue;
  }
  //utasítások, melyek akkor hajtódnak végre, ha az if-ben megadott feltétel hamis
}

Ebben az esetben nem kell a feltételtől függő utasításokat else ágba foglalni, hiszen a continue utasítás rögtön a ciklus következő lépéséhez ugrik, anélkül, hogy a ciklus blokkjában lévő hátralévő utasítások végrehajtódnának.

Utasítások végrehajtása, vagy nem végrehajtása mindig a ciklus egy adott lépésében értendő. Például lehetséges, hogy a feltétel igaz a ciklus harmadik lépésében (mondjuk amikor i értéke 2), így a ciklusmagban hátralévő utasítások nem hajtódnak végre a ciklus harmadik lépésében. Viszont mondjuk a ciklus negyedik lépésében a feltétel hamis, így ekkor a ciklusmag hátralévő utasításai végrehajtódnak.

Break utasítás

Ha pedig azt szeretnénk, hogy a ciklus egy bizonyos feltétel teljesülése esetén ne folytatódjon tovább (tehát ne hajtódjanak végre a ciklus jelenlegi lépésében hátralévő (a break utasítást követő) utasítások, és a ciklus következő lépései sem), akkor a break utasítást használhatjuk.

Do-while ciklus (hátultesztelős ciklus)

A do-while úgynevezett hátultesztelős ciklus, mely kifejezés azt jelenti, hogy a ciklusmagban lévő utasítások egyszer biztosan lefutnak, és a ciklusfeltételben megadott logikai kifejezés értéke csak a ciklusmag további lefutását befolyásolja.
Ebből az következik, hogy a do-while ciklust általában adatbevitel ellenőrzésre, vagy pedig utasítássorozatok ismételt végrehajtásához használjuk.
(A foreach, for és while ciklusok egyébként elöltesztelős ciklusok, mivel az esetükben a ciklusfeltétel már a ciklusmag legelső lefutását is befolyásolja: ha a ciklusfeltétel hamis, a ciklusmag egyszer sem fut le).

do-while ciklus példa: ismételt végrehajtás

Miután egyszer már lefutott a program, vagy bizonyos utasítások sorozata, megkérdezzük a felhasználótól, hogy szeretné-e újra végrehajtani. Igény szerint akár a program összes utasítása is szerepelhet egy do-while ciklus blokkjában.

Szemléltető vázlat:

do {
  //tetszőleges utasítások
  cout << „Szeretne ujra vegrehajtani a programot?” << endl;
  char valasz;
  cin >> valasz;
} while ( valasz == ‘i’ || valasz == ‘I’ );

While ciklus (elöltesztelős ciklus)

Amíg a foreach ciklus a for ciklus egy speciális esetére alkalmazható, úgy a while ciklussal a for ciklusnál bővebb eseteket is megvalósíthatunk (másképp fogalmazva a for ciklus a while ciklus egy speciális esete).
A while ciklus tulajdonképpen olyan mint egy if, else ág nélkül, azzal a különbséggel, hogy nem csak egyszer fut le, hanem egészen addig, amíg az általunk megadott feltétel érvényben van (tehát true az értéke). Amikor a feltétel már nem teljesül, a ciklusmag nem fut le (a ciklus leáll).
Ügyeljünk arra, hogy a do-while ciklussal ellentétben a while ciklus ciklusmagja egyszer sem hajtódik végre, ha a feltétel már a ciklus első lépésében hamis.

Szintaktika:

while ( /*feltétel*/ ) {
  //tetszőleges utasítások
}

while ciklus példa: egy egész szám számjegyeinek száma

For ciklus helyett while ciklust használhatunk, ha egy számlálásnál nem ismerjük a ciklusmag végrehajtásának számát.

Egy int típusú szám 10-zel való osztása valójában az adott szám legkisebb helyiértékű számjegyének elhagyását jelenti (mivel egészosztás esetén az eredményt nem tizedestört formájában kapjuk, hanem egész számként). Pl. ha int típusú 128-at osztunk 10-zel, annak eredménye 12 lesz.
(Ez persze csak akkor igaz, ha a 10 is int típusú. Ha az eredményt tizedestört alakban kívánjuk megkapni, akkor használjuk a 128 / 10.0 vagy esetleg a static_cast<double> (128 / 10) kifejezéseket).
Ha egy int típusú szám minden egyes 10-zel osztását követően növelünk egy számlálót, akkor megkapjuk az adott szám számjegyeinek számát.
A számlálónak adjunk kezdőértéket, különben az eredmény nem lesz megfelelő.

#include <iostream>
using namespace std;

int main () {
  int szam;
  cout << „Kerem adjon meg egy egesz szamot” << endl;
  cin >> szam;
  cout << „A beolvasott szam: ” << szam << endl;
  int szamjegyek = 1;

  while ( szam /= 10 ) {
    szamjegyek++;
  }

  cout << „A szamjegyek szama: ” << szamjegyek << endl;
  return 0;
}

továbbiak erről a témáról>

mogi.bme a ciklusokról és elágazásakról>