Bevezető előadás

1 Miről lesz szó a félévben?

A számítási folyamatok


Milyenek?

2 A programok

/* legnagyobb közös osztó */
int a, b, t;

scanf("%d %d", &a, &b);

while (b != 0) {
   t = a%b;
   a = b;
   b = t;
}

printf("%d", a);

A programkódok


Programozási nyelv

A C nyelvet eredetileg Dennis Ritchie fejlesztette ki, 1969 és 1973 között. Azóta több szabványosított változata lett. A jelenlegi változata 2011-ben jelent meg, de az alapjai a kidolgozása változatlanok.

3 A programozás lényege

Program készítése

Legnagyobb közös osztó
  1. A két szám: A és B.
  2. Amíg B≠0, addig
    1. T legyen A/B maradéka
    2. A-ba másoljuk B-t
    3. B-be másoljuk T-t
  3. A-ban a keresett osztó.

„A programozás alapjai”

Az utóbbi miatt jó az is, hogy egy viszonylag alacsony szintű nyelvvel foglalkozunk. Ami ugyanis a számítógépnek bonyolult vagy nehézkes valamilyen szempontból, azt C-ben sem lehet általában egy-két szónyi programkóddal megoldani. Ezért aztán a félévben mindenki előtt két feladat áll igazából: megtanulni programozni, és megérteni a számítógép lelkivilágát. Ez kell ahhoz, hogy a C-vel boldogulni lehessen.

4 A félév végére…


Telefonkönyv

Kit keresünk? Tapsi Hapsi

Száma: 555-125687

Új keresés (i/n)? n_

Hogyan lehet olyan programot írni, amely sok adatot tárol és dolgoz fel?

Megváltoztatunk egy cellát a táblázatkezelőben, és újraszámolódik minden, ami kell. Hogyan lehet ezt megcsinálni?


Egyszerű játékok: hogyan működik például egy kukacos játék? Hogyan jegyzi meg, merre halad a kukac?

Amőba játék: mitől tűnik úgy a gép, mintha intelligens lenne? Meg tudod verni a saját amőba játékodat? Meg tudja verni a szobatársad? Meg tudod úgy erősíteni, hogy már ne tudja?! :)

Tudnivalók a tárgyakhoz

6 Tudnivalók I.

Honlap, adminisztrációs portál

Minden információ hiteles forrása: http://infoc.eet.bme.hu/

Konzultáció: kérdések, nagy házi stb.


Oktatás: két tárgyban; külön jegy!

  1. Programozás alapjai 1.
    Előadás: ez most itt.
    Gyakorlat: kis tantermi, táblán-papíron feladatmegoldás
  2. Szoftver labor 1.
    Labor: géptermi órák – önálló munka, programozás

7 Tudnivalók II. – Prog 1.

Elvárások

  1. Részvétel: max 30% hiányzás előadáson (RFID!) és gyakorlaton.
  2. 1 nagy ZH: „zárthelyi”, ellenőrző nagydolgozat a félév közben.
  3. 5 kis ZH: gyakorlati órák elején. A 3 legjobb átlaga kell elérje a 40%-ot.
  4. Vizsga: ez adja a végleges jegyet.

Számonkérések jellege

Gyakorlati órák – átjelentkezés

8 Tudnivalók III. – Szoftlab 1.

Szoftver labor 1.

  1. A laboron önálló munka van.
  2. Részvétel: max 30% hiányzás. Beugró lesz az órák elején!
  3. Kis ZH-k: az előző hasonlóan. 5-ből a 3 legjobb számít.
  4. NHF: nagy házi feladat.
    A félév közben kell elkészíteni, 13. héten bemutatni.
  5. Jegy: a KZH-k és a NHF alapján.

Nagy házi

9 Jövőbeli programozós tárgyak

Nem teljes lista:

Algoritmusok

11 A tudás fajtái

Deklaratív tudás

  • „Ami igaz”
  • Egy számról meg tudjuk mondani, hogy egy másik gyöke-e.

Imperatív tudás

  • „Hogyan kell csinálni”
  • Ha adott egy szám, ki tudjuk találni, mennyi a gyöke!

x gyöke egy olyan y,
amire y2=x,
és y≥0

Tippeljük meg, mennyi: y'.
A tipp javítható: (y'+x/y')/2
Javítgassuk, amíg nem elég jó.

Ennek megfelelően: imperatív programozás az, amikor olyan programot kell írni, amelyben lépésről lépésre megmondjuk a számítógépnek, hogy mikor mi a teendő. A hangsúly az imperatív nyelvekben a megoldás módján van. Léteznek deklaratív programozási nyelvek is, amelynél megadjuk, milyenek a helyes megoldások, és a számítógép találja ki a megoldás módját. Ezeknél a megoldható problémák köre sokkal szűkebb, mint az imperatív nyelvek esetében.

Látjuk azt, hogy az imperatív tudás hasznosabb. A deklaratív tudás alapján, ha adott egy zsáknyi y, akkor meg tudjuk mondani, hogy azok közül melyik az, amely x-nek gyöke. Viszont sokkal jobb ennél az, ha kapunk egy x-et, akkor meg tudjuk határozni a hozzá tartozó y-t!

12 Specifikáció és algoritmus

Specifikáció: mit kell csináljon


Algoritmus: hogyan csinálja


Művészet? Tudomány? Mérnöki feladat?

Nincs olyan általános módszer, amely segítségével egy algoritmus szisztematikusan kidolgozható lenne. Vagyis amellyel egy deklaratívan („mi igaz”) adott problémára imperatív („hogyan kell csinálni”) megoldás lenne adható. Hogy ez vajon művészet, tudomány vagy mérnöki feladat, azt nem lehet 100%-osan eldönteni:

A programozás során rengeteg olyan problémával találkozunk, amelyek rendszeresen felmerülnek. Vannak jól bevált megoldások, amelyeket érdemes újra és újra felhasználni. Egy jó programozó bármikor tud mondani többféle módszert is arra, hogyan lehet egy névsort ábécébe rendezni, sőt azt is tudja, mikor melyik módszer a gyorsabb. Ezért sokszor, amikor programozunk, már megtanult algoritmusokat kódolunk csak le.

13 Egy gép belülről: faktoriális számítása

Ezzel a géppel egy szám faktoriálisát lehet kiszámolni.

L
1. Írd be a számot N-be.
2. Nyomd meg az A↓1 gombot.
3. Nézd meg, hogy világít-e a lámpa.
    Ha igen, ugorj a 7. pontra.

4. Nyomd meg az S↑A gombot.
5. Nyomd meg az N→ gombot.
6. Ugorj a 3. pontra.
7. Kész, az eredmény A-ban.
faktoriális gép
használati utasítás

A gép alkatrészei:

  • Trapéz: a ráírt műveletet végzi. Ha megváltozik a bemenete, akkor a kimenete is rögtön követi.
  • Háromszög: konstans számot állít elő.
  • Téglalap (regiszter): ez egy számot tárol.
  • Gomb: beírja a számot abba a regiszterbe, amely felé a nyíl vezet.
  • Kör: a beleírt feltétel teljesülését ellenőrzi.
  • Lámpa: világít, ha az elé kötött feltétel teljesül.

Vegyük észre, hogy nem csak az alkatrészek határozzák meg a működést, hanem a használati utasítás is. Ha nem tartjuk be pontosan, hanem össze-vissza nyomkodjuk a gombokat, akkor a gép hülyeséget csinál.

14 Pszeudokód: a gép szöveges leírása

Ez egy
algoritmus

Megjegyzett számok: A és N.
Kérj egy számot a felhasználótól: N.
A értéke legyen 1.
Ellenőrzés: Ha N=1, ugorj előre a „vége” címkéhez.
A értéke legyen A·N.
N értékét csökkentsd 1-gyel.
Ugorj vissza az „ellenőrzés” címkéhez.
Vége: Írd ki A értékét.


A szöveges leírás (pszeudokód) tartalmazza:

Vagyis mindent, ami az előző dián is volt.

Ezzel megadjuk az algoritmust. Vegyük észre, hogy teljesen mechanikusan végrehajtható lépésekről van szó: egyszerű, matematikai jellegű lépéseket végzünk. Szorzást kell elvégezni, egyenlőséget vizsgálni stb.

15 Algoritmus – definíció

Algoritmus: módszer a feladat megoldására

  • Utasítássorozat megengedett lépésekből
  • Mechanikusan végrehajtható
  • Véges sok lépésből áll
  • Mindig egyértelműen adott a következő lépés
  • Minden időpontban véges sok memória kell

 175
+343
────
 518

összeadás

  • „az összes számjegyet”
  • „add össze”
  • ha eléri a 10-et, van átvitel”
20│2
10│2
 5│5
 1│ 

prímtényezős felbontás

  • amíg nagyobb, mint 1”
  • ha osztható”
  • „írd le az osztót”

A papíron összeadás és a prímtényezős felbontás olyan algoritmusok, amelyeket általános iskolában tanítanak. Vegyük észre, hogy mind kimerítik a fenti feltételeket: mechanikusan végrehajthatóak, mindig pontosan definiálják a következő lépést – és valamilyen bonyolult probléma megoldását adják meg úgy, hogy közben egyszerű lépéseket használnak.

Változók, típusok és kifejezések

17 A változók fogalma

Változók: eltárolt, megjegyzett értékek, amelyeknek nevet adunk.

  • Másképpen: egy hely neve, ahol valamilyen értéket tárolunk.
  • Egy változó egy dolgot jegyez meg, ezért minden megjegyzett dologhoz külön változó kell.

Műveletek

Kiértékelés
Egy változóban tárolt adatot előveszünk, „olvassuk”.
Értékadás
Egy változóban új adatot jegyzünk meg, „írjuk”.
A régi értéke ilyenkor elveszik!

18 A változók használata

A program futása során, egyes időpontokban más lehet az értéke:

X értéke legyen 5.     értékadás (írás)

Leírom X-et.             kiértékelés (olvasás): „5”

X értéke legyen X+1.  kifejezés kiértékelése, aztán értékadás

Leírom X-et.              ez „6” lesz

A programnak időbeliséget adnak!

Fontos gondolat, hogy az értékadás miatt számít a műveletek sorrendje! Ha nem létezne értékadás, akkor ez nem lenne így. Például az alábbi képletben teljesen mindegy, hogy melyik tényező értékét számítjuk ki előbb: (3+4)×(6-9)×(12-4-6+5). Haladhatunk balról jobbra, jobbról balra, vagy akár kezdhetjük a középső 6-9-cel is. Ezzel szemben a fenti kódban láthatóan számít az, hogy a növelés előtt után írjuk le az X változó értékét. A faktoriálisszámító gépnél is számított az, hogy milyen sorrendben nyomjuk meg a gombokat.

19 A típusok fogalma

Típus: az értékkészlet és a műveletek együttese.

  • A változóknak típusa van
  • Ez határozza meg az értékkészletet és a végezhető műveleteket is
  • A típusok szinte minden programozási nyelvben megtalálhatóak

Típusok: példák
típusértékkészletműveletek
egész-1, 2, 5, …összeadás, kivonás, összehasonlítás
valós1.5, 7, 3.14, …összeadás, kivonás, összehasonlítás
logikaiigaz, hamisés, vagy, tagadás
karakterbetűk, írásjelek, …összehasonlítás, következő, előző
szövegkaraktersorozatokösszefűzés, keresés

20 Kifejezések

Kifejezések és típusok

műveletek
kifejezéseredmény
1+23
5+2*311
6*(3+4)42
vegyes kifejezések
kifejezéseredmény
1<2igaz
2≥3hamis
'a' < 'b'igaz

A műveletek adott típusokon végezhetőek el, és az eredménynek is van valamilyen típusa. Ezek azonban nem feltétlenül ugyanazok. Például egy szám+szám művelet eredménye is szám, de egy szám<szám összehasonlítás logikai, igaz/hamis típusú eredményt ad. Lehetséges az is, hogy egy művelet két operandusának típusa sem egyezik meg: időpont+időtartam→időpont. Pl. 12:15+30 perc=12:45.


Kifejezések tagjai

21 Hibás kifejezések

Érvényes kifejezés


kifejezéshiba
3*(1+nincs meg a vége
'a' + 'b'karakter plusz karakter?
1-HAMISszám mínusz logikai?
1<X<5X szám → 1<X logikai. Logikai < szám?
(1<X)<5értelmetlen
1<(X<5)értelmetlen

C bevezető

23 Helló, világ

A tradicionális első program forráskódja:

első C
program
#include <stdio.h>

int main()
{
    /* üdvözlet */
    printf("Helló, világ!\n");

    return 0;
}

Helló, világ!

printf() – kiírás

\
visszaper
(backslash)
  • printf(): kiír valamit
  • "szöveg": a szöveg (karaktersorozat) idézőjelben. A gép nem keres benne értelmet
  • Vagy mégis? \n: új sort kezd (ha idézőjelet szeretnénk kiírni, az \" lenne, hogy meg tudja a gép különböztetni a szöveg végét jelző idézőjeltől)
  • A printf()-nek adott szöveget, ún. paramétert zárójelbe (parenthesis) kell tenni
  • ; pontosvessző: utasítás vége

/* üdvözlet */ – megjegyzések

  • /* */: megjegyzés (comment)
  • A gép nem foglalkozik vele, magunknak írjuk
  • Olvashatóvá, követhetővé tehetjük a programot

return 0; – programrész vége

  • return: vége ennek a programrésznek
  • 0 itt azt jelenti, hogy rendben, hiba nélkül
  • később részletesen beszélünk majd erről

{ } – utasításblokk

  • { }: kapcsos zárójel (curly bracket, brace) utasításblokk eleje és vége
  • ezzel jelezzük, mettől meddig tart
  • jellegzetes C-s, rengeteg nyelv átvette

int main() – főprogram

  • main: a főprogram neve
  • később a programjainkat kisebb részekre bontjuk, most csak a főprogram van
  • int és (): ezekről is később lesz majd szó

#include <stdio.h> – előre megírt programrészek

#
kettőskereszt
hash mark
  • #include: beillesztjük
  • kacsacsőrök között
  • stdio.h: helyettünk megírt programrészek, amelyeket a C tartalmaz. Jelen esetben a kiírás: printf().

Előre megírt programrészek: nekünk nem kell vele foglalkozni, hogy mi lesz a kiírt betűkkel. Számunkra ez a program kimenete; hogy az hogyan jut el a képernyőig, az már nem a mi dolgunk.

24 A változók – létrehozás és értékadás

Definíció (létrehozás)

int x; // x egész

int a, b;
int kerulet, terulet;

Létrehozás: x egy egész szám.

  • A változóinknak nevet adunk, ezeknek betűvel kell kezdődniük, és nem lehet bennük ékezetes betű
  • Megmondjuk a gépnek a változó típusát és nevét, innen tudja a gép, hogy van egy új név, és hogy az mit jelent
  • int: egész szám neve C-ben (integer)

Használat

x = 3;   // x legyen 3
x = 2+3;

x = x+1; // x nőjön eggyel

Értékadás: x elfelejti régi értékét, és mostantól ezt tárolja.

x=5

x=x+1
x=5+1
x=6
  • = az értékadás művelet jele C-ben
  • x=x+1: nem egyenlet, hanem értékadás
  • „x legyen egyenlő x pillanatnyi értéke +1-gyel”

25 Szám kiírása és beolvasása

Kiírás

*
csillag
(asterisk)
int x;

x = 2*3;   /* szorzás */

printf("x: %d.\n", x); // !
x: 6.
  • *: szorzás jele
  • %d: egy egész számot szeretnénk kiírni
  • d, mert „decimális”, tízes számrendszerben
  • a %d helyére a változó értéke kerül, és úgy jelenik meg

Beolvasás

&
„et” vagy „és”
(ampersand)
int szam;

printf("Mennyi? ");

scanf("%d", &szam); // !
Mennyi? _
  • scanf(): beolvasás
  • "%d": egy egész számot
  • & kell a változó neve elé, ennek okáról majd részletesen lesz szó

Bár a printf() és a scanf() használata formailag szinte megegyezik, fontos észben tartani, hogy a printf() csak kiírni, a scanf() pedig csak beolvasni tud! Emiatt ez helytelen:

scanf("Mennyi? %d", &x);

26 Számológép

#include <stdio.h>

int main()
{
    /* kiszámolandó */
    
    printf("Eredmény: %d\n", 2*3);

    return 0;
}

Már van egy számológépünk C-ben: a „kiszámolandó” megjegyzéssel jelzett helyre bármilyen matematikai kifejezést beírhatunk (természetesen persze a C nyelvtani szabályainak megfelelően), és a program futtatása után megkapjuk az eredményt.

27 A C nyelv „erősen típusos”

változók használata
műveletegészvalós
létrehozásint n;double x;
kiírásprintf("%d", n);printf("%f", x);
beolvasásscanf("%d", &n);scanf("%lf", &x);

A típusos nyelvekben sok olyan részlet van a programkódban, ahol figyelnünk kell egy adott változónk típusára. Azon kívül, hogy egy valós szám típusát double-ként adjuk meg a C-ben, figyelnünk kell a kiírásnál és a beolvasásnál is: a printf() a valós, vagyis double típusú számhoz %f-et vár, míg a scanf() %lf-et. Vigyázni kell: nem biztos, hogy a gép figyelmeztet minket, ha ezeket rosszul használjuk!

Vannak nyelvek, amelyekben típus megadása nélkül használhatóak a változók. Azoknak persze nem az a célja, mint a C-nek, hogy számítógépközeli, gyors, jól optimalizálható programokat lehessen írni velük.

28 A kör kerülete és területe

Az első interaktív programunk, amely nem csak kiír valamit, hanem kérdez is a felhasználótól – sőt az eredmény a felhasználó által adott bemenő adattól függ.

pi=3.14;
a programban
tizedespont,
nem vessző!
#include <stdio.h>

int main()
{
    double sugar; // valós szám → double

    printf("Mennyi a kör sugara? ");
    scanf("%lf", &sugar);                    // scanf %lf

    printf("Kerülete: %f, területe: %f.\n",  // printf %f
           2*sugar*3.1416, sugar*sugar*3.1416);

    return 0;
}
Mennyi a kör sugara? 4.5
Kerülete: 28.274400, területe: 63.617400.

A kör sugarát a sugar nevű változóban tároltuk. Fontos, hogy mindig értelmes nevet adjunk a változónak, amely utal a szerepére. Ez megkönnyíti a programkód olvasását. Itt jó lett volna még az r név is, de az xx vagy az a1 nem igazán.

A programozás menete

30 Specifikáció, algoritmus, kód

A programozás részfeladatai

specifikáció
a feladat megfogalmazása
algoritmizálás
tervezés, a megoldás menetének kitalálása
kódolás
a megoldás leírása egy programozási nyelven
tesztelés, hibakeresés, dokumentálás

31 Specifikáció és algoritmizálás

Írjunk programot, amelyik kiszámítja egy téglalap kerületét és területét! A program kérdezze meg a két oldalhosszt a felhasználótól, és ezután írja ki az eredményt.

specifikáció

PROGRAM
  
  KIÍR: "Téglalap"
  KIÍR: "a="
  BEOLVAS: a
  KIÍR: "b="
  BEOLVAS: b
  
  KIÍR: "K=", 2·(a+b)
  KIÍR: "T=", a·b

PROGRAM VÉGE

algoritmus

Mi van az algoritmusban? „Az, amit kézzel is csinálnánk.” Vagyis azokat a lépéseket kell leírnunk pontosan, szabatosan, amelyek elvégzésével kialakul a várt eredmény – és amelyeket igazából papíron is végeznénk. Hogy mennyire részletesen kell leírnunk az algoritmust, az a programozási metodikától függ. Most egy imperatív nyelvről lesz szó az egész félévben, ezért kiírásokról, beolvasásokról, kifejezések kiértékeléséről, változókról, értékadásról beszélünk.

32 Algoritmus és kódolás



PROGRAM


  
  KIÍR: "Téglalap"
  KIÍR: "a="
  BEOLVAS: a
  KIÍR: "b="
  BEOLVAS: b
  
  KIÍR: "K=", 2·(a+b)
  KIÍR: "T=", a·b


PROGRAM VÉGE

algoritmus

#include <stdio.h>

int main()
{
  double a, b;
  
  printf("Téglalap\n");
  printf("a=");
  scanf("%lf", &a);
  printf("b=");
  scanf("%lf", &b);
  
  printf("K=%f, ", 2*(a+b));
  printf("T=%f\n", a*b);
  
  return 0;
}

C program

Miközben a programot a pszeudokódból írjuk át C nyelvűre, már tisztában kell lennünk a C nyelvi sajátosságokkal is. Pl. hogy jelezni kell előre a változókat, hogy a printf() végzi a kiírást, a scanf() a beolvasást stb. Tudnunk kell, hogy a 2*(a+b) kifejezés értéke is double, és ezért %f-t kell írni a kiíráshoz.

Az algoritmizálást és a kódolást különválasztva azonban leegyszerűsíthetjük a dolgunkat, hiszen egyszerre csak egy dologra kell figyelnünk. Az algoritmizálásnál az imperatív megoldás kitalálására, a kódolásnál pedig a használt programozási nyelv nyelvi sajátosságaira.

33 Mi történik a C programmal?


A fordítás menetéről később részletesen lesz szó. A fordítás azért előnyös, mert a gépi utasításokká alakítást csak egyszer kell megtenni, a program futása előtt. Futás közben már olyan formára van hozva a program, hogy azt a számítógép közvetlenül tudja használni, ezért az nagyon gyors tud lenni.

34 Tesztelés, hibakeresés, dokumentálás

Tesztelés, hibakeresés

Szintaktikai hiba (syntax error):
printf("K=%f, ", 2*(a+b);
printf("T=%f\n" a*b);

A nyelvtani szabályok szerint hibás.

Szemantikai hiba (semantic error):
printf("K=%f, ", a*b);
printf("T=%f\n", 2*(a+b));

Nem azt csinálja, amit kellene.

A szintaktikai hibát nevezik fordítási idejű hibának is (compile time error), hiszen már akkor kiderül, amikor a fordító a programunkat feldolgozza. A szemantikai hiba másik neve futási idejű hiba (runtime error), mert egy ilyen hatását már csak a program működése közben tapasztaljuk.


Dokumentálás

35 A Code::Blocks környezet

A félévben Code::Blocks fejlesztőkörnyezetet ajánljuk a Prog1 és a Szoftlab1 munkához. Ez megtalálható a HSZK-ban is. Ingyenes, elterjedt, gyors és könnyen használható alkalmazás, amellyel többféle programozási nyelven is lehet programokat fejleszteni – azaz megírni, tesztelni és nyomon követni, belső működést vizsgálva futtatni.