[itk] Számítástechnika kezdőknek

C++ programozás kezdőknek - első lépések

[2016. szeptember 06.] [ christo161 ]

Ebben a részben elméleti alapismeretekről, és a CodeBlocks fejlesztői környezet telepítéséről és alapvető használatáról lesz szó (egy olyan programról, ami első ránézésre egy szövegszerkesztőre hasonlít, és a programozást segítő kényelmi funkciókkal van ellátva), valamint dióhéjban a parancssorban történő fordításról. Ebben a részben még nem kezdünk el programozni.

Következő rész: Az első program

Előszó

Ez a tananyag azoknak készült, akik még soha életükben nem programoztak, és nem tudják hogyan kezdjék el. Esetleg azoknak is ajánlom, aki már elkezdtek programozni, de valamit nem értenek, valahol elakadtak.
A címben a "kezdőknek" szó nem azt jelenti, hogy könnyű, hanem csak azt, hogy először az alapvető tudnivalók szerepelnek a tananyagban, lehetőség szerint egymásra épülve (ez utóbbit sajnos nem lehet tökéletesen megvalósítani, mert minden mindennel összefügg).
A tananyag elején természetesen sok olyan példaprogram szerepel, amiket már rengetegen megírtak, de ahhoz, hogy egy témában újat tudjunk alkotni, meg kell értenünk már meglévő tudnivalókat is.
Legyünk türelmesek, mert nem lehet néhány nap alatt a nulláról megtanulni C++-ul, és lehet, hogy egyes anyagrészekre többször is vissza kell térni az alaposabb megértéséhez.
Ez a tananyag akkor is hasznos lehet valakinek, ha később más programozási nyelvet választ a C++ helyett, mivel a tananyag algoritmizálási ismereteket is tartalmaz, illetve sok más programozási nyelv szintaktikája (nyelvtani szabályai) hasonlít a C++-ra.

codeblocks_hello_world.png

A tananyag különböző részeiben kiegészítő információk is találhatók. Ezek egy része nem annyira fontos, viszont gyakran tartalmaznak olyan tudnivalókat is, amik kizárólag azért kerültek a kiegészítő információk közé, mert az adott fejezet olvasásakor még nem baj, ha az olvasó nem érti őket, egy-két további fejezet elolvasását követően viszont mindenképp érdemes visszatérni rájuk.
Ne essünk pánikba, ha olyan kifejezéssel találkozunk a tananyagban, ami nincs rögtön elmagyarázva. Egy példa: már az első példaprogramnál kitérünk arra, hogy minden C++ programnak tartalmaznia kell egy main nevű függvényt, és persze attól, hogy nevén nevezzük a dolgot (vagyis megemlítjük, hogy ez egy függvény), nyilvánvalóan ezen a ponton még nem kell megérteni, hogy pontosan mi is az a függvény, és milyen szerepe van a programozásban.
A tananyag egyes részei átugorhatók, de volt már arra példa, hogy valaki a jelen fejezetet teljesen kihagyta, mert úgy gondolta, hogy itt csak mellékes elméleti tudnivalók szerepelnek, aztán persze azt sem tudta, hogy ha a CodeBlocks-ból a fordítót nem tartalmazó verziót telepíti fel, akkor a legalapvetőbb példaprogramokat sem tudja lefordítani és futtatni (hacsak nem telepít fel manuálisan egy fordítót). Szóval aki tényleg a nulláról kezd programozni tanulni, annak nem tanácsolom ezen tananyag nem folytonos olvasását, kivéve persze ha valaki egy ZH előtti este találja meg ezt a tananyagot, akkor talán érdemes csak a példaprogramokra fókuszálni (már ha ezt a sort elolvassa az illető :) ).

Természetesen biztos lesz, akinek ezen tananyag stílusa nem fog tetszeni, de mindenkinek tudom ajánlani a jobb oldalt található hasznos linkek oldaldobozt (mobil nézetben nem látszik). Illetve ha valaki esetleg hibát talál a tananyagban, nyugodtan jelezze hozzászólásban, vagy a facebook oldalon.

Update: bár szerintem nagyon szembetűnő, de mivel azt tapasztaltam, hogy nem mindenkinek egyértelmű, ezért leírom, hogy ez a tananyag jelenleg még félig sincs kész. Aki nulláról kezd programozást tanulni, annak így is egy jó kis kezdeti löketet adhat, de nem javaslom, hogy bárki arra várjon, hogy a közeljövőben elkészül a tananyag hátralévő része. Javaslom a már korábban említett jobb oldali hasznos linkeket (ismét megemlítem, hogy mobil nézetben nem látszik), illetve az udemyn elérhető tananyagokat.

Az előszó keretében következzen még néhány gyakori kérdés, és csak azt követően kezdődnek a tényleges tudnivalók. Ezekről a kérdésekről persze nyilván jókat lehet vitatkozni, előfordulhat, hogy ezeknek a válaszoknak az ellentétét is leírja valaki valahol. Az itt használt fogalmakat csak azoknak kell értenie, akik vitatkozni szeretnének ezekkel az állításokkal :)

Lehet-e diploma nélkül programozóként dolgozni?

Rövid válasz: igen, lehet.
Viszont ezt a nulláról elérni jó eséllyel nem 2-3 hónap. Sok olyan példát láttam már, hogy valaki elvégzett egy OKJ vagy ahhoz hasonló tanfolyamot, aztán ha azzal nem tudott rögtön elhelyezkedni, feladta. Nem szabad feladni. Ehhez idő kell. Van, akinek évek.
A C++-ban pedig az a jó, hogy nem fog néhány év alatt felismerhetetlenül megváltozni, esetleg csak kibővül néhány új lehetőséggel :)
Én például munka mellett (amely munkának semmi köze nem volt a programozáshoz) tanulgattam programozni, és sosem gondoltam volna, hogy valaha ebben fogok dolgozni, de aztán szép lassan, évek alatt eljutottam egy olyan szintre, aminek köszönhetően ez megtörténhetett. Arra bíztatok mindenkit, akit érdekel a programozás, hogy ne hagyja abba, ha apránként is, de frissítse a tudását.

Tényleg matekzseninek kell lenni ahhoz, hogy valaki megtanulhasson programozni?

Rövid válasz: szerintem nem.
Ahhoz, hogy elkészítsünk egy ablakos programot, ami egy SQL adatbázisból kér le adatokat, amiket mondjuk egy táblázatban megjelenít, nem kell egyetemi matek.
Alapvető matematikai ismereteket azért meg kell tudni érteni. Például, hogy egy egész szám akkor páratlan ha kettővel osztva egyet ad maradékul, és akkor páros ha nullát. Vagy például, hogy egy szám abszolútértéke az adott szám mínusz egyszerese, ha a szám negatív, ha pedig a szám pozitív, akkor önmaga (másképp fogalmazva a vizsgált szám mínusz előjel nélkül).
Illik ismerni az alapvető aritmetikai műveletek precedenciáját (elvégzési sorrendjét) is. Például, hogyha egy összetett aritmetikai kifejezésben nincs zárójelezés, akkor előbb a szorzást és az osztást végezzük el (ha több is van egymás mellett, akkor balról jobbra), és csak azt követően az összeadást és a kivonást (ha több is van egymás mellett, akkor balról jobbra).
Pl. 3-60/5/4-1=-1

Ezek általános iskolai első- és második osztályos tananyagok. Az emberek túlnyomó része csak akkor nem érti őket, ha nem akarja.
Persze vannak olyan területei a programozásnak, amihez mindenképp egyetemi matek kell. Például: grafikus keretrendszert (pl. Unreal Engine, Unity Engine) nélkülöző 3d grafika, titkosítás, mesterséges intelligencia.
Azt azért nem garantálom, hogy a tananyag teljesen matekmentes lesz, de annyit megígérhetek, hogy a példaprogramokban nem másodfokú egyenletek megoldását vagy két szám legnagyobb közös osztóját fogjuk megkeresni. (Arra viszont senki ne számítson, hogy az első példaprogramok nagyon érdekesek lesznek és sok értelmük lesz :) ).

Tényleg elavult nyelv a C++?

Rövid válasz: nem.
De biztos sok hozzászólást fognak írni egy ilyen című hír alá :)
Attól, hogy több Java programozót keresnek, mint C++ programozót, még nem lesz elavult a C++. Sőt, attól sem, hogy C#-ban könnyebb programozni.
A C++-hoz jelenleg is aktívan készülnek az új szabványok (C++17, C++20/23), melyek új lehetőségekkel bővítik a nyelvet.

cpp_timeline_1.png

cpp_timeline_2.png

forrás: modernescpp.com

Sok népszerű programot írtak és írnak ma is C++-ban. Ezeknek a karbantartásához még jó ideig szükség lesz C++ programozókra.
Egy lista C++-ban írt programokról

Illetve van még egy nem elhagyagolható indok, amiért ma is érdemes C-ben vagy C++-ban programokat írni. Gyorsabb programokat lehet írni C++-ban, mint sok más programnyelvben.
"C++ code is much faster than C# code, which makes it a better solution for applications where performance is important. For instance, your network analysis software might need some C++ code, but performance is probably not a huge issue for a standard word processing application coded in C#." forrás
Porkoláb Zoltán a C programozás videósorozatának a második videójában is említést tesz erről, illetve Horváth Gábor is kitér erre a videójában.

C++ nyelven tényleg csak parancssoros programokat lehet írni?

Rövid válasz: nem.
Ennyi erővel Javaban is, meg C#-ban is. És csak a nyelvet kiegészítő függvénkönyvtárak segítségével lehet ablakos vagy 3D-s programokat írni.
Egy lista C++-ban írt programokról
Tény viszont, hogy bizony a legtöbb (tehát nem az összes) magyar nyelvű tananyag/tanfolyam C++-szal csak parancssoros programok szintjén foglalkozik.

C++-ban tényleg mindent nulláról kell megírni, és nem támaszkodhatunk mások által megírt függvényekre, osztályokra?

Egy lista C++-hoz használható függvénykönyvtárakról/osztálykönyvtárakról

Egy másik lista C++-hoz használható függvénykönyvtárakról/osztálykönyvtárakról

Persze előfordulhat, hogy egy program forráskódjában nulláról írnak meg függvényeket vagy osztályokat, ahelyett, hogy valamelyik meglévőt használnák (pl. a LibreOfficeban nem a C++ Standard Library std::string osztályát használják, hanem egy saját OUString nevű osztályt a szövegek tárolásához).

A C nyelv ismerete szükséges-e a C++ nyelv megértéséhez?

Nem, de természetesen nagy előny.
Illetve szinte minden programozási nyelv ismerete előny egy újabb programozási nyelv megértéséhez/megtanulásához. Az persze előfordulhat, hogy hasonló nyelvekben bizonyos dolgoknak némileg eltérő jelentése van, mint C++-ban (pl. C++-ban és C#-ban a static vagy a using kulcsszavan nem egészen ugyanazt jelentik, illetve C#-ban és Javaban nem definiálható olyan függvény, ami nem metódus/tagfüggvény, míg C++-ban igen).

Nehezebb-e a C++ nyelv, mint a C?

Bár a C++ bővebb, mint a C (így ilyen szempontból elsőre nehezebbnek tűnhet), de sok esetben igaz az, hogy a C nyelvben bonyolultabban lehet megoldani valamit. Jó példa erre már rögtön a parancssorba történő kiíratás (C-ben printf, C++-ban cout), illetve hogy C-ben nincs string típus (hanem karaktertömböket használ szövegek tárolásához), míg a C++-hoz ott az std::string a Standard Libraryben.
Jó eséllyel igaz az az állítás, hogy aki meg tudja tanulni az egyiket, az a másikat is.

Minden C nyelvű kód érvényes a C++ nyelvű kódnak is?

Nem, és ez soha nem is volt így. Már csak azért sem, mert C++-ban vannak új kulcsszavak, amik C-ben lehetnek azonosítónevek, C++-ban viszont nem. Ez persze gyakorlatilag nem nagy különbség, de vannak ennél jelentősebb különbségek is.
Sőt, kerülendő a C stílusú kód C++ kódban történő használata.

További tévhitek a C++-ról:

A C++ legnépszerűbb mítoszai III. rész
Common Misconceptions of C++
Some popular misconceptions about C++

Aki szeretne még arról olvasni, hogy a C++ miért ilyen, és miért nem olyan, annak ajánlom a Bjarne Stroustrup oldalán lévő gyakori kérdéseket.

A jelenleg népszerű programozási nyelvek között szerintem nincs olyan, amiről legalább egy okos/híres programozó ne mondott valami rosszat. Természetesen így van ez a C++-szal is, és sokat el lehet ilyeneken vitatkozgatni, de én azt gondolom, hogy ha valaki bármilyen programozási nyelvet megtanul alaposabban, az már becsülendő, legyen szó Java-ról, C#-ról, vagy akár PHP-ról.

Alapvető tudnivalók

Ebben a tananyagban azt a tevékenységet nevezzük programozásnak, amikor egy számítógépes program forráskódját (vagy annak csak egy részét, esetleg egy új verzióját) készítjük el, legyen szó egyszerű vagy bonyolult programról. Bonyolultabb programok esetén a forráskód megírását alapos tervezés előzi meg, illetve a kód átláthatósága érdekében be kell tartani bizonyos kódolási szabályokat, mintákat is (például: [1], [2]). Természetesen ezen tananyag példaprogramjai annyira egyszerűek, hogy nem kell tervezgetni őket.
Arról is jókat lehet vitatkozni, hogy mi a különbség a programtervező, a fejlesztő, a kódoló és egyéb hasonló elnevezések között (egy erről szóló cikk), de itt ebbe most nem megyek bele.

A számítógép nyelve a gépi kód, amit általában 1-esek és 0-k (vagyis kettes számrendszerbeli számok) sorozataként szoktak emlegetni. A számítógép processzora csak a gépi kódú utasításokat tudja végrehajtani, és persze különböző processzortípusonként eltérő gépi kódok léteznek.
Mivel nehéz lenne gépi kódú programokat írni, ezért létrehoztak kényelmesebb, emberközelibb programnyelveket. (Ezeknek a szintjeit nem fogom pontosan kifejteni, csak két szintet említek meg. Részletesebb információ: Andrew S. Tanenbaum Számítógép architektúrák c. könyvében.)
A gépi kódú programozáshoz közelebb álló nyelveket hívjuk assembly nyelveknek, melyek használata esetén a programozó feladata hadverközeli dolgok kezelése (pl. a processzor regiszterei, megszakításkezelés). A mai magas szintű nyelvekkel ellenténben az assembly nyelvekben jellemzőek a (goto-szerű) ugróutasítások is.
Ahhoz, hogy egy adott assembly nyelven írt kódot a számítógép processzora végre tudjon hajtani, először át kell alakítani gépi kóddá. Ezt végzi el az assembler. Különböző processzortípusokhoz eltérő assembly nyelvek léteznek.
Az assemblynél könnyebben tanulható, és hardverfüggetlenebb nyelveket hívjuk magas szintű programozási nyelveknek. Ezek közé tartozik például a C, C++, C#, Java, Visual Basic, Pascal, Javasctipt, Perl, Phyton, Ruby, shell script, bash script, ... stb.
A magas szintű nyelvek létrejöttével természetesen nem szűnt meg az alacsonyabb szintek létjogosultsága. Noha magas szintű nyelveken könnyebb programozni, az alacsony szintű nyelveken viszont jobban kihasználhatjuk a számítógép hardvere által nyújtott lehetőségeket, és hatékonyabb programokat írhatunk.

gepi_kod_assembly_cpp.png

A C, és C++ nyelveket egyaránt szokták a magas szintű, és tévesen az alacsony szintű programozási nyelvek közé sorolni. Valójában magas szintű nyelvek, de alacsony szintű műveleteket, valamint bitstruktúrákat is támogatnak (sok más magas szintű programozási nyelvvel ellentétben).
Természetesen a magas szintű programozási nyelveken írt kódot is át kell alakítani gépi kóddá, ahhoz, hogy a számítógép processzora futtatni tudja, de ennek több módja is létezik, melyeknek természetesen megvannak az előnyei és hátrányai is.

  • Pl. C++ esetén a C++ nyelven írt programkódot tartalmazó fájlok (forrásfájlok) alapján egy fordító (compiler) hozza létre a gépi kódú utasításokat tartalmazó fájlokat (a futtatható programot, mely futtatásához a fordítást követően már nincs szükség a fordítóra).
    Bonyolult programok esetén a lefordított fájlokból szinte lehetetlen, de legalábbis nagyon nehéz pontosan visszafejteni a forráskódot (reverse engineering).
    Nyílt forráskódú (open source) programoknak hívják azokat, amelyeknek a forráskódját a készítők rendelkezésre bocsátják.
    Néhány példa: a Linux operációs rendszerek kernelje (magja), Firefox, Thunderbird, LibreOffice, Gimp, Blender, Audacity, VLC player, FileZilla, Notepad++, Wireshark. Több példa: egy lista nyílt forráskódú szoftverekről. Ezek forráskódja általában github.com-on található meg.
  • Pl. a Perl, Phyton, vagy a (jellemzően linuxos) shell script, vagy Bash script esetén a forráskód nem kerül lefordításra, nem jönnek létre gépi kódot tartalmazó fájlok, hanem egy értelmező (interpreter) alakítja át a program forráskódját a program futtatásának minden egyes alkalmával gépi kódra.
    Ezekhez hasonló a Javascript is, ám az esetében az internetes böngészőkbe van beépítve a Javascript értelmező.
  • Pl. a Java nyelv ebből a szempontból a fenti opciók hibridje. A fordítás által keletkező köztes kódot (bájtkódot) egy értelmező (Java Virtual Machine) futtatja.

Megjegyzés: a fent felsoroltak csak néhány szemléltető példa, egy programnyelv ezek közül akár több lehetőséget is támogathat (pl. Java kódból is lehet fordított fájlt készíteni), illetve az idők folyamán változhat a helyzet.

A C++ nyelven írt forrásfájlok gépi kódra történő fordításának lépései:

  • C++ esetén először egy úgynevezett preprocesszor (előfordító) végez módosításokat a programkód szövegén (pl. #define: keresés és csere, #include: a header fájlok tartalmának a programkódba történő beillesztése), a programkódban elhelyezett, preprocesszornak szóló (# jellel kezdődő) utasítások alapján (melyek mindegyike külön sorba írandó).
    Ebben a lépésben (preprocesszálás) még nem kezdődik meg a gépi kódra történő átalakítás.
    Fordítási egységnek (translation unit) nevezzük, ha egy cpp fájlba a preprocesszor (rekurzívan) beillesztette az összes header fájl tartalmát.
  • Ezt követően a fordító (compiler, pl. GCC, CLang, Visual C++, stb) az egyes fordítási egységekből úgynevezett object fájlokat hoz létre, melyek már gépi kódú utasításokat (úgynevezett tárgykódot) tartalmaznak, de még nem futtathatóak. (Ennek előnye, hogy több fájlból álló forráskód esetén elég csak azt a fájlt újrafordítani, melynek módosítjuk a tartalmát).
  • Végül az object fájlokat a linker szerkeszti össze futtatható fájllá.

Néhány megjegyzés:

  • A GCC rövidítés (GNU Compiler Collection) egy programcsomag, mely tartalmazza a gcc-t, és a g++-t. A g++ fordítót C++ programkódok fordítására használjuk, a gcc-t pedig C programkódok fordítására. Elképzelhető, hogy valahol mégis úgy fogalmaznak, hogy "GCC fordító", de ezalatt nyilvánvalóan C kód esetén a gcc-t, C++ kód esetén pedig a g++-t kell érteni.
  • Különböző processzortípusokhoz különböző fordító készíti el a gépi kódot a forrásfájlokból. Ez akkor is így van, ha több különböző processzortípushoz is elérhető egy adott fordító (pl. GCC). Ekkor az a gépi kód, amit pl. egy x86-os processzortípushoz állítottunk elő, nem fog működni egy ARM processzoros eszközön.
  • Hasonló a helyzet a különböző operációs rendszerek esetén. Pl. egy Windowsos GCC más objectfájlokat hoz létre, mint egy Linuxos GCC. Sőt, például a grafikus felületen futó programoknak, vagy bonyolultabb parancssoros programoknak már a forráskódja is tartalmaz operációs rendszer specifikus elemeket.
  • Ha a C++ nyelven írt program csak egyetlen forrásfájlból áll, akkor is keletkezik object fájl, amiből szintén a linker hozza létre a futtatható fájlt.
  • Unix-szerű rendszereken az object fájlok kiterjesztése .o, Windowsban pedig .obj
  • Ha esetleg olyannal találkoznánk, hogy a.out, az már egy futtatható fájl, nem pedig object fájl. Akkor kapunk a.out (assembly output) elnevezésű fájlt, ha Unix-szerű rendszeren nem adunk meg nevet az indítható állománynak (például a g++ helloworld.cpp parancs esetén).
  • A fordító (illetve az értelmező) nem képes egy programkód minden hibáját felismerni. Előfordulhat, hogy noha egy helyes kifejezést írunk a programkódunkba, de ez a kifejezés mégsem azt jelenti, mint amire gondoltunk. Ennek eredményeképp ha a programunk le is fordul, lehet, hogy nem egészen úgy fog működni, mint ahogy elvárnánk.
    Az ilyen hibák felderítése nem könnyű egy több ezer soros kódban, ezért jó ha tisztában vagyunk egy programozási nyelv apróbb részleteivel, illetve hogy pontosan milyen hibákat követhetünk el (erről a témáról több száz oldalas könyvek szólnak (pl. C++ hibaelhárító)).

Manapság számos programozó nem csupán fordítót és egyéb, a fordítóhoz mellékelt programokat, továbbá valamilyen kezdetleges szövegszerkesztőt használ, hanem kényelmi funkciókkal is ellátott fejlesztői környezetet, úgynevezett IDE-t (integrált fejlesztői környezetet). Például: CodeBlocks (C::B-nek szokták rövidíteni), Microsoft Visual Studio, Apple XCode, Qt Creator, KDevelop, CLion, NetBeans, Eclipse, Geany, Anjuta, Dev-C++, C++ Builder.
Ebben a tananyagban CodeBlocks-t fogunk használni, C++ nyelven fogunk programozni, és g++ fordítót fogunk használni (ami a GCC része).
Egy fejlesztői környezet első ránézésre egy szövegszerkesztőre hasonlít. Természetesen egyéb funkciókat is tartalmaz, például ha vannak hibák a forráskódban, a fordítás megkísérlésekor kiírja, hogy melyik sorban találhatók a hibák (bár erre önmagában a fordító is képes), tartalmaz nyomkövető módot (debug), amellyel lépésenként futtathatjuk a programunkat, és ellenőrízhetjük, hogy az egyes lépésekben a változóink milyen értékeket vesznek fel. Tartalmaz továbbá kódszínezőt (syntax highlight), esetleg auto indent funkciót (egy blokkon belüli kódot automatikusan bejlebb tabulál). És persze kényelmesebb a menüből kiválasztani a fordítás elindítását (build and run), vagy egy gyorsbillentyűt megnyomni (f9), mint parancssorból fordítani.

A CodeBlocks fejlesztői környezet innen tölthető le:
http://www.codeblocks.org/downloads/binaries

CodeBlocks telepítése Windowson

Windowsban a CodeBlocks telepítése egyszerű next, next, finish-szerű telepítés. Kezdőként ügyeljünk arra, hogy a fordítót is tartalmazó telepítőfájlt töltsük le (amelyiknek a mingw kifejezés szerepel a nevében), különben a CodeBlocksban nem fogjuk tudni lefordítani, és futtatni a programjainkat (hacsak nem telepítünk és állítunk be hozzá manuálisan valamilyen fordítót).
Az idők során jó eséllyel frissebb verziójú CodeBlocks telepítőfájlokat lehet majd letölteni a honlapról, tehát a verziószám változni fog. Vagyis a telepítőfájl nevében a képen látható 16.01 helyett valami más fog szerepelni (pl. 17.12).

codeblocks_windows_mingw.jpg

A mingw a GCC Windows-os portja (windowsra megírt verziója). Tartalmazza pl. a g++ fordítót, tartalmaz linkert, assemblert (egy C++ nyelven írt programba be lehet ágyazni assembly kódot is),  a C++ Standard Library header fájljait, egyéb rendszerspecifikus header fájlokat (pl. Windows API), és egyéb összetevőket. A pontos lista itt megtekinthető: http://www.mingw.org/wiki/MinGW

A CodeBlocks nem csak Windows-on érhető el, hanem egyéb népszerűbb operációs rendszereken is. Például: OS X, Linux (pl. Debian, Fedora, CentOS, Suse, Ubuntu). A CodeBlocks honlapjának a letöltés menüpontjában megtaláljuk az egyes operációs rendszereknek megfelelő telepítőfájlokat.

CodeBlocks telepítése Linuxon

Debian és Ubuntu alapú Linux disztribúciókon (amiken van apt csomagkezelő frontend)

(Egy másik blogomon már írtam egy ismertetőt a Debian, és Ubuntu alapú linuxokon történő parancssoros telepítésről.)

codeblocks_ppa.png

A letöltéseknél az Ubuntunál láthatunk egy PPA címet:
https://launchpad.net/~damien-moore/+archive/ubuntu/codeblocks-stable

Ezt a címet kell hozzáadni az apt adatbázisához, annak érdekében, hogy a programot telepíteni lehessen. (Illetve amint új verzió érhető el, a frissítéskezelő az egyéb frissítésekkel együtt fel fogja kínálni a telepítést, valamint az apt-get update és apt-get upgrade parancsokkal szintén telepíthetjük.)

A címet át kell alakítanunk ilyen formába:
ppa:készítő_neve/program_neve, vagyis
ppa:damien-moore/codeblocks-stable
...mert az add-apt-repository parancs (amivel PPA címeket lehet hozzáadni az apt adatbázisához) csak az ilyen formájú címeket tudja kezelni.

A PPA cím apt adatbázisához való hozzáadásához, az elérhető frissítések letöltéséhez, és a CodeBlocks telepítéséhez használjuk ezt a három parancsot:

sudo add-apt-repository ppa:damien-moore/codeblocks-stable
sudo apt-get update
sudo apt-get install codeblocks

Azonban ettől a három parancstól még nem fog települni a g++ fordító, így ha azt külön nem telepítjük, a parancssorban és a CodeBlocks-ban sem tudjuk fordítani és futtatni a C++ nyelven írt programjainkat.

gplusplus_not_installed.jpg

codeblocks_gplusplus_not_installed.jpg

Érdemes telepíteni a build-essential csomagot, ami tartalmazza a gcc, és g++ fordítót is. Az ehhez szükséges parancs:

sudo apt-get install build-essential

apt_get_install_build_essentials.jpg

Hogy kezdhetünk el programot írni a CodeBlocksban?

Miután elindítottuk a CodeBlocks-ot, kattintsunk a kezdőlapon Create a new project szövegre, vagy pedig a file menüből válasszuk a New, majd a Project menüpontot.

codeblocks_new_project.png

Eleinte parancssoros programokat fogunk írni (melyek parancssorból kérik be az adatokat a felhasználótól, és a parancssorba írják ki az eredményt), így válasszuk a Console applicationt.

codeblocks_new_console_application_linux.png

Egyébként attól függetlenül, hogy egyelőre parancssorban futó programokat írunk, észrevehetjük, hogy az itt felsorolt lehetőségek némileg eltérőek a különböző operációs rendszereken (pl. Windowson és Linuxon). Ez azért van, mert például az ablakos, vagy 3D-s programok írása jellemzően eltérő módon valósítható meg különböző operációs rendszereken. Néhány példa:

Windows API: ablakos programok (Windows)
Windows Forms: ablakos programok (Windows)
GTK: ablakos programok (több platform)
Qt: ablakos programok (több platform)
SDL: 2D és 3D programozás, jellemzően játékok (több platform)
DirectX: 3D programozás (Windows)
OpenGL: 3D programozás (több platform)
Vulkan: 3D programozás (több platform)

Egyrészt kezdőknek tanácsos először parancssoros programokat írni, és azok segítségével megérteni az alapokat.
Továbbá a fentebb felsoroltakhoz nem a CodeBlocks a legszerencsésebb választás. (Pl. Windows Formshoz Visual Studio, Qt-hoz pedig Qt Creator).

codeblocks_new_console_application_win.png

Ebben a tananyagban a C++ programozási nyelvet fogjuk használni, így válasszuk a C++-t.

codeblocks_new_project_step_1.png

Ezt követően a legfelső szövegmezőben nevezzük el a projektünket (pl. elso_programnak), majd egyel lejjebb, a ... feliratú gombra kattintva válasszunk ki egy könyvtárat, ahová el szeretnénk helyezni a projekt könyvtárát (ami tartalmazni fogja a programunkhoz tartozó forrásfájlokat, a fordítást követően keletkező fájlokat, és egyéb fájlokat, például a projekt beállításait tartalmazó fájlt).
FONTOS: ne szerepeljen szóköz vagy ékezet sem az elérési útban, sem a projektnévben (sem pedig a projekt azon fájljainak nevében, amiket a több fájlból álló projektek esetén a projekthez majd később hozzáadunk).

codeblocks_new_project_step_2.png

A következő lépésnél kiválaszthatjuk a fordítót (alapesetben a GCC programcsomag fordítói vannak kiválasztva: gcc és g++), illetve megadhatjuk, hogy a projekt könyvtárán belül milyen könyvtárba jöjjön létre a programunk forráskódja alapján készített futtatható állomány, illetve a fordítás közbeeső lépésének fájljai.
Kezdőként itt semmit nem kell átállítani, rákattinthatunk a Finish gombra.

codeblocks_new_project_step_3.png

Ekkor a CodeBlocks a projekt könyvtárában létrehoz egy main.cpp nevű forrásfájlt, amiben egy nagyon egyszerű programkódot helyez el (Hello World! szöveg kiíratása a parancssorba). Ezt a fájlt úgy nyithatjuk meg, ha a baloldali panelen duplán kattintunk a sources mappára, majd a main.cpp fájlra.

codeblocks_open_main_cpp.png

Amikor majd programot írunk, elsősorban ennek a main.cpp fájlnak írjuk át a tartalmát, illetve az egyszerűbb (egy fájlból álló) példaprogramok kódját ebbe a fájlba másolhatjuk be (akár a fejlesztői környezet segítségével, vagy akár egy egyszerű szövegszerkesztővel, viszont formázást használó szövegszerkesztőt (pl. Microsoft Word, Wordpad, OpenOffice, LibreOffice) erre a célra ne használjunk).
Az ebben a fájlban található main függvény a programunk belépési pontja. A program érdelmi tartalma (vagyis amit a program valójában csinál) a main függvény első utasításával kezdődik (akkor is, ha a forráskód több fájlból áll).
(Ne tévesszük össze a main.cpp fájlt a main függvénnyel. A main.cpp fájlt nevezhettük volna másképp is, pl elsoprogram.cpp-nek, viszont a main függvényt nem nevezhethük át, különben a program nem fog lefordulni. A CodeBlocks alapértelmezetten main.cpp-nek nevezi el az egyszerű parancssoros program main függvényt tartalmazó fájlját, de természetesen ezt is módosíthatjuk.)

A fordításhoz, és egyúttal a program futtatásához válasszuk a Build menüből a Build and run menüpontot, vagy használjuk az F9 gyorsbillentyűt (mindkét esetben mentésre kerülnek a forráskódban végzett módosítások).

codeblocks_build_and_run.png

Ekkor (ha nincs a fordító által észlelhető hiba a programban) a program futásának eredménye egy parancssoros ablakban lesz látható. Amikor a program futása véget ér, a parancssoros ablak nem tűnik el azonnal, hanem csak egy Enter billentyű leütését követően. De ez csak a fejlesztői környezetben van így. Ha a Windows fájlkezelőjében duplán kattintunk a program futtatható fájljára (pl. elso_program.exe), akkor a megnyíló parancssoros ablak a program futását követően azonnal bezárul. A későbbiekben lesz szó ennek a problémának a megoldásáról is. 

codeblocks_hello_world.png

C++11 szabvány

A C++11 szabvány (korábbi nevén C++0x) 2011 szeptemberében jelent meg, sok újdonságot és módosítást tartalmaz (például új típusokat, új vagy módosított kulcsszavakat).
Bővebb információ: [1] [2]

Ha azt szeretnénk, hogy egy CodeBlocks projektünket a fordító a C++11-es szabvány szerint fordítsa le, akkor a bal oldali panelen jobb gombbal kattintsunk a megnyitott projekt nevére, majd válasszuk a Build options menüpontot...

cpp11_build_options.png

...majd a megnyíló ablakban jelöljük be a Have g++ follow the C++11 ISO C++ language standard lehetőséget.

cpp11_build_options_2.png

Ha ezt nem tesszük meg, de a forráskódunk tartalmaz olyan kódrészletet, ami csak a C++11-es szabvány szerint érvényes, akkor a program nem fog lefordulni (a fordító nem fogja elkészíteni az indítható állományt).

Hasonlóan járhatunk el a C++14, C++17 és C++20 verziókkal.

Egyéb: egy CodeBlocks projekt könyvtára és fájljai

Alapbeállítás szerint a lefordított fájl a projekt könyvtárán belüli bin könyvtárban jön létre.

codeblocks_project_files.jpg

A projekt könyvtárában találhatjuk a program forráskódját, a main.cpp-t is (később majd lesznek olyan programjaink is, amik nem csak ebből az egy fájlból állnak).
A .cbp kiterjesztésű fájl a CodeBlocks projekt fájl, ha erre duplán kattintunk, a projekt megnyílik a CodeBlocksban. Ez és a többi fájl egyéb beállításokat tartalmaz a CodeBlocks projektre nézve, a tényleges forráskódot a .cpp, .h, esetleg .cxx, .hxx, .hpp kiterjesztésű fájlok tartalmazzák.

Egyéb: online C++ fordítók

Számos honlap létezik, ahol a C++ kódunkat beírva a futtatás eredményét megtekinthetjük. Ez hasznos lehet, ha például egy olyan számítógépet használunk, ahol nincs jogosultságunk, vagy időnk programokat telepíteni (pl. iskola, munkahely, kávézó).

cpp_online.png

Egyéb: tetszőleges terminál beállítása Linuxon

Linuxon azt is be lehet állítani, hogy melyik parancssoros programban futtassa a CodeBlocks a fordítást követően a programot.

codeblocks_cli_types.png

Például Ubuntuban a gnome-terminalt használva:

codeblocks_gnome_terminal.png

Fordítás parancssorban

Windowsban:

A billentyűzetünkön nyomjuk meg egyszerre a windows gombot és az R billentyűt, majd a felugró ablakba (futtatás) írjuk be, hogy cmd és üssünk entert.
Ekkor elindul a parancssor.
(Persze kikereshetjük valamilyen menüből is a parancssort, csak ahány Windows verzió, annyi különböző módszer van már erre).

Lépjünk be abba a könyvtárba, ahol a lefordítandó cpp fájlunk található.
Itt futtassuk a következő parancsot:
g++ bemenetifájlnév -o kimenetifájlnév.
Példa:

g++ elsoprogram.cpp -o elsoprogram.exe

A bemeneti fájlnév annak a fájlnak a neve, amit fordítani szeretnénk (a forrásfájl), a kimeneti fájlnév pedig a programkódból keletkező indítható fájl. A kimeneti fájlnév kiterjesztése szükségszerűen exe, mivel a Windowsban az indítható állományok leggyakoribb kiterjesztése exe.
Ha több bemeneti fájl van, akkor azokat szóközzel elválasztva soroljuk fel egymás után.
(C++11-es szabvány szerint érvényes kódrészletet tartalmazó forráskód esetén a fordításhoz használt parancsban a sikeres fordításhoz szerepelnie kell az std=c++11 kapcsolónak, a fájlparaméterek előtt:
g++ -std=c++11 bemenetifájlnév -o kimenetifájlnév)

windows_cli_compile.png

Tipikus hiba, hogy a rendszer nem találja a g++-t. Van egy környezeti változó (path), ahová ha beírjuk egy könyvtár elérési útját, akkor az abban a könyvtárban lévő indítható állományok (pl. exe, com, bat kiterjesztésű fájlok) bármelyik könyvtárból elindíthatóak lesznek az elérési útjuk megadása nélkül is.
Amikor telepítettük a CodeBlocks-ot, az egyik alkönyvtárába települt a g++.exe fájl is. Ahol ez a fájl van, annak a könyvtárnak az elérési útját kell hozzáfűznünk az említett környezeti változóhoz.

Ezt parancssorban például úgy tehetjük meg, hogy belépünk abba a könyvtárba, aminek az elérési útját hozzá szeretnénk adni a pathhoz, és itt kiadjuk a következő parancsot:
set path=%path%;%cd%
Ebben az esetben a változtatás csak addig él, amíg be nem zárjuk a parancssort. Ha azt szeretnénk, hogy a változtatás tartós legyen, akkor a vezérlőpultban nyissuk meg a számítógép beállításait (vagy használjuk a windows gomb + pause break gyorsbillentyűt), majd válasszuk a rendszer menüpontot, ott pedig a környezeti változók feliratú gombra kattintsunk. Itt az alsó listában megtaláljuk a path-ot, és át tudjuk szerkeszteni. Az egyes könyvtárak elérési útjai pontosvesszővel vannak elválasztva egymástól.

windows_set_path.png

Linuxon:

Nyissunk meg egy parancssoros felületet (Ubuntuban például ctr+alt+t vagy ctr+alt+f1, mely utóbbi esetén alt + f7-el tudunk visszalépni grafikus felületre), lépjünk be abba a könyvtárba, ahol a lefordítandó cpp fájl található
Itt futtassuk a következő parancsot:
g++ bemenetifájlnév -o kimenetifájlnév. Például:

g++ main.cpp -o elsoprogram

Ha több bemeneti fájl is van, akkor azokat szóközzel elválasztva tudjuk felsorolni.
A kimeneti fájlnak nem szükséges kiterjesztést adni (mint Windowsban), mivel a Linux alapú operációs rendszerek nem igénylik, hogy a fájlneveknek kiterjesztése legyen. Azért van mégis egyes fájloknak kiterjesztése Linuxon is, mivel vannak olyan alkalmazások, amik viszont igénylik a kiterjesztések használatát.
C++11-es szabvány szerint érvényes kódrészletet tartalmazó forráskód esetén a fordításhoz használt parancsban a sikeres fordításhoz szerepelnie kell az std=c++11 kapcsolónak:
g++ -std=c++11 bemenetifájlnév -o kimenetifájlnév

linux_gcc_cli_compile.jpg

A lefordított programot parancssorban így futtathatjuk:

./fájlnév

linux_cli_execute.jpg

A fájlnév előtt az aktuális könyvtárat valójában csak akkor kell jelölni, ha az aktuális könyvtár elérési útja nem szerepela PATH környezeti változóban. Mivel a saját könyvtárunk az alkönyvtáraival együtt szerepel a PATH változóban, így sokszor nem szükséges az aktuális könyvtár kiírása egy indítható fájl parancssorban történő futtatásakor, de nem hátrány, ha megszokjuk a használatát.

Esetleg előfordulhat, hogy a lefordított fájlon nem lesz futtatási jog, és így hibaüzenetet kapunk az indítás megkísérlésekor. Erről úgy tudunk meggyőződni, hogy az ls -al paranccs által megjelenített listában az adott fájlhoz tartozó első oszlop nem tartalmaz x karaktereket. Ekkor használjuk a chmod u+x ./fájlnév parancsot. Ezen parancs futtatásához lehet, hogy rendszergazdai jogosultság szükséges.

Kiegészítő információk

Amikor CodeBlocksban rákattintunk a Build and Run ikonra, vagy megnyomjuk az F9 billentyűt, a Build Logban megfigyelhetjük, hogy a CodeBlocks a következő parancsokat futtatja (alapbeállítás szerint):

g++ -Wall -fexceptions -g -c elérési_út/main.cpp -o obj/Debug/main.o
g++ obj/Debug/main.o -o bin/Debug/projektnév

Az egyszerűbb áttekintés érdekében tekintsük a parancsokat extra kapcsolók nélkül:

g++ -c elérési_út/main.cpp -o obj/Debug/main.o
g++ obj/Debug/main.o -o bin/Debug/projektnév

Ezen két utóbbi parancs csupán annyiban különbözik a fentebb már említettől (g++ main.cpp -o elsoprogram), hogy nem csak futtatható állományt hoz létre, hanem egy közbeeső object fájlt is.

Az első utasítás első paraméterében megadjuk a forrásfájlt, majd az -o (output file rövidítése) kapcsolót követően a létrehozni kívánt object fájl nevét (a -c kapcsoló ahhoz szükséges, hogy az első lépésben csak az object fájl jöjjön létre, a linkelés még ne történjen meg).
A második utasításban pedig első paraméterként adjuk meg a létrehozni kívánt indítható állomány (a projekt könyvtárához képesti) elérési útját és nevét, második paraméterként pedig az object fájl (projekt könyvtárához képesti) elérési útját.

A CodeBlocks alapbeállításai által használt további kapcsolók jelentése:

-Wall: ne csak a fordítási hibákat (angolul error) írja ki a fordító, hanem a lényegesebb figyelmeztetéseket (warning) is.

error: nem fordul le a program, ha ilyen típusú hiba szerepel a forráskódban
warning: ha csak ilyen hibát tartalmaz a forráskód, a program lefordul, de lehet, hogy hibás működést fog eredményezni, illik kijavítani az ilyen típusú hibákat is

-fexceptions: kivételkezelés ( azaz try { } catch ( ) { } blokkok ) engedélyezése a forráskódban. C++ kód esetén ez akkor is érvényes, ha nincs megadva (C kód esetén viszont nem), ha esetleg C++ kódban tiltani szeretnénk a kivételkezelést, akkor az -fno-exceptions kapcsolót használhatjuk.

-g: a debug (nyomkövető) mód használatához plusz információk elhelyezése a kódban. A fájlok mérete nagyobb lesz, így a felhasználók számára közzétett verzió fordításakor érdemes kikapcsolni.

Egyéb kapcsolók:

-Wextra: a fordító az összes warningot kiírja, nem csak a lényegesebbeket.

-pedantic: a fordító hibaüzenetben kiírja a kód nem szabványos részeit. Nem szabványos kódrészlet az, amit bizonyos fordítók engedélyeznek, de előfordulhat, hogy egyes fordítók nem támogatják. Egy példa:
int elemszam;
cin >> elemszam;
int tomb[elemszam];
Ezt például a g++ elfogadja, de példaául a Microsoft Visual Studio fordítója nem (erről a kódrészletről a tömbök fejezetben lesz szó részletesebben). A kód hordozhatósága miatt javasolt a forráskódnak lehetőség szerint csak szabványos kódrészletet tartalmaznia.

-std=c++11: a forráskód C++11-es szabvány szerinti értelmezése.

-O3 (nem nulla, hanem nagy o betű): a fordító a sebességre optimalizálja a kódot.

-Os: a fordító az alacsony helyfoglalásra optimalizálja a kódot.

Ezeket a kapcsolókat természetesen parancssorban történő fordításnál is használhatjuk, és a CodeBlocksban is beállíthatjuk, ugyanabban a menüben, ahol a C++11-et (lásd fentebb).

A fordítás egyes lépéseinek eredményei:

Az előfordítás eredményét kiíratjuk a parancssorba (ez általában több ezer sor, így érdemesebb inkább fájlba menteni):

g++ -E fajlnev.cpp

Az előfordítás eredményét bemásoljuk a fajlnev.txt nevű fájlba:

g++ -E fajlnev.cpp > fajlnev.txt

(Ha már létezik ilyen nevű fájl > jel esetén felülírja, >> jel esetén pedig a tartalmához hozzáfűzi).

gpp_e.png

Az assembly kóddá történő fordítás eredményét menjük el a fajlnev.s nevű fájlba:

g++ -S fajlnev.cpp

gpp_s.png

Az object fájllá történő fordítás eredményét kapjuk meg a fajlnev.o (Windowson fajlnev.obj) nevű fájlba:

g++ -c fajlnev.cpp
g++ -c fajlnev.cpp -o fajlnev.o

Ha a programunk több forrásfájlból áll, akkor természetesen nem készíthető minden forrásfájlból egy-egy indítható állomány, hanem az egyes forrásfájlokat object fájllá tudjuk külön-külön lefordítani (akár anélkül, hogy a többi fájlt is le kellene fordítani), majd az összes object fájlból készülhet el az indítható állomány. (A DLL, illetve SO kiterjesztésű fájlokról csak a tananyag későbbi részében lesz szó.)

Indítható állomány létrehozása:
Unix-szerű rendszereken:

g++ fajlnev.cpp -o fajlnev

Windowson:

g++ fajlnev.cpp -o fajlnev.exe

Következő rész: Az első program

A bejegyzés trackback címe:

https://itkezdoknek.blog.hu/api/trackback/id/tr887746690

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.