Labor, 2. hét: egyszerű programok

Pohl László, Czirkos Zoltán · 2018.08.27.

Egyszerű C programok lefordítása, futtatása. Bemenet és kimenet kezelése, egyszerű számítások és vezérlési szerkezetek.

Ezen az első laboron a Code::Blocks fejlesztőkörnyezet használatának alapjait ismerjük meg. Felkészülés a laborra:

1. Próba ZH

Ha még nem vitted föl a gyakorlaton írt próba ZH pontszámát, tedd meg!

2. A Code::Blocks fejlesztőkörnyezet

Az integrált fejlesztőkörnyezetek (integrated development environment, IDE) a programok fejlesztését – készítését, tesztelését, hibakeresését segítő programok. A C nyelv szabványos és elterjedt volta miatt rengeteg ilyen készült hozzá. A Prog1 tárgyban az ajánlott fejlesztőkörnyezet a Code::Blocks nevű, ingyenesen letölthető szoftver, ami megtalálható a HSzK gépein is.

Indítsd el a Code::Blocks programot! Válaszd ki a File menü New/Project… menüpontját! Az alábbi ábrákon látható módon folytasd a projekt létrehozását! Figyelj minden részletre!

  • A projekt típusának válaszd ki a Console application-t. Nyomd meg a Go gombot.
  • A következő oldalon a programozási nyelvet kell megadnod. Ez legyen a C.
  • Ezután arról érdeklődik a Code::Blocks, hogy mi legyen a projekt neve. Írd be, hogy „elso”. Alatta kell beállítanod azt a mappát, ahol a projekt fájlok tárolódnak. Ha ez üresen van hagyva, akkor válaszd ki a ... gombot megnyomva a Dokumentumok mappádat. (Jegyezd meg a mappa elérési útját!) Fontos: a projekt mappa neve, se elérési útja ne tartalmazzon se ékezetes betűket, se szóközt!
  • A negyedik ablakban a fordítóprogramot lehet megadni. Ha nem a „GNU GCC Compiler” van kiválasztva, akkor válaszd azt, továbbá ha a „Create "Debug" configuration” nem lenne beikszelve, akkor azt javítsd ki. De ezek így szoktak lenni.
  • Ezzel létre is jött a projekt. A bal oldalon, a „Management” résznél láthatóak a hozzá tartozó fájlok. A „Sources” mappát kinyitva megtalálod a fő programmodult, a main.c-t. Ebben egy helló világ program van. Fontos: a megadott mappanév ne tartalmazzon ékezetes betűket! Sok program ezeket nem szereti.

3. Helló Világ

A Code::Blocks eleve úgy hozta létre a projektet, hogy egy egyszerű helló világ programot tett bele. Ha másik fejlesztőkörnyezetet használsz, akkor másold be ezt a C programot (kettőt kattintva a kódra kijelölheted az egészet):

#include <stdio.h>

int main(void) {
    printf("Hello world!\n");
    return 0;
}

Figyeld meg a szövegszerkesztőben a kódot: ki van színezve. Mely szavak színesek? Vajon miért jó ez a szolgáltatás? Áttekinthetőbb a kód, segít észrevenni bizonyos elgépeléseket. Sok környezet az összetartozó zárójelpárokat is kiemeli.

A futtatható program

A fejlesztőkörnyezet által létrehozott saját program ugyanúgy működik, mint a többi parancssori alkalmazás: tartozik hozzá egy .exe fájl, és fájlba irányítható ennek is a kimenete. A programodat a „Build and run” (zöld play gomb + sárga fogaskerék) gombra kattintva indíthatod el, vagy a Build/Build and run menüpontot választva. Ilyenkor előbb lefordítja a gép, és aztán el is indítja. Ennek eredménye így kell kinézzen.

Keresd meg a lefordított programot a számítógépen! Ez valahol abban a mappában lesz, amelyiket kiválasztottad a projekt létrehozásánál. Keresd ezt meg a fájlkezelőben!

Tipp: ha nem emlékszel a mappa nevére, meg tudod keresni. A Code::Blocks az ablakának bal oldalán sorolja fel a projekthez rendelt fájlokat, a „Management/Project” sávon. Itt van a main.c nevű is. Jobb klikk, „Properties…”: a „File name (absolute)” résznél látod a fájl teljes elérési útját, mappákkal együtt:

  • C:\Documents and Settings\Név\Dokumentumok... – Windows XP.
  • C:\Users\Név\... – Windows 7-től fölfelé. (Vigyázat: nem User, hanem Users!)
  • /home/név/... – Linux.

Nyiss egy parancssori ablakot!

  • Windows 7: A Start menü Futtatás… parancsát választva indítsd el a cmd.exe programot!
  • Windows 10: Windows 10 esetén: a Start gombra jobb klikk, és Futtatás, vagy Windows + R után cmd.exe.

Navigálj el a projektedhez! Mappát váltani a cd paranccsal lehet, megadva neki a mappa nevét, amit az előbb megkerestél:

C:\> cd C:\Users\111111\projektem\

Írd be itt a dir parancsot, hogy lásd a fájlokat! Ott kell legyen például a main.c fájl is.

C:\Users\111111\projektem\> dir

Lépj be a bin\Debug mappába, és add ki újra a dir parancsot! Ott kell legyen a lefordított program, az elso.exe.

C:\Users\111111\projektem\> cd bin\Debug
C:\Users\111111\projektem\bin\Debug> dir

Indítsd el, a nevének beírásával:

C:\Users\111111\projektem\bin\Debug> elso.exe

A lefordított program egy fájl, amely tartalmazza azokat a számítógépnek szóló utasításokat, amelyek végül kiírják a kívánt szöveget; és még egy sor egyéb dolgot, amelyek az operációs rendszernek kellenek. Az ilyet futtathatónak szokás nevezni (vagy a szakzsargonban binárisnak, binary). Ilyen fájlokat tartalmaznak a programok telepítői is (installer). A lefordított program emberi fogyasztásra már alkalmatlan. Próbáld meg kiíratni a tartalmát a type elso.exe (Linuxon: cat elso) paranccsal, látni fogod.

4. Megoldások feltöltése

Az egész félév során feladat lesz az a laborban, hogy az elkészített megoldásokat a labor végén csomagold össze egy ZIP fájlba (nem 7ZIP, nem RAR!), és töltsd azt fel a portálra. Így neked is meglesz.

Ahogy fent már láttad, az adminisztrációs oldalon elérhető a feladatbeadó felület is. A kiírt feladatok közt fogod látni minden héten a laborfeladatoknak való helyet. Itt több fájlt kijelölve is megadhatod a .c programjaidat, vagy csomagolva egyszerre feltöltheted az egészet.

Arra ügyelj, hogy a becsomagolt ZIP-ben az EXE fájlok (azaz a projekthez tartozó bin mappa) ne legyenek benne! Ezeket a portál nem fogja engedni feltölteni. Legegyszerűbb ZIP-be csomagolás előtt törölni ezeket.

5. \n és %d

Indulj ki egy Helló, világ programból. Írd át így a programodban a kiírt szöveget:

printf("Hello\nworld\n\n!");

Mit tapasztalsz? És ha így írod át a szöveget, ékezetekkel?

printf("Helló világ!");

Sajnos Windowson az ékezetes betűket tartalmazó szövegek másképp jelennek meg egy menüs-grafikus programokban, mint a parancssorban. Ennek okáról majd lesz szó. Egyelőre egyszerűbb ékezet nélküli szöveget használni: Hello vilag!

Két \\ karaktert használva mit látsz?

printf("Hello world!\\n");

A visszaper \ speciális karakter az idézőjelek között megadott "szövegekben": ezzel kell megjelölni a fordítóprogram számára a különleges karaktereket, pl. a sortörést. Mivel így ennek a karakternek jelentése van, ha magát a visszapert \ szeretnénk a szövegben szerepeltetni, kétszer írjuk egymás után. Hasonló a helyzet a printf()-nél a százalék % karakter esetén, amely a változók helyeit jelöli meg; azzal a különbséggel, hogy a \-eket még a fordító dolgozza fel, a %-okat pedig már a program futása közben a printf(). Erről később részletesen lesz még szó.

Írd ki darabonként egyetlen printf() utasítással az alábbi szövegeket!

A printf("hello\n") kiirja, hogy "hello",
es kezd egy uj sort.
A "%d" segitsegevel egy valtozo erteket tudjuk kiirni.
Megoldás
#include <stdio.h>

int main(void) {
    printf("A printf(\"hello\\n\") kiirja, hogy \"hello\",\nes kezd egy uj sort.\n");
    printf("A \"%%d\" segitsegevel egy valtozo erteket\ntudjuk kiirni.\n");

    return 0;
}

6. A tartály

Tartály

Írj programot, amely segít kiszámolni a felhasználónak, hogy hány doboz festéket kell vennie a lábakon álló tartály festéséhez! Ehhez használnod kell majd az első előadásokon tanultakat. Indulj ki az előadáson bemutatott kör kerülete és területe programból!

A tartálynak ismerjük a magasságát és az átmérőjét. Mindenhol le kell festeni, az oldalát, a tetejét és az alját is. Tudjuk azt is, hogy egy doboz festék 2 m2 felület lefestéséhez elegendő.

Tartaly festese

Milyen magas? 2
Mennyi az atmeroje? 1.2

4.900885 doboz festek kell.

Figyelj arra, hogy a program kódjában tizedesvessző helyett tizedespontot kell használni (pl. 3.14), ugyanígy a bemenet megadásánál is. Ha nem jön ki a fenti eredmény, gondold át, helyes-e a képlet, amit használsz.

Megoldás
#include <stdio.h>

int main(void) {
    double atmero, magas;
    printf("Tartaly festese\n\n");
    printf("Milyen magas? ");
    scanf("%lf", &magas);
    printf("Mennyi az atmeroje? ");
    scanf("%lf", &atmero);

    double sugar = atmero/2;
    double doboz = (2*sugar*sugar*3.14159265 + magas*2*sugar*3.14159265) / 2;

    printf("\n%f doboz festek kell.\n", doboz);

    return 0;
}

Hasonló feladatok

Ha ez a feladat nehezen ment, megoldhatsz pár hasonló feladatot a példatárból, mielőtt a következő feladatra rátérsz.

Vigyázz, a laborfeladatokat erősen ajánlott az utolsó feladatig megoldani, hogy a jövő hétre felkészült legyél. Ha nem sikerül, fejezd be őket otthon!

7. Másodfokú egyenlet

Írj programot, amely az ax2+bx+c=0 másodfokú egyenlet együtthatóit kérdezi a felhasználótól, és kiírja az egyenlet x1 és x2 megoldását! A megoldóképlet:

Próbáld ki a bal oldalt látható egyenletekre! Ezekkel ellenőrizni tudod a megoldásod. Próbáld ki aztán a jobb oldali egyenletekre is. Mit tapasztalsz? Miért?

egyenletmegoldás
2x2-x-6=0x1=2, x2=-1.5
x2-12x+35=0x1=5, x2=7
egyenletmegoldás
x2-2x+1=0?
x2+2x+10=0?

Írd át úgy a programot, hogy figyelembe vegye azokat az eseteket, amikor nincs, vagy csak egy valós gyök van, és eszerint végezd a kiírást! Ehhez használnod kell az elágazásról tanultakat: lásd az előadást!

Megoldás

Arra kell figyelni, hogy ne vonj negatív számból négyzetgyököt. A gyökvonás előtt a diszkrimináns vizsgálatával meg kell nézni, hány valós megoldás lesz.

Itt egy nagyobb C kifejezést kapsz, amiben többféle operátor (összeadás, kivonás, szorzás stb.) szerepel. Ezeknek a műveleteknek C-ben ugyanúgy van precedenciája, mint a matematikában. A szorzás pl. magasabb rendű művelet, mint az összeadás. A C nyelv precedencia szabályai összetettebbek; erről majd előadáson lesz szó.

Az if (diszkr==0) vizsgálat elméletben helyes, gyakorlatban azonban nem előnyös ilyet írni. A kerekítési hibák miatt előfordulhat az, hogy 0-hoz olyan közeli szám adódik, amit már 0-ra kerekít a számítógép. Erről is később lesz szó előadáson.

#include <math.h >
#include <stdio.h>

int main(void) {
    double a, b, c;
    printf("a=");
    scanf("%lf", &a);
    printf("b=");
    scanf("%lf", &b);
    printf("c=");
    scanf("%lf", &c);

    /* a diszkriminans: b² - 4ac */
    double diszkr;
    diszkr = b * b - 4 * a * c;

    /* ha <0, 2 komplex gyok lenne */
    if (diszkr < 0) {
        printf("Nincs valos gyok!\n");
    }
    /* ha pont 0, akkor 1 megoldas van */
    if (diszkr == 0) {
        printf("Egy valos gyok: %f\n", -b / (2 * a));
    }
    /* >0, akkor 2 megoldas */
    if (diszkr > 0) {
        printf("Ket gyok: %f, %f\n",
               (-b + sqrt(diszkr)) / (2 * a),
               (-b - sqrt(diszkr)) / (2 * a));
    }

    return 0;
}

Hasonló feladatok

Ha ez a feladat nehezen ment, megoldhatsz pár hasonló feladatot a példatárból, mielőtt a következő feladatra rátérsz.

Vigyázz, a laborfeladatokat erősen ajánlott az utolsó feladatig megoldani, hogy a jövő hétre felkészült legyél. Ha nem sikerül, fejezd be őket otthon!

8. Számok kiírása

Az ábrán egy program pszeudokódja látható, amely kiírja a számokat 1-től 20-ig.

Gondolok egy számra, legyen ez 1.
Ismétlés, amíg a szám ≤ 20
    Leírom a számot.
    Új sort kezdek.
    Növelem a számot 1-gyel.
Ismétlés eddig

Írd meg ezt a programot C-ben az előadáson tanult while ciklussal!

Figyeld meg: ahogy gépeled be a while utáni { kapcsos zárójelet, az Enter billentyű hatására a gép egyből néhány szóközzel beljebb kezdi a sorokat. A bezáró } kapcsos után pedig újra kintebb. Használd ezt ki! Így áttekinthetőbb lesz a programod, jobban látszik a ciklus belseje. Ha elrontottad a formázást, a Code::Blocks automatikusan, utólag is képes rendbe tenni a kódot: ehhez kattints jobb gombbal a forráskódra, és válaszd az előugró menüből a „Format use Astyle” menüpontot.

Írd át a while ciklust for ciklusra!

Hasonló feladatok

Ha ez a feladat nehezen ment, megoldhatsz pár hasonló feladatot a példatárból, mielőtt a következő feladatra rátérsz.

9. Adott hosszúságú vonal

Írj egy programot, amely kér a felhasználótól egy számot, és kirajzol egy + és jelekből álló szakaszt. Pl. ha a szám 4, akkor a képernyőn a lenti ábra jelenjen meg, vagyis a belsejében 4 db legyen:

Mekkora legyen a szakasz? 4
+----+

Írd meg a program pszeudokódját, utána pedig gépen a C forráskódot! A pszeudokódot írhatod a fejlesztőkörnyezetbe megjegyzésként is, az egyes sorok alá odaírva a C nyelvű megfelelőjüket.

Tipp: ehhez a programhoz nem kell if elágazás. Ha olyan változatot írtál, amiben van, akkor próbáld meg anélkül is! Gondolj arra, hogy a szakasz elején és végén biztosan van +.

Megoldás
#include <stdio.h>

int main(void){
    int hossz;
    printf("Mekkora legyen a szakasz?\n");
    scanf("%d", &hossz);  /* Hossz beolvasása */

    printf("+");  /* A vonal elejére kell egy + jel */
    for (int i = 0; i < hossz; i = i+1)  /* Ciklus, ami kiír adott - jelet */
        printf("-");
    printf("+");  /* A vonal végére is kell egy + jel */

    return 0;
}

10. További feladatok

Ha elkészültél, folytasd a feladatgyűjtemény ehhez a témakörhöz kapcsolódó feladataival!