Informatika2-2015/Eloadas 8 C-1 C alapok for ciklus

A MathWikiből
A lap korábbi változatát látod, amilyen Csirke (vitalap | szerkesztései) 2015. április 1., 11:19-kor történt szerkesztése után volt.
(eltér) ←Régebbi változat | Aktuális változat (eltér) | Újabb változat→ (eltér)

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

Memória nem biztosság

Személyes eszközök