Informatika2-2015/Eloadas 8 C-1 C alapok for ciklus
Tartalomjegyzék |
C alapok
Egy kis történelem
A C az egyik legrégebbi programozási nyelv ami létezik. Amikor kifejlesztették, akkor még így nézett ki egy modern számítógép. Amikor elkezdték fejleszteni, akkor még sok helyen lyukkártyákat használtak a programozáshoz. Mi azt a változatot fogjuk használni, ami 1989-ben lett sztenderdizálva, mert még most is az az alapértelmezett.
Mivel ilyen régi a nyelv, mások voltak a szempontok a kifejlesztésekor mint a mai programozási nyelveknél. Fontos volt a hatékonyság, mind a fordítóprogram, mind a kész, lefordított program részére. És hát sok mindent, ami a legtöbb mai programozási nyelvben egyértelmű, akkor még nem is találtak ki, mint ötlet. Ennek következtében sokszor sokminden kényelmetlenebb lesz mint a python-ban.
Ennek következtében manapság a legtöbb új programozási project-hez modernebb nyelveket használnak. Viszonylag nagy biztossággal tudom állítani, hogy ha matematikusok lesztek, nem fog kelleni C-ben programoznotok. Azért még mindig vannak dolgok, amihez a C van használva, főleg olyan dolgok, amikor fontos a hatékonyság, vagy a nyelv egyszerűsége:
- A Linux operációs rendszer kernel-je, belsőségei.
- Más programozási nyelvek implementációja. Pl. a python interpreter amit használtunk, C-ben van írva.
- Úgynevezett "beágyazott rendszerek" programozása. Ilyen pl. egy kocsi belső digitális rendszere (Nem a GPS ami a pultba van építve, hanem pl. az ABS), router-ek, orvosi műszerek.
Azonban sok más programozási nyelv épül a C-re, sokat azzal a céllal fejlesztettek ki hogy a C különböző problémáit oldják meg, és ezeknek a nyelveknek szintaxisban és működésben is sok közös pontja van a C-vel. Ezért, ameddig ebből a tárgyból el fogunk jutni a C megtanulásában, az azokhoz a nyelvekhez is hasznos lesz, ezért hasznos számotokra ezt tanulni, hiába nem fogjátok magát a C nyelvet használni. Ezek közé a továbbfejlesztett nyelvek közé tartozik a C++, Java, C#, és a Go, sok más között.
Interpretált vs. Fordított nyelv
Vegyük a következő egyszerű python programot:
print "Hello World!"
Mentsük el ezt hello.py fájlnéven, és vegyük a következő, kb. ekvivalens, C programot:
#include <stdio.h> void main() { printf("Hello World!\n"); }
És mentsük el hello.c fájlnéven.
Ekkor úgy tudom futtatni a python programot parancssorból, hogy beírom hogy
> python hello.py Hello World!
(Windows-on, ha a .py kiterjesztés a python-hoz van rendelve, akkor elég duplaklikkelni rá, vagy csak azt írni parancssorba hogy "hello.py", de az akkor is ugyanúgy a python nevű programot fogja meghívni.)
Ilyenkor lefut a python nevű program, ami a python nyelv interpretere, és az beolvassa a python.py fájlt, és végrehajtja a benne levő utasításokat. Ahhoz hogy futtatni tudjam a python programomat, fel kellett hogy telepítsem a python-t a számítógépemre.
Ezzel ellentétben C-nél először ezt írom be a parancssorba:
> gcc hello.c -o hello.exe
Ekkor még nem fut le az általam írt program, csak létrejön egy új fájl, hello.exe néven. Ez egy alkalmazás, amit aztán külön tudok futtatni, pl. így
> hello Hello World!
Ezt a hello.exe fájl át tudom küldeni más Windows-os gépekre, és azokon is tudom futtatni, attól függetlenül hogy a C azokra telepítve van-e. A gcc egy C fordító: lefordítja a .c fájlt egy alkalmazássá.
Ez két különböző megoldás a programozó nyelvek megvalósítására.
Összehasonlítva a kettőt: Forráskód:
- Interpreternél oda kell adni magát a kódot a felhasználónak, így biztos bele tud nézni hogy hogy működik
- Fordítónál a forráskódot titokban lehet tartani, így azt is hogy belül hogy működik a programunk (ami lehet hogy versenyelőny számunkra)
Sebesség:
- Általában a Fordítós programnyelvek gyorsabbak/hatékonyabbak a program futásakor
Fejlesztés sebessége:
- Interpreternél egyből el tud indulni a kód amit éppen módosítottunk. (Némelyik interpretált nyelvnél akár futás közben is változtatható a kód.)
- Fordított nyelveknél van egy plusz lépés a kód megírása és a kipróbálás között, ami nagy programoknál néhány perc is lehet.
Ellenőrzés:
- Interpretált nyelveknél csak a kódnak azt a részét ellenőrzi ami lefut, ezért könnyű félkész programnak csak a kész részeit tesztelni, de
- 'Fordított nyelvnél az egész programot ellenőrzi (és, hát, feldolgozza) fordításkor, így könnyebb biztosnak lenni hogy nem maradt alapvető hiba a programban mielőtt az alkalmazást átadjuk.
Különböző fordítók
A python-hoz a python interpreter, amit az előbb említett módon a parancssorból a python paranccsal elindítok az a python nyelvnek a CPython nevű, C-ben megírt megvalósítása. Ez messze a legelterjedtebb megvalósítás, a szabvány szerint ahol nem egyértelmű a szabvány leírása, ott ennek a megvalósításnak kell megfelelni. Csak akkor használunk más változatot, amikor speciális körülmények vannak (pl. a CloudCoder-en belül), de a más változatoknak is az a célja, hogy a CPython-nak megfeleljenek.
Ezzel ellentétben a C-nél van egy szép ~520 oldalas pdf fájl, ami igyekszik minden részletre menően leírni hogy minden esetben mit kell csinálnia a programnak. (Megjegyzem hogy ez úgy 520 oldal, hogy a C nyelv jelentősen egyszerűbb mint a python. Ezeket a modern/bonyolultabb nyelveket már kb. lehetetlen lenne pontosan leírni hogy mikor mit kell csinálniuk, minden esetre kiterjedően.) Ez amit linkeltem, a C89 sztenderd, amit egy bizottság elfogadott nemzetközi ISO sztenderd C-nek, és a különböző fordítók ezt próbálják megvalósítani. Ellentétben a python-nal nincs egyértelmű győztes, több fordító is van elterjedt használatban.
- Talán a legelterjedtebb a gcc (GNU Compiler Collection). Ezt fogjuk mi is használni laboron, és ennek egy változatát ajánlom otthoni használatra is. Ez egy nagyon régóta fejlesztett fordító, az első publikus változata 1987-ben lett közzétéve. Nyílt forráskódú, és a Linuxon ez az alapértelmezett, ezt használják kb. az összes linux változat fordítására is.
- A gcc-hez hasonló alapelvekkel rendelkezik a clang (C language front end). Ez is nyílt forráskódú, de kicsit máshogy, és az Apple kezdte el jogi okok miatt erősen fejleszteni kb. 10 éve, de az elmúlt ~5 évben már eléggé feltört, és kezdi veszélyeztetni a gcc-t, van már egy-két linux változat is ami ezzel van fordítva. (Ez azért nagy szám, azért említem, mert a linux talán a legbonyolultabb létező C program, amelyik fordító azzal elbír az valószínűleg minden mással is.) Előnye hogy újabb, ezért a fordítóprogramok írásában azóta kifejlesztett technikákat tudták használni a megírásakor, ami néhány dologban jobbá teszi. Apple Mac rendszereken ez már egy ideje az alapértelmezett.
- A Microsoft saját fordítója az MSVC (Microsoft Visual C). Ez ugyan nem nyílt forráskódú, de már sok éve mindenki számára ingyenesen elérhető. Windows-os fejlesztéshez elég népszerű, egybe van csomagolva a Visual Studio fejlesztő környezettel, aminek (most már) az ingyenes változata is jól versenybe száll a más ingyenes fejlesztőkörnyezetekkel. Azért nem ezt ajánlom, hogy ugyanazt használjátok otthon mint laboron, és mert a kezelőfelület ugyan tapasztalt programozók számára hatékony, kezdők számára ilyesztő lehet, sok felesleges dolgot tartalmaz. Windows-on ez az alapértelmezett.
Vannak még más fordítók is, de kevésbé népszerűek, úgyhogy most nem térek ki rájuk.
Alap szintaxis
Whitespace
Első dolog ami más mint a python-ban, hogy nem számít hogy hova tesszük az újsorokat, behúzásokat, szóközöket. Ha két nyelvi elem el van választva a kódban, akkor annyi szóközt, újsort, és tab-ot tehetsz közé amennyit akarsz, csak pl. egy változónéven vagy karakterláncon belülre ne tegyél. Ezeket a karaktereket, a szóközt/újsort/tabot együttesen whitespace-nek hívják.
Például nézzük az egyik lehetséges legegyszerűbb C programot:
#include <stdio.h> void main() { printf("Hello World!\n"); }
Ez ekvivalens ezzel:
#include <stdio.h> void main () {printf( "Hello World!\n") ;}
De azért persze az első változat olvashatóbb. Így tehát nem azt mondom ezzel, hogy felejtsétek el amit a python-nál tanultatok ebből a szempontból, hanem hogy továbbra is alkalmazzátok, annak ellenére hogy a nyelv maga már nem kötelez rá. (Ezért szeretik a tanárok előbb tanítani a python-t, ha nincsenek a szép kódra kötelezve az új tanulók, nagyon csúnya, és hát, a tanár számára nehezen olvasható, kód szokott születni.)
Mivel az új sor nem jelenti a programsor végét, ezért azt pontosvesszővel jelezzük, mivel a blokkot nem jelezhetjük azzal hogy több tab-ot teszünk a sor elejére, ezért azt kapcsos zárójellel jelezzük. További hasonló dolgokat meglátjuk amikor eljutunk az illetékes nyelvi elemig.
Típusosság
A python egy nem típusos nyelv. Ez azt jelenti, hogy egy változónak a típusa nem fix. Ezért működik a következő kód:
a = 5 print a a = "Elemer" print a a = None print a
Itt az a változónak sorról sorra változik a típusa, számról karakterláncra, majd NoneType-ra. Ezzel ellentétben a C-nél minden változónak meg kell mondani a típusát mielőtt először használjuk. Így ez a program nem helyes:
#include <stdio.h> void main() { float a; a = 5.5; a = "Elemer"; }
Ha megpróbálom ezt lefordítani, akkor a gcc hibaüzenetet ad:
>gcc hello.c -o hello.exe hello.c: In function 'main': hello.c:6:5: error: incompatible types when assigning to type 'float' from type 'char *' a = "Cica";
Ez a kötelesség a típus megadására mindenre kiterjed, majd a függvényekre magukra, és a függvények paramétereire is.
Egyelőre ismernünk kell az int típust, ami egész számok tárolására használható, és a float típust, ami valós számokhoz.
if, while
Az if feltétel és a while ciklus alapvetően ugyanúgy néz ki mint python-ban, csak az eddig említett szintaxis különbségekkel: mindkét esetben a feltételt zárójelbe kell rakni, a futtatandó kódot pedig kapcsos zárójelbe. Példa if-re:
#include <stdio.h> void main() { int a = 5; if (a > 0) { printf("Pozitiv!\n"); } else { printf("Nem pozitiv!\n"); } }
Példa while-ra:
#include <stdio.h> void main() { int a = 5; while (a > 0) { printf("Meg pozitiv!"); a -= 1; } }
Függvény definiálás
Függvény definíció úgy néz ki, hogy