3. gyakorlat

Ismerkedés a bíróval

Két bíró rendszert különböztetünk meg:

Előfordulhat, hogy egy biztonsági kérdés érkezik először (mindkét bíró esetén)! Itt nem kell megijedni. Csak keressük meg a megjelenő oldalon, hogy hogyan kell elfogadni a feltételeket. Fogadjuk el, hogy tisztában vagyunk minden eshetőséggel és lépjünk tovább!

Ezután regisztráljunk mindkét bíró rendszerben:

Feladat (f0273)

Feladat:

Oldd meg a bíró rendszerben az alábbi feladatot. A feladat egy program megírása lesz, amely IO műveleteket is végez, de a bíró rendszer sajátosságai miatt a programot nem main, hanem main_p néven kell elkészítened! A bírótól kapott feladatkezdeményt kell kiegészítened!

Problémafelvetés:

Írj egy olyan C programot, ami kiírja, hogy "Hello, Progalap!"!

Specifikáció:

A programnak nincs inputja. A program outputja a "Hello, Progalap!" szöveg egy lezárt sorban.

Feladat (f0274)

Feladat:

Oldd meg a bíró rendszerben az alábbi feladatot. A feladat egy program megírása lesz, amely IO műveleteket is végez, de a bíró rendszer sajátosságai miatt a programot nem main, hanem main_i néven kell elkészítened! A bírótól kapott feladatkezdeményt kell kiegészítened!

Problémafelvetés:

Írj egy programot, ami bekér három egész számot, és kiírja az összegüket.

Specifikáció:

A program inputja három, whitespace karakterekkel elválasztott egész szám, az outputja pedig a három szám összege egy lezárt sorban.

Feladat (f0275)

Feladat:

Oldd meg a bíró rendszerben az alábbi feladatot. A feladat egy program megírása lesz, amely IO műveleteket is végez, de a bíró rendszer sajátosságai miatt a programot nem main, hanem main_v néven kell elkészítened! A bírótól kapott feladatkezdeményt kell kiegészítened!

Problémafelvetés:

Írj egy programot, ami bekér egy valós számot, és kiírja a négyzetét.

Specifikáció:

A program inputja egy valós szám. Az output alakja "X*X=Y" egy lezárt sorban, ahol X a beolvasott szám, Y pedig az X négyzete. Minden számot 4 tizedesjegy pontossággal kell kiíratni.

Függvények

Ahogyan a printf függvényt sem szeretnénk minden programunkban saját magunk megírni, úgy egy-egy jól körülhatárolt részfeladatot is érdemes egy-egy függvényben megoldani. Így ez a megoldás később újra felhasználható lesz és nem kell újra megírnunk ugyanazt a viselkedést.

Felmerülhet a kérdés, hogy miért nem egyszerűen csak átmásoljuk a sokszor használt kódrészletet? Nos, ez lehet egyszerűbbnek tűnik, de sok szempontból rossz megközelítés. Először is indokolatlanul megnöveljük a kódsorok számát, így átláthatatlanabb lesz a kódunk. Másodszor pedig képzeljük el, hogy hibát találunk az eredeti megvalósításban, ekkor az összes helyen, ahová azt bemásoltuk ki kellene javítani. Függvény esetén ezt csak egy helyen kell megtennünk.

Mielőtt továbbhaladsz, hasznos lehet elolvasni az előadásjegyzet függvényekről szóló részét.

Függvény deklaráció:

1
típus név( formális_paraméterek );

Függvény definíció:

1
2
3
típus név( formális_paraméterek ) {
    törzs
}

Példa függvények használatára:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>      

void nullParamVoid() {
    printf("Ez egy paraméter nélküli függvény, amelynek nincs visszatérési értéke.\n\n");
}

int nullParamInt() {
    printf("Ez egy paraméter nélküli függvény, amelynek 1 a visszatérési értéke.\n\n");
    return 1;
}

// Egy egyparaméteres fgv, ami kiszámítja egy négyzet kerületét az oldalhosszból
int negyzetKerulet(int a) {
    int kerulet;
    kerulet = 4 * a;
    return kerulet;
}

// Egy többparaméteres fgv, ami kiszámítja egy téglalap területét a két oldalhosszból
int teglalapTerulet(int a, int b) {
    return a * b;
}

int main() {
    // A main függvény allján lévő függvények hívása
    nullParamVoid();
    nullParamInt();
    printf("%d\n\n", negyzetKerulet(5));
    int terulet = teglalapTerulet(3, 4);
    printf("%d\n\n", terulet);
    return 0;
}

Feladat (f0012)

Feladat:

Írj egy függvényt, ami összead két egész értéket, és visszatér az eredménnyel! Írj egy főprogramot, ami bekér két egész számot, és a függvény segítségével kiírja az összegüket.

FŐPROGRAM:

Problémafelvetés:

Írj egy főprogramot, ami bekér két egész számot, és egy függvény segítségével kiírja az összegüket.

Specifikáció:

A főprogram inputja két, whitespace karakterekel elválasztott egész szám, az outputja pedig a függvény visszaadott értéke egy lezárt sorban.

RÉSZALGORITMUS (összeadó függvény):

Problémafelvetés:

Írj egy függvényt, ami összead két egész értéket, és visszatér az eredménnyel!

Specifikáció:

A függvénynek nincs sem inputja, sem outputja. A függvénynek két egész paramétere van, a visszatérési értéke pedig a két paraméter összege.

Lehetséges megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Gergely Tamás, 2015. őszi félév.
 *
 * Algoritmustervezés:
 *    A program két változóba bekér egy-egy egész számot, majd közvetlenül
 *    kiíratja az e két számra alkalmazott függvény visszatérési értékét.
 *
 * fordítás:
 *    gcc -Wall -o m0012 m0012.c
 *
 * futtatás:
 *    ./m0012
 */

#include <stdio.h>

int add(int p1, int p2) {
    return p1 + p2;
}

int main() {
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", add(a, b));
    return 0;
}
m0012.c

Videók a függvényekről:

functions 1

functions 2

functions 3

Feladat (f0020)

Problémafelvetés:

Írj egy programot ami a sugárból kiszámítja egy kör kerületét és területét!

Specifikáció:

A program inputja egyetlen nemnegatív valós szám, a kör sugara. A program outputja két sor. Az elsőben a "T = " szöveg után a kör területe, a második sorban a "K = " szöveg után a kör kerülete szerepel. Mindkét számot 10 karakteren jobbra igazítva 3 tizedesjegy pontossággal kell kiíratni. A beolvasás előtt a program elején ki kell írni egy rövid tájékoztatót arról, hogy a program milyen adatot kér be.

Megvalósítás:

A \(\pi\) értékét beírhatjuk közvetlenül mindenhová, ahol használni kell, vagy deklarálhatunk egy globális változót, amit \(\pi\) értékére inicializálunk, de érdemesebb a math.h-ban definiált konstanst felhasználni. Ehhez a C program elejére be kell szúrni az

1
#include <math.h>

sort. Ezután a programban használható az M_PI azonosító, ami a \(\pi\) értékét fogja jelenteni.

Lehetséges megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <math.h>

double area(double r) {
    return r * r * M_PI;
}

double perimeter(double r) {
    return 2.0 * r * M_PI;
}

int main() {
    double r = 0.0;
    printf("Adja meg a kör sugarát!\n");
    scanf("%lf", &r);

    printf("T = %10.3lf\n", area(r));
    printf("K = %10.3lf\n", perimeter(r));

    return 0;
}
m0020.c

Vezérlési szerkezetek

Az if utasítás segítségével valamely tevékenység (utasítás) végrehajtását egy kifejezés (feltétel) értékétől tehetjük függővé. Az if alábbi formájában az utasítás csak akkor hajtódik végre, ha a kifejezés értéke igaz (nem nulla):

1
2
3
if (kifejezés) {
    utasítás
}

A zárójelben lévő kifejezés egy logikai kifejezést takar. Ezt a program a szelekciós vezérlőszerkezet végrehajtásakor kiértékeli, és a kiértékelés eredménye vagy igaz vagy hamis érték. Egy logikai kifejezés logikai változókból/értékekből és logikai operátorokból állhat. A C nyelvben a \(C^{99}\) óta létezik a _Bool logikai típus, de egész típusokban (int, char) is tárolhatunk logikai értékeket. A 0 egész érték hamis, a nem nulla pedig igaz logikai értéket jelent. Ha egy C-s művelet eredménye logikai érték, annak eredménye vagy 0 (hamis) vagy 1 (igaz) lehet.

Az if szerkezetről ad segítséget a követekző videó is:

if

Az if-else szerkezet használatával arra az esetre is megadhatunk egy tevékenységet, amikor a kifejezés (feltétel) értéke hamis (zérus):

1
2
3
4
5
if (kifejezés) {
    utasítás
} else {
    utasítás
}

Az if-else szerkezetről ad segítséget a követekző videó is:

if

Az else-if szerkezet nem más, mint egymásba ágyazott if utasítások egy gyakran használt formája, amikor az else ágakban szerepel az újabb if utasítás:

1
2
3
4
5
6
7
8
9
if (kifejezés) {
    utasítás
} else if (kifejezés) {
    utasítás
} else if (kifejezés) {
    utasítás
} else {
    utasítás
}

Az else-if szerkezetről ad segítséget a követekző videó is:

if

Relációs operátorok:

a és b értékek: változók, konstansok, valamilyen művelet vagy függvény eredményei, vagy literálok (literálnak nevezzük a helyben definiált adatot, pl. 5, vagy 'A')

  • a == b - a egyenlő-e b-vel. Az egyenlőség eldöntése tehát az == művelet, és nem összetévesztendő az értékadás művelettel (=)!
  • a < b - a kisebb-e b-nél
  • a > b - a nagyobb-e b-nél
  • a <= b - a kisebb-egyenlő-e b-nél
  • a >= b - a nagyobb-egyenlő-e b-nél
  • a != b - a nem egyenlő-e b-vel

Logikai operátorok:

a és b logikai értékek: változók, konstansok, valamilyen művelet vagy függvény eredményei, vagy literálok

  • !a - a kifejezés értéke NEM a, tehát akkor lesz igaz, ha a hamis volt.
  • a && b - a kifejezés értéke a ÉS b, tehát akkor lesz igaz, ha a és b is igaz volt.
  • a || b - a kifejezés értéke a VAGY b, tehát akkor lesz igaz, ha a és b közül legalább az egyik igaz volt.

Természetesen több logikai értéket is összeláncolhatunk az && és || operátorokkal.

1
2
3
4
5
6
7
int a = 0;
int b = 1;
int c = 42;

(a < b) && (c == 42) && !a;   // igaz && igaz && igaz => igaz
a && b && c;                  // hamis => hamis
a || b || c;                  // hamis || igaz => igaz

A fenti példák magyarázatánál látszik a C egyik érdekessége, az úgynevezett rövidített kiértékelés. Az 5. sorban lévő kifejezést végig kiértékeljük, mind a 3 tényezőjét, ezek mind igazak lesznek, tehát a végeredmény is igaz. A 6. sorban lévő kifejezés esetében a program futása során elegendő az első tényező, az a változó értékét megvizsgálni, hiszen ha egy logikai konjunkció ("éselés") valamelyik tagja hamis, akkor a végeredmény is az. A C pontosan ezt csinálja, a további tényezőkkel nem foglalkozik. A 7. sorban lévő kifejezésnél az a változó mellett a b értékét is megvizsgáljuk, de a c-t már nem, hiszen ha diszjunkcióban ("vagyolás") valamely tag igaz, akkor a végeredmény is igaz. A kiértékelés balról jobbra történik.

A logikai operátorok használatát mutatja be a következő videó:

Logikai operátorok

Feladat (f0055)

Problémafelvetés:

Készíts egy programot, ami bekér egy egész számot és kiírja, hogy az adott szám páros vagy páratlan-e.

Specifikáció:

A program inputja egyetlen egész szám. A program outputja egyetlen sor, melyben a "A megadott szám páros." illetve "A megadott szám páratlan." szöveg szerepel, ha a beolvasott szám páros illetve páratlan. A program a bekérés előtt tájékoztatja a felhasználót arról, hogy milyen inputot vár.

Megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program bekér egy egész számot, majd ennek kettővel osztva adott
 *    maradéka alapján kiírja a megfelelő szöveget.
 *
 * Megvalósítás:
 *    C nyelvben az if() { } else { } szerkezet használható arra, hogy egy
 *    feltétel függvényében hajtsunk, vagy éppen ne hajtsunk végre
 *    utasításokat.
 *
 * fordítás:
 *    gcc -o m0055 m0055.c
 *
 * futtatás:
 *    ./m0055
 */

#include <stdio.h>

int main() {
    int n;
    printf("Kérek egy egész számot:");
    scanf("%d", &n);
    if (n % 2 == 0) {
        printf("A megadott szám páros.\n");
    } else {
        printf("A megadott szám páratlan.\n");
    }
    return 0;
}
m0055.c

Feladat (f0271)

Feladat:

Oldd meg a bíró rendszerben az alábbi feladatot. A feladat egy függvény megírása lesz. Az IO műveletekkel nem kell foglalkoznod, azt a bírótól kapott feladatkezdemény más részei megoldják, csak a függvényt kell elkészíteni, és feltölteni a bíróra ellenőrzés céljából.

Problémafelvetés:

Készíts egy függvényt, ami a paraméterben kapott számról megállapítja, hogy az adott szám páros vagy páratlan-e.

Specifikáció:

A függvény inputja egyetlen egész szám, amelyet paraméterben kap. A függvény outputja a visszatérési értéke, amely legyen 1, ha a szám páros, minden egyéb esetben pedig legyen 0. A függvény nem végez IO műveleteket!

Feladat (f0056)

Problémafelvetés:

Készíts egy programot, ami bekér két pozitív egész számot és írja ki, hogy az első szám osztható-e a másodikkal.

Specifikáció:

A program inputja két pozitív egész szám, M és N. A program outputja egyetlen sor, melyben az "M osztója N-nek." illetve "M nem osztója N-nek." szöveg szerepel a két szám oszthatóságának függvényében. A program a két számot külön-külön tájékoztatás után kérje be.

Megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program begér két egész számot, az elsőt osztja a másodikkal, majd a
 *    maradék alapján kiírja a megfelelő szöveget.
 *
 * fordítás:
 *    gcc -o $BASENAME$ $FILENAME$
 *
 * futtatás:
 *    ./$BASENAME$
 */

#include <stdio.h>

int main() {
    int m, n;
    printf("Kérem az osztandót (pozitív egész szám):");
    scanf("%d", &m);
    printf("Kérem az osztót (pozitív egész szám):");
    scanf("%d", &n);
    if (m % n != 0) {
        printf("%d nem osztója %d-nek.\n", n, m);
    } else {
        printf("%d osztója %d-nek.\n", n, m);
    }
    return 0;
}
m0056.c

Feladat (f0057)

Problémafelvetés:

Készíts egy programot, ami bekér két természetes számot és írja ki, hogy az első szám osztható-e a másodikkal. A nullával osztás nem megengedett, ezt külön jelezze.

Specifikáció:

A program inputja két nemnegatív egész szám, M és N. A program outputja egyetlen sor, melyben a "Nullával nem osztunk!", "M osztója N-nek." illetve "M nem osztója N-nek." szöveg szerepel a két szám oszthatóságának függvényében. A program a két számot külön-külön tájékoztatás után kérje be.

Megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program bekér két egész számot, és először ellenőrzi, hogy az osztás
 *    elvégezhető-e. Ha igen, akkor elvégzi az osztást és a maradék alapján
 *    kiírja a megfelelő szöveget, ha nem, akkor kiírja a nullával osztáshoz
 *    tartozó szöveget.
 *
 * fordítás:
 *    gcc -o m0057 m0057.c
 *
 * futtatás:
 *    ./m0057
 */

#include <stdio.h>

int main() {
    int m, n;
    printf("Kérek egy egész számot:");
    scanf("%d", &m);
    printf("Kérek egy másik egész számot:");
    scanf("%d", &n);
    if (n != 0) {
        if (m % n != 0) {
            printf("%d nem osztója %d-nek.\n", n, m);
        } else {
            printf("%d osztója %d-nek.\n", n, m);
        }
    } else {
        printf("Nullával nem osztunk!\n");
    }
    return 0;
}
m0057.c

Feladat

Oldd meg az előző feladatot többszörös szelekció (else-if szerkezet) használatával!

Feltételes kifejezések

Az if-else helyett feltételes kifejezések is használhatók. Ezzel tömörebb formában fogalmazható meg ugyanaz, sőt, egy adott helyre behelyettesítendő érték kiválasztására is használható.

1
feltetel ? muvelet_ha_igaz : muvelet_ha_hamis;

Feladat (f0060)

Problémafelvetés:

Írjuk ki egyetlen printf segítségével, hogy egy szám páros vagy páratlan-e.

Specifikáció:

A program inputja egyetlen egész szám. A program outputja egyetlen sor, melyben a "A megadott szám páros." illetve "A megadott szám páratlan." szöveg szerepel, ha a beolvasott szám páros illetve páratlan. A program a bekérés előtt tájékoztatja a felhasználót arról, hogy milyen inputot vár.

Megvalósítás:

A programban a beolvasás előtti tájékoztatást nem számítva egyetlen printf() függvényhívás szerepelhet.

Megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Megvalósítás:
 *    C nyelvben a ? : feltételes kifejezés tulajdonképpen egy kifejezésen
 *    belüli if-else -et valósít meg. A kifejezés eredménye a feltétel
 *    értékétől függően az egyik vagy a másik kifejezés lesz.
 *
 * fordítás:
 *    gcc -o $BASENAME$ $FILENAME$
 *
 * futtatás:
 *    ./$BASENAME$
 */

#include <stdio.h>

int main() {
    int n;
    printf("Kérek egy egész számot: ");
    scanf("%d", &n);
    printf("A megadott szám %s.\n", (n % 2 == 0) ? "páros" : "páratlan");
    return 0;
}
m0060.c

Feladat (f0061)

Problémafelvetés:

Írjuk ki egyetlen printf használatával, hogy egy szám osztója-e egy másiknak. A 0 semminek sem osztója.

Specifikáció:

A program inputja egyetlen egész szám. A program outputja egyetlen sor, melyben az "M osztója N-nek." illetve "M nem osztója N-nek." szöveg szerepel. A program a két számot külön-külön tájékoztatás után kérje be.

Megvalósítás:

A programban a beolvasás előtti tájékoztatást nem számítva egyetlen printf() függvényhívás szerepelhet.

Megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * fordítás:
 *    gcc -o $BASENAME$ $FILENAME$
 *
 * futtatás:
 *    ./$BASENAME$
 */


#include <stdio.h>

int main () {
    int m, n;
    printf("Kérek egy egész számot:");
    scanf("%d", &m);
    printf("Kérek egy másik egész számot:");
    scanf("%d", &n);
    printf("%d%s osztója %d-nek.\n", n, (n != 0 && m % n == 0) ? "" : " nem", m);
    return 0;
}
m0061.c

Megjegyzés

A feltételes kifejezéseket egymásba is ágyazhatjuk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

int main () {
    int x;

    printf("Kérek egy egész számot: ");
    scanf("%d", &x);
    printf("Kérek egy másik számot: ");
    scanf("%d", &y);

    printf("Osztoja-e %d-nek %d?. %s\n", x, y,
        // %s helyére string-ek, azaz karaktersorozatok helyettesíthetők be,
        // így pl. bármilyen szöveg "" között megadva.
            (y == 0) ? "A kerdes ertelmetlen!" :    // tehát leellenőrizzük, hogy y nulla-e,
                                                    // ha igen, akkor kiírjuk, hogy értelmetlen, 
                    ((x % y == 0) ? "Igen, osztója." : "Nem, nem osztója.")
                                                    // ellenkező esetben, pedig az x és y oszthatóságától
                                                    // függően kerül kiírásra az 1. avagy a 2. állítás
    );
}

A fenti példa működő kód. Azonban a feltételes kifejezések egymásba ágyazása rontja a kód olvashatóságát, így nem ajánlott túl sokat egymásba ágyazni. (Átalában is igaz, hogy a túl tömör írásmód az olvashatóság rovására megy.)

Esetkiválasztásos szelekciós vezérlés

A switch utasítás többirányú programelágaztatást tesz lehetővé olyan esetekben, amikor egy egész kifejezés értékét több konstans értékkel kell összehasonlítanuk. Az utasítás álatlános alakja:

1
2
3
4
5
6
7
switch ( kifejezés ) {
    case címke : műveletek; break;
    case címke : műveletek; break;
        ...
    case címke : műveletek; break;
    default : műveletek; break;
}

A switch utasítás először kiértékeli a kifejezést, majd átadja a vezérlést arra a case címkére (esetre), amelyben a címke értéke megegyezik a kiértékelt kifejezés értékével - a futás ettől a ponttól folytatódik. Amennyiben egyik case sem egyezik meg a kifejezés értékével, a program futása a default címkével megjelölt utasítással folytatódik. Ha nem használunk default címkét, akkor a vezérlés a switch utasítás blokkját záró } utáni utasításra adódik. A break utasítás kiugrasztja a switch-ből a vezérlést, ha kihagyjuk, az a következő címkére kerül. Ez használható pl. olyankor, ha több címkéhez ugyanazokat a műveleteket kell végrehajtani.

A switch utasítást mutatja be a következő videó:

switch

Feladat (f0062)

Problémafelvetés:

Írj egy progamot, ami egy egész számot kap inputként és kiírja a hét ezen sorszámú napjának nevét. A nap kiírására készíts függvényt, melynek paramétere a nap sorszáma. A program jelezze, ha rossz az input.

Specifikáció:

A program inputja egy egész szám. A program outputja a hét megfelelő napjának neve, vagy a "Nincs ilyen nap." szöveg.

Algoritmustervezés:

A főprogram csak a beolvasásért felel, a függvény pedig a kiíratásért.

FŐPROGRAM:

Problémafelvetés:

Írj egy progamot, ami beolvas egy egész számot, majd meghívja a függvényt a megfelelő paraméterrel.

Specifikáció:

A program inputja egy egész szám, közvetlen outputja egy tájékoztatás a szám beolvasása előtt.

FÜGGVÉNY:

Problémafelvetés:

Írj egy függvényt, amely kap egy egész számot, majd kiírja, hogy ez a hét hányadik napja, vagy hogy "Nincs ilyen nap.".

Specifikáció:

A függvénynek nincs inputja, paramétere egyetlen \(N\) egész szám. A függvény kimenete egyetlen sor, a hét \(N\)-ik napjának neve, vagy a "Nincs ilyen nap." szöveg. A függvénynek nincs visszatérési értéke.

Megoldás
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

void hetnapja (int h) {
    if (h == 1) {
        printf("Hétfő\n");
    } else if (h == 2) {
        printf("Kedd\n");
    } else if (h == 3) {
        printf("Szerda\n");
    } else if (h == 4) {
        printf("Csütörtök\n");
    } else if (h == 5) {
        printf("Péntek\n");
    } else if (h == 6) {
        printf("Szombat\n");
    } else if (h == 7) {
        printf("Vasárnap\n");
    } else {
        printf("Nincs ilyen nap.\n");
    }
}

int main () {
    int h;
    printf("Kérek egy egész számot: ");
    scanf("%d", &h);
    hetnapja(h);
    return 0;
}

Feladat

Készítsd el a fenti feladatot switch használatával is (ha nem azzal csináltad)!

Megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Megvalósítás:
 *    A feladat megvalósítható lenne else if használatával, de mivel minden
 *    feltétel ugyanolyan alakú, és egy kifejezést (ami most egy változó)
 *    hasonlít egy egész értékhez, célszerűbb a switch() használata.
 *
 * fordítás:
 *    gcc -o $BASENAME$ $FILENAME$
 *
 * futtatás:
 *    ./$BASENAME$
 */

#include <stdio.h>

void hetnapja (int h) {
    switch (h) {
      case 1: 
        printf("Hétfő\n");
        break;
      case 2:
        printf("Kedd\n");
        break;
      case 3:
        printf("Szerda\n");
        break;
      case 4:
        printf("Csütörtök\n");
        break;
      case 5:
        printf("Péntek\n");
        break;
      case 6:
        printf("Szombat\n");
        break;
      case 7:
        printf("Vasárnap\n");
        break;
      default:
        printf("Nincs ilyen nap.\n");
        break;
    }
}

int main () {
    int h;
    printf("Kérek egy egész számot: ");
    scanf("%d", &h);
    hetnapja(h);
    return 0;
}
m0062.c

Kezdőfeltételes ismétléses vezérlés

Más néven előltesztelős ciklus, vagy while-ciklus.

A while ciklus mindaddig ismétli a hozzá tartozó utasítást (a ciklus törzsét), amíg a vizsgált kifejezés (vezérlőfeltétel) értéke igaz (nem nulla). A vizsgálat mindig megelőzi az utasítás végrehajtását. Általános alakja:

1
2
3
while (kifejezés){
    utasítás
}

Tehát, ha a kifejezés értéke már kezdetben is hamis, akkor a while ciklus törzsén belül elhelyezkedő utasítás(ok) egyszer sem fut(nak) le.

A switch-nél látott break utasítás ciklusokból való "kitörésre" is alkalmazható. Így írhatunk olyan (esetleg egyébként végtelen) ciklust, amelyben egy, vagy több helyen egy if segítségével megvizsgálunk egy feltételt, majd az alapján (esetleg néhány művelet végrehajtása után) kilépünk a ciklusból. Ezt hívjuk hurok ismétléses vezérlésnek lásd előadás anyag.

A while utasítást mutatja be a következő videó:

while

Feladat

Írjunk egy programot, ami kiírja 1-től 10-ig számokat!

Megoldás
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>

int main() {
    int i = 1;
    while (i <= 10) { // Tehát addig fog futni a ciklus, amíg az i értéke kisebb vagy egyenlő, mint 10.
        printf("%d\n", i);
        i = i + 1;    // FONTOS! Ne felejtsük el növelni az i értékét, különben végtelen ciklust kapunk.
    }
    return 0;
}

Feladat

Írjunk olyan programot, ami addig kér be számokat a billentyűzetről, amíg a beírt szám nem 0! (0 az adott végjel)!

Feladat

Módosítsuk a programot úgy, hogy végeredményként írja ki a beírt számok összegét!

Végfeltételes ismétléses vezérlés

Más néven hátultesztelős ciklus, vagy do-while-ciklus.

A do-while utasításban a ciklus törzsét képező utasítás végrehajtása után kerül sor a tesztelésre. Így a ciklus törzse legalább egyszer mindig végrehajtódik. Általános alakja:

1
2
3
do {
    utasitas
} while (kifejezés);

A do-while ciklus futása során mindig először végrehajtódik az utasítás és ezt követően értékelődik ki a kifejezés. Amennyiben a kifejezés értéke igaz (nem nulla), akkor új iteráció kezdődik (azaz újra lefut a ciklus), míg hamis (0) érték esetén a ciklus befejezi működését.

do while

Feladat

Írjunk egy olyan programot do-while ciklus segítségével, ami 0 végjelig kér be számokat, majd kírja azok összegét. A ciklusban ne szerepeljen a break utasítás.

Megoldás
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <stdio.h>

int main() {
    int x, osszeg=0;

    do {
        printf("Kérek egy számot (kilépéshez: 0):");
        scanf("%d", &x);
        osszeg += x;
    } while (x != 0);   // tehát mindig a ciklus végén történik az ellenőrzés

    printf("A számok összege: %d\n", osszeg);
    return 0;
}

Feladat (f0066)

Feladat:

Az osszeg-while.c és osszeg-do-while.c programok feladata egy 0 végű egész számsorozat összegének kiszámítása. Mik a programok hibái? Hogyan és miért működnek rosszul ha összeg helyett szorzatot kell számolniuk?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 */

#include <stdio.h>

int main() {
    int x;
    int osszeg = 0;
    while (x != 0) {
        scanf("%d", &x);
        osszeg += x;
    }
    printf("%d\n", osszeg);
    return 0;
}
osszeg-while.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 */

#include <stdio.h>

int main() {
    int x;
    int osszeg = 0;
    do {
        scanf("%d", &x);
        osszeg += x;
    } while (x != 0);
    printf("%d\n", osszeg);
    return 0;
}
osszeg-do-while.c

Számlálásos ismétléses vezérlés

Más néven for-ciklus.

A for utasítást átlagban akkor használjuk, ha a ciklusmagban megadott utasítást adott számszor kívánjuk végrehajtani. Általános alakja:

1
2
3
for (kezdőérték_kifejezés ; feltétel_kifejezés ; léptető_kifejezés){
    utasítás
}

A ciklusban van egy változó (a ciklusváltozó, vagy számláló), amit egy kezdőértékből kiindulva, folyamatosan növelünk vagy csökkentünk egy végértékig, és minden ilyen körben végrehajtunk néhány műveletet. A műveletekben a ciklusváltozó aktuális értéke is felhasználható.

A kezdőérték_kifejezés-sel állítjuk be a ciklusváltozó kezdőértékét. A léptető_kifejezés-sel növeljük vagy csökkentjük a ciklusváltozó értékét tetszés szerint. A feltétel_kifejezés-t pedig minden egyes iterációban ellenőrizzük. A ciklus addig fut amíg ez a feltétel teljesül. Mivel a feltételünk akkor nem fog már teljesülni, amikor a ciklusváltozó elér egy bizonyos értéket, ezért jól befolyásolható, hogy a ciklus hányszor fusson le.

A ciklus változó növelésére (inkrementálására) és csökkentésére (dekrementálására) létezik egy-egy speciális operátor:

  • Az A++; utasítás megegyezik az A = A + 1 (vagy A += 1;) utasítással.
  • Az A--; utasítás megegyezik az A = A - 1 (vagy A -= 1;) utasítással.

A ++ és -- műveletek pre- és postfix alakban is használhatók.

  • A postfix alak esetén a B = A++; utasítás megegyezik a B = A; A = A + 1; utasítás-sorozattal.
  • A postfix alak esetén a B = A--; utasítás megegyezik a B = A; A = A - 1; utasítás-sorozattal.
  • A prefix alak esetén a B = ++A; utasítás megegyezik a A = A + 1; B = A; utasítás-sorozattal.
  • A prefix alak esetén a B = --A; utasítás megegyezik a A = A - 1; B = A; utasítás-sorozattal.

A for ciklus használatát mutatja be a következő videó:

for

Feladat

Írjunk egy programot, ami összeszorozza 1-től 10-ig számokat!

Megoldás
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <stdio.h>

int main() {
    int i;
    int szorzat;
    // több kezdő érték illetve léptető kifejezés is megadható vesszővel elválasztva
    for (i = 1, szorzat = 1; i <= 10; ++i) {    // tehát i=1 miatt 1-től indul a számlálás és
                                                // egész addig tart amíg i el nem éri a 10-es
                                                // értéket, az i <= 10 miatt
        szorzat *= i;       // és minden egyes körben képezzük az szorzatot az adott i-vel (1*2*3*...*10)
    }

    printf("A számok szorzata: %d\n", szorzat);
    return 0;
}

Feladat

Módosítsuk a for ciklust úgy, hogy csak minden 3-mal osztható számot szorozzon össze!

Megoldás
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <stdio.h>

int main() {
    int i;
    int szorzat;

    for (i = 3, szorzat = 1; i <= 10; i += 3) {  // csak annyit kell tennünk, hogy az i értékét nem 1-gyel,
                                                 // hanem 3-mal növeljük minden egyes körben 3-tól indítva
        szorzat *= i;                            // mivel 3 ugyebár osztható 3-mal, ezért ha mindig 3-mal nő i,
                                                 // így mindig a 3-mal osztható számokat kapjuk,
    }                                            // egész a végfeltételig (jelen esetben 10-ig)
    printf("A számok szorzata: %d\n", szorzat);
    return 0;
}

Feladat (f0270)

Feladat:

Oldd meg a bíró rendszerben az alábbi feladatot. A feladat egy függvény megírása lesz. Az IO műveletekkel nem kell foglalkoznod, azt a bírótól kapott feladatkezdemény más részei megoldják, csak a függvényt kell elkészíteni, és feltölteni a bíróra ellenőrzés céljából.

Problémafelvetés:

Készíts egy függvényt, ami kiszámítja a paraméterben kapott egész számnál kisebb páratlan pozitív egész számok összegét.

Specifikáció:

A függvény egyetlen paramétere a kérdéses szám, amelyről meg kell mondani, hogy mennyi a nála kisebb páratlan pozitív egész számok összege. A függvény visszatérési értéke ez az összeg. A függvény nem végez IO műveleteket!

Feladat (f0272)

Feladat:

Oldd meg a bíró rendszerben az alábbi feladatot. A feladat egy függvény megírása lesz. Az IO műveletekkel nem kell foglalkoznod, azt a bírótól kapott feladatkezdemény más részei megoldják, csak a függvényt kell elkészíteni, és feltölteni a bíróra ellenőrzés céljából.

Problémafelvetés:

Készíts egy függvényt, ami a paraméterben kapott pozitív egész számról megállapítja, hogy az adott szám prím-e.

Specifikáció:

A függvény inputja egyetlen egész szám, amelyet paraméterben kap. A függvény outputja a visszatérési értéke, amely legyen 1, ha a szám prím, minden egyéb esetben pedig legyen 0. A függvény nem végez IO műveleteket!

Feladat

Próbáljuk ki mit csinál az alábbi for ciklus!

1
2
3
int i, j, output;
for (i = 1, j = 100, output = 0; i <= 10; i++, j--)
    output+=i*j;

Feladat

Módosítsuk a ciklusmagot úgy, hogy egy printf segítségével kiírjuk az i, j és out aktuális értékét.

Jövőheti ZH

Jövő héten 1. ZH

Téma:

  • C programozás (ezután mindig az lesz): 2. gyakorlat anyaga.

Gyakorlásra:

  • A honlapon a 2. gyakorlathoz tartozó anyag, magyarázatokkal, példákkal.
  • További feladatok találhatóak a PUB-ban. (/n/pub/ProgramozasAlapjai/Gyakorlat/ - átfedés lehet az "itt" és "ott" található feladatok között).
  • Jelmondat: "Nézegetéssel nem lehet programozni tanulni, csak gyakorlással!"

Összegzésként:

  • Tudni kellene C programot fordítani és futtatni. ( gcc -o vmi vmi.c ÉS ./vmi )
  • Létrehozni változókat. ( int, char, float, double )
  • Beolvasni adatot. ( scanf )
  • Kiíratni adatot. ( printf )
  • Visszatérési értékekre ügyelni. ( return )
  • Csak azt programozzuk le amit a feladat kér, se többet, se kevesebbet. Pl. ha sortörést kér, teszünk sortörést, ha nem írja, hogy ki kellene írni valamit a képernyőre, nem íratunk ki semmit, stb.
  • Az itt felsoroltakra a további ZH-kon is mind szükség lesz.

Egyéb infó:

  • Előreláthatóan 30 percetek lesz a feladatok megoldására és beadására
  • A feladatokat a bíró rendszeren keresztül fogjátok megkapni és beadni is, és az értékelést is a bíró fogja csinálni ott helyben. Tehát egyből látni fogjátok a pontszámokat amiket a bíró adott.
  • Limitált a feltöltések száma és mindig a legjobb pontszám fog számítani.
  • Aki késik, az is csak a fenti időintervallum alatt írhatja a ZH-t, mivel a bíró rendszer nyit, majd automatikusan zár is.
  • Hiányozni csak igazolással lehet, de a ZH akkor sem pótolható!
Tanácsok zh íráshoz - alapul véve az eddig megírt zh-kban leledző hibákat
  • Nem megfelelő a fájl kiterjesztése
    • (A fájl kiterjesztése mindig legyen .c - feladat.c, main.c, macska.c. Több pont ne szerepeljen a fájlnévben, a feladat.1.c például nem jó, mert a bíró 1.c kiterjesztést fog érzékelni.)
  • Rossz fájlt töltünk fel bíróra
    • (Feltöltés előtt érdemes megnézni, hogy jó mappában vagyunk-e,illetve ha gombra kattintós-kiválasztós módon csináljuk, akkor nézzük meg a dátumot is, hogy mikor szerkesztettük utoljára.)
  • Feltöltjük a kezdeti fájlt.
    • (Lásd előző pont: jó fájlt kell feltölteni.)
  • Fordítási hiba van a fájlban
    • (Érdemes legalább lefordítani feltöltés előtt. Kb. 5 mp az egész. CodeLite-ban Ctrl+F5, egyébként gcc programneve.c -o programneve. Ezután a fordító ki fogja írni, hogy mi a problémája, sorszámmal együtt, hogy "nézd itt a hiba, tegyél már ide egy pontosvesszőt" - ha kijavítunk egy ilyet, akkor fordítsuk megint, és javítsuk a következőt. Amíg error-t ír (codeliteban: piros szöveg) a fordító, addig a bíró is 0 pontot fog rá adni.)
  • A bíró 0 pontot ad a megoldásra, de nem nézzük meg, hogy mi a gond.
    • (Nézzük meg. Kattintsunk az X. próbához tartozó riport.txt linkre. Ha mindegyiknél hibás válasz van, akkor tudjuk, hogy legalább lefordult, csak rosszul működik a programunk. Ha azt írja, hogy fordítási hiba, akkor nem tudta lefordítani. Ilyenkor fordítsuk le a gépünkön, mert azt elfelejtettük. Ha valamiért ezt nem tudjuk megtenni, akkor a bíró is kiírja a fordítási hibákat. A riportot (X. próbára kattintás) új lapon nyitjuk meg, és a címsorból kitöröljük a riport.txt-t, akkor egy mappába jutunk, ahonnan kiválaszthatjuk a compile.txt-t. Abban benne vannak a fordítási hibák, sorszámokkal együtt.)
  • A függvényben beolvasunk vagy kiírunk valamit a képernyőre.
    • (NEM szabad. A kapott paraméterekkel kell dolgozni, és a return-ben valamivel visszatérni, kivéve, ha a feladat kifejezetten IO művelet elvégzését kéri.)
  • A zh vége előtt 2 perccel töltjük fel a legelső (mellesleg fordítási hibás) kódunkat.
    • (NE! Ha már valamennyire kész vagyunk (ha több feladat van, akkor ha 1 feladat kész), vagy ha valami speciális esetre már működik, akkor nyugodtan töltsük fel, és lehet, hogy 1-2 pontot már kapunk is rá, és nyugodtabban próbálkozhatunk tovább.)
  • Nem formázzuk megfelelően a kódot.
    • (Ettől még működhet, a bíró is elfogadja - ha jó -, de ha valami gond van, akkor nagyon nehéz lesz javítani, és sok idő el fog menni vele. Tehát érdemes inkább azt a 2mp-et rászánni, hogy egy oszloppal eltoljuk azt a kapcsos zárójelet.)
  • Nem olvassuk el a feladatot
    • (El kell olvasni a feladatot, inkább többször.)
  • Többször rákattintunk a feltöltés gombra
    • (NE kattintsunk rá többször!)
  • Olyan helyen ír hibát a fordító, amit nem is mi írtunk
    • (Valahova eggyel több vagy kevesebb zárójelet tettünk (kapcsos, sima vagy szögletes). Érdemes szépen formázni a kódot.)
  • A programkódba kétszer illesztjük be a teljes megkapott forráskódot
    • (Ilyet ne csináljunk!)
  • Nem a függvényekbe, hanem azon kívülre dolgozunk.
    • (Az úgy nem lesz jó, a függvényekbe dolgozzunk! Természetesen ha szükséges, új függvényeket is létrehozhatunk.)
  • Idegeskedünk, ha a bíró nem ad pontot.
    • (Oké, csak gyorsan, de nyugodtan olvassuk el a feladatot még egyszer, és nézzük meg pl. egy példa inputra papíron, hogy mit kéne adnia a programnak, és mit ad valójában (papíron végigvezetve az egyes változók állását az egyes pillanatokban), és akkor meglesz a probléma forrása, és könnyebb javítani.)
  • Nem ismerjük az egyes vezérlési szerkezetek használati módját, működését, és nem tudjuk őket megfelelően használni, és fogalmunk sincs, hogy mire való, vagy miért vannak.
    • (Gyakoroljunk otthon minél többet, nézzük át a segédanyagokat, videókat, stb...)

További feladatok

Feladat (f0015)

Feladat:

Egészítsd ki a muvreal.c programot úgy, hogy a program által kiírt eredmény

  • a) a két szám összege legyen!
  • b) a két szám különbsége legyen (elsőből a második)!
  • c) a két szám szorzata legyen!
  • d) a két szám hányadosa legyen (első per második)!

A programon csak a main függvény vége utáni részen módosíthatsz!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 */

#include <stdio.h>

float muvelet(float a, float b);

int main() {
    float x, y;
    printf("Kérek két valós számot: ");
    scanf("%f %f", &y, &x);
    printf("Az eredmény: %f\n", muvelet(x, y));
    return 0;
}
/* Ettől a ponttól lehet módosítani */
muvreal.c

Feladat (f0017)

Van egy vicc:

  • Hogyan teszel be egy elefántot a hűtőbe?
  • ???
  • Kinyitod a hűtőajtót, beteszed az elefántot, majd becsukod a hűtőajtót. És hogyan teszel be egy zsiráfot a hűtőbe?
  • ...
  • ...

De ez egy programozási kurzus, szóval:

Problémafelvetés:

Adott két feladat, egy elefánt és egy zsiráf hűtőbe tétele. Írj egy-egy C függvényt, ami megvalósítja ezt a két feladatot!

Specifikáció:

A függvényeknek nincs sem inputja, sem közvetlen outputja.

Algoritmustervezés:

Négy művelettel kell dolgoznunk: hűtőajtó kinyitása és becsukása, valaminek a hűtőbe tétele illetve hűtőből kivétele. Ezeket egy-egy függvény valósítja meg. A megvalósításuk most nem érdekel minket, csak az, hogy hogyan lehet meghívni őket. Illetve szükségünk lesz még két programelemre, melyek az elefántot és a zsiráfot reprezentálják. Ezek segítségével kell megvalósítani a két függvényt.

Megvalósítás:

Adott a huto.c, amely tartalmazza a két megírandó függvény "vázát", valamint egy főprogramot az ellenőrzéshez, de ez utóbbihoz ne nyúljunk! A programban használhatjuk a huto.h-ban definiált ELEFANT és ZSIRAF azonosítókat, melyek az elefántot és a zsiráfot reprezentálják, valamint a négy fentebb említett műveletet megvalósító huto_nyitas(), huto_csukas(), betesz_hutobe() és kivesz_hutobol() függvényeket. Utóbbi kettő hívásakor paraméterként meg kell adni az ELEFANT vagy ZSIRAF azonosítókat.

Ha sikerül lekódolni a két függvényt, a huto.c programot le kell fordítani, és a lefordított program futtatásakor egyrészt kiírja a végrehajtott lépéseket, másrészt azt is, hogy a két függvény valóban azt csinálja-e, amit kell. És esetleg a vicc poénja is kiderül...

MEGJEGYZÉS:

Header fájlokban csak nagyon kivételes esetben definiálunk függvényeket, általában megelégszünk azok deklarációjával, és külön .c forrásban történő definíciójával. Most azért vannak a headerben definiálva, hogy elegendő legyen egyetlen c forrást (huto.c) fordítani.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Ez a fájl az SZTE Programozás Alapjai kurzusához készült.
 * A fájl NEM SZABVÁNYOS C header fájl, mert a függvények törzsét is
 * tartalmazza, de így egyszerűbb a használata.
 *
 * Használat:
 *
 * A c forrásprogram elejére kell beírni az
 *    #include "huto.h"
 * sort, ezek után használhatóak lesznek az alábbi konstansok:
 *    ELEFANT                      az elefántot jelképező konstans azonosító
 *    ZSIRAF                       a zsiráfot jelképező konstans azonosító
 * és függvények:
 *    void huto_nyitas()           a hűtő kinyitását modellező függvény
 *    void huto_csukas()           a hűtő becsukását modellező függvény
 *    void betesz_hutobe(VALAMI)   VALAMI-nek a hűtőbe rakását modellező függvény
 *    void kivesz_hutobol(VALAMI)  VALAMI-nek a hűtőből kivételét modellező függvény
 * Az utolsó két függvény esetén a VALAMI most ELEFANT vagy ZSIRAF lehet.
 */

#ifndef HUTO_H
#define HUTO_H

#include <stdio.h>
#include <string.h>

#define ELEFANT "elefant"
#define ZSIRAF  "zsiraf"
#define STRSIZE 256

void huto_nyitas();         // hűtőajtó kinyitása
void huto_csukas();         // hűtőajtó becsukása
void betesz_hutobe(char*);  // betevés hűtőbe (mit)
void kivesz_hutobol(char*); // kivétel hűtőből (mit)

/* A következő rész tartalmazza a fenti függvények implementációját, e
 * miatt nem szabványos ez a C header fájl.
 */

enum ajto_allapot { csukva, nyitva };

struct {
    enum ajto_allapot ajto;
    char tartalom[STRSIZE];
} huto = { csukva, "" } ;

#define zzz(a) ((*(a) == 'a' || *(a) == 'e' || *(a) == 'i' || *(a) == 'o' || *(a) == 'u' || \
         *(a) == 'A' || *(a) == 'E' || *(a) == 'I' || *(a) == 'O' || *(a) == 'U') \
         ? "az" : "a")

void huto_nyitas()
{
    if (huto.ajto == csukva) {
        huto.ajto = nyitva;
        printf("Kinyitom a hutoajtot.\n");
    } else {
        printf("Nem tudom kinyitni a hutoajtot, mert mar nyitva van.\n");
    }
}

void huto_csukas()
{
    if (huto.ajto == nyitva) {
        huto.ajto = csukva;
        printf("Becsukom a hutoajtot.\n");
    } else {
        printf("Nem tudom becsukni a hutoajtot, mert mar csukva van.\n");
    }
}

void betesz_hutobe(char* mit)
{
    if (huto.ajto == nyitva) {
        if (strncmp(huto.tartalom, "", STRSIZE) == 0) {
            strncpy(huto.tartalom, mit, STRSIZE);
            printf("Beteszem a hutobe %s %sot.\n", zzz(mit), mit);
        } else {
            printf("A hutoben mar van egy %s, igy nem tudok betenni semmi mast,\n\tfoleg nem egy %sot.\n", huto.tartalom, mit);
        }
    } else {
        printf("Csukott ajton keresztul nem tudom betenni %s %sot.\n", zzz(mit), mit);
    }
}

void kivesz_hutobol(char* mit)
{
    if (huto.ajto == nyitva) {
        if (strncmp(huto.tartalom, mit, STRSIZE) == 0) {
            strncpy(huto.tartalom, "", STRSIZE);
            printf("Kiveszem a hutobol %s %sot.\n", zzz(mit), mit);
        } else if (strncmp(huto.tartalom, "", STRSIZE) == 0) {
            printf("A huto ures, nem tudok belole kivenni semmit.\n");
        } else {
            printf("A hutoben egy %s van, nem egy %s. Inkabb benthagyom.\n", huto.tartalom, mit);
        }
    } else {
        printf("Csukott ajton keresztul nem tudok kivenni semmit.\n");
    }
}

int ellenorzes(char* elvaras) {
    if (huto.ajto == nyitva) {
        printf("Ne pazarold az energiat! Elfelejtetted becsukni a hutoajtot!\n");
        return 0;
    }
    if (strncmp(huto.tartalom, "", STRSIZE) == 0) {
        printf("Nem jo! A huto ures, nincs benne %s!\n", elvaras);
        return 0;
    }
    if (strncmp(huto.tartalom, elvaras, STRSIZE) != 0) {
        printf("Nem jo! A hutoben %s van %s helyett!\n", huto.tartalom, elvaras);
        return 0;
    }
    printf("Sikerult %s %sot berakni a hutobe.\n", zzz(elvaras), elvaras);
    return 1;
}

#endif
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Bár a program a huto.h header fájlt is felhasználja, mivel az
 * nem szabványos header és megvalósítást, definíciót is tartalmaz,
 * ezért a fordítás egyszerű marad.
 * 
 * fordítás:
 *    gcc -Wall -o huto huto.c
 *
 * futtatás:
 *    ./huto
 *
 * A programban használhatóak lesznek az alábbi konstansok:
 *    ELEFANT                      az elefántot jelképező konstans azonosító
 *    ZSIRAF                       a zsiráfot jelképező konstans azonosító
 * és függvények:
 *    void huto_nyitas()           a hűtő kinyitását modellező függvény
 *    void huto_csukas()           a hűtő becsukását modellező függvény
 *    void betesz_hutobe(VALAMI)   VALAMI-nek a hűtőbe rakását modellező függvény
 *    void kivesz_hutobol(VALAMI)  VALAMI-nek a hűtőből kivételét modellező függvény
 * Az utolsó két függvény esetén a VALAMI most ELEFANT vagy ZSIRAF lehet.
 */

#include <stdio.h>
#include "huto.h"

void elefant() {
    /* Ezt kell kitölteni */
}

void zsiraf() {
    /* Ezt kell kitölteni */
}

/*
 * A main függvényen nem szabad változtatni, a feladat a fenti
 * két függvény megírása.
 */

int main() {
    printf("Elefant betetele:\n\n");
    elefant();
    if (ellenorzes(ELEFANT)) {
        printf("---\nZsiraf betetele:\n\n");
        zsiraf();
        ellenorzes(ZSIRAF);
    } else {
       printf("\nAmig az elefantot nem sikerül rendesen a hutobe tenni,\na zsiraffal nem is foglalkozunk.\n");
    }
    printf("---\n");
    return 0;
}

huto.h huto.c

Feladat (f0069)

Problémafelvetés:

Valósítsd meg a linuxos seq parancs egy változatát, ami beolvas két egész számot, majd a kettő közötti egész számokat (a határértékeket is beleértve) növekvő sorrendben soronként kiírja. A két végpont sorrendje nem érdekes, ha a második kisebb, akkor is ki kell írni az elemeket.

Specifikáció:

A program inputja két egész szám, A és B, outputja pedig A <= B esetén az [A, B] vagy A > B esetén a [B, A] zárt intervallumok egész értékű elemei növekvő sorrendben, minden elem külön sorban. A program más kimenetet nem ad.

A specifikációtól eltérő megvalósítást mutatja be a következő videó:

seq

Lehetséges megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Algoritmustervezés:
 *    A program bekér két egész számot, majd ha kell akkor átrendezi őket,
 *    hogy az első legyen a kisebbik, ezután az elsőtől a másodikig növekvő
 *    sorrendben haladva minden értékre végrehajtja ugyanazt a műveletet. Ez
 *    a művelet az aktuális érték kiírása egy sorba.
 *
 * fordítás:
 *    gcc -o $BASENAME$ $FILENAME$
 *
 * futtatás:
 *    ./$BASENAME$
 */

#include <stdio.h>

int main() {
    int a, b, i;
    scanf("%d %d", &a, &b);
    if (a > b) {
        int m = a;
        a = b;
        b = m;
    }
    for (i = a; i <= b; ++i) {
        printf("%d\n", i);
    }
    return 0;
}
m0069.c

Feladat (f0070)

Problémafelvetés:

Döntsd el egy karakterről, hogy kis- vagy nagybetű, szám, esetleg egyéb karakter ("kisbetű", "nagybetű", "számjegy", "egyéb")!

Algoritmustervezés/Megvalósítás:

Készíts többféle algoritmust és megvalósítást. Először oldd meg a feladatot megkötések nélkül, majd úgy, hogy az alábbi megszorítások közül kiválasztasz egyet, és azt betartod: - Az if, ?: és switch közül csak az if szerkezetet használhatod. - Az if, ?: és switch közül csak a ?: kifejezést használhatod. - Az if, ?: és switch közül csak a switch szerkezetet használhatod. - Az if, ?: és switch közül egyiket sem használhatod.

Lehetséges megoldás

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai feladat megoldása
 *
 * Gergely Tamás, 2008. őszi félév.
 *
 * Specifikáció:
 *    Input: egyetlen karakter
 *    Output: az input beolvasása előtt egy tájékoztató szöveg, majd utána a
 *    "kisbetű", "nagybetű", "számjegy", "egyéb" szövegek valamelyike a
 *    beolvasott karakter értékének megfelelően.
 *
 * Algoritmustervezés:
 *    A program nem tartalmaz hibakezelést.
 * 
 * Megvalósítás:
 *    Megkötések nélkül.
 *
 * fordítás:
 *    gcc -o $BASENAME$ $FILENAME$
 *
 * futtatás:
 *    ./$BASENAME$
 */

#include <stdio.h>

int main() {
    char c;
    printf("Kérem a karaktert: ");
    scanf("%c", &c);
    if ('a' <= c && c <= 'z') {
        printf("kisbetű\n");
    } else if ('A' <= c && c <= 'Z') {
        printf("nagybetű\n");
    } else if ('0' <= c && c <= '9') {
        printf("számjegy\n");
    } else {
        printf("egyéb\n");
    }
    return 0;
}
m0070.c

Feladat (f0078)

Problémafelvetés:

Írj egy programot, ami bekéri a sakktábla egy mezőjének koordinátáját, majd megmondja, hogy a normál kezdeti felállítás szerint milyen bábu van az adott helyen! A bábu színe "világos" vagy "sötét", alakja "gyalog", "bástya", huszár", "futó", "vezér", "király". (Pl. "a2" input esetén "világos gyalog", "c8" esetén "sötét futó".) Ha az adott helyen nincs bábu, akkor a mező színét írja ki (pl. "d4" esetén "üres sötét mező"). Feltételezhető, hogy az input pontosan két karakter, amik egy sakktábla-mezőt jelölnek.

Algoritmustervezés/Megvalósítás:

Készíts többféle algoritmust és megvalósítást. Először oldd meg a feladatot megkötések nélkül, majd úgy, hogy az alábbi megszorítások közül kiválasztasz egyet, és azt betartod: - Az if, ?: és switch közül csak az if szerkezetet használhatod. - Az if, ?: és switch közül csak a ?: kifejezést használhatod. - Az if, ?: és switch közül csak a switch szerkezetet használhatod.

Feladat (f0083)

Feladat:

Az intervallum.c program feladata ellenőrizni, hogy egész számok egy zárt intervalluma tartalmaz-e egy harmadik egész számot. Teszteld a programot különböző értékekkel! Mi a hiba a programban, miért úgy működik ahogy, és hogyan lehet javítani?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 */

#include <stdio.h>

#ifndef UTF8
// szöveges output
#define ISIN  " eleme "
#define NOTIN " nem eleme "
#else
// a matematikai szimbólumok UTF-8 kódjai
#define ISIN  "\xe2\x88\x88 "
#define NOTIN "\xe2\x88\x89 "
#endif

int main () {
    int x, a, b;

    printf("Kérem az intervallum alsó és felső végpontját (két egész számot): ");
    scanf("%d %d", &a, &b);
    printf("Kérem az értéket (egy egész számot): ");
    scanf("%d", &x);

    if (a <= x <= b) {
        printf("%d%s[%d,%d]\n", x, ISIN, a, b);
    } else  {
        printf("%d%s[%d,%d]\n", x, NOTIN, a, b);
    }
    return 0;
}
intervallum.c

Feladat (f0085)

Kérdés:

Elhagyható-e C nyelvben egy if igaz ága úgy, hogy a hamis ágat meghagyjuk? Pontosabban, lehet-e C nyelven olyan if-else vezérlést készíteni, amelyben az igaz (if) ág nem tartalmaz műveletet, de a hamis (else) ág igen? Ha igen, hogyan?

Feladat (f0098)

Problémafelvetés:

Készíts egy programot, amely logikai true/false értéket reprezentáló 1 vagy 0 értéket olvas be, majd kiírja true/1 érték esetén az 'I', false/0 érték esetén a 'H' karaktert egyetlen sorban. Más input érték esetén ne írjon ki semmit!

Algoritmustervezés:

A főprogram végezze el az érték beolvasását, a helyesség ellenőrzését és a kiíratást. De készíts egy olyan függvényt, amely logikai értéket kap paraméterként, a visszatérési értéke pedig egy karakter, és ezt használd fel a kiíratáshoz!

Feladat (f0129)

Problémafelvetés:

Írj egy programot ami bekér egy n pozitív egész számot, majd kiírja az 1-től n-ig terjedő zárt intervallumba eső négyzetszámokat.

Algoritmustervezés/Megvalósítás:

A beolvasást a főprogram végezze, de a működés lényegi része külön függvény(ek)ben legyen! Készíts többféle algoritmust és megvalósítást. Először oldd meg a feladatot megkötések nélkül, majd úgy, hogy az alábbi megszorítások közül kiválasztasz egyet, és azt betartod:

  1. A for, while és do-while közül csak a for szerkezetet használhatod.
  2. A for, while és do-while közül csak a while szerkezetet használhatod.
  3. A for, while és do-while közül csak a do-while szerkezetet használhatod.

Hasonló feladat megoldását mutatja be a következő videó:

seq

Lehetséges megoldások

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Keleti Márton, 2018. őszi félév.
 *
 * Specifikáció:
 *    Input: egy pozitív egész szám
 *    Output: az 1-től n-ig terjedő zárt intervallumba eső négyzetszámok
 *
 * Algoritmustervezés:
 *    A beolvasást a főprogram végzi, a működés lényegi része külön
 *    függvényben van. Csak a for szerkezetet használjuk.
 *
 * fordítás:
 *    gcc -Wall -o m0129-1 m0129-1.c
 *
 * futtatás:
 *    ./m0129-1
 */

#include <stdio.h>

void negyzetszamkeres(int n) {
    for (int i = 1, negyzet = 1; negyzet <= n; ++i, negyzet = i * i) {
        printf("%d ", negyzet);
    }
    printf("\n");
}

int main() {
    int szam;

    scanf("%d", &szam);
    negyzetszamkeres(szam);

    return 0;
}
m0129-1.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Keleti Márton, 2018. őszi félév.
 *
 * Specifikáció:
 *    Input: egy pozitív egész szám
 *    Output: az 1-től n-ig terjedő zárt intervallumba eső négyzetszámok
 *
 * Algoritmustervezés:
 *    A beolvasást a főprogram végzi, a működés lényegi része külön
 *    függvényben van. Csak a while szerkezetet használjuk.
 *
 * fordítás:
 *    gcc -Wall -o m0129-2 m0129-2.c
 *
 * futtatás:
 *    ./m0129-2
 */

#include <stdio.h>

void negyzetszamkeres(int n) {
    int i = 1, negyzet = 1;
    while (negyzet <= n) {
        printf("%d ", negyzet);
        ++i;
        negyzet = i * i;
    }
    printf("\n");
}

int main() {
    int szam;

    scanf("%d", &szam);
    negyzetszamkeres(szam);

    return 0;
}
m0129-2.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * Szegedi Tudományegyetem
 * Informatikai Tanszékcsoport
 * Szoftverfejlesztés Tanszék
 *
 * Programozás Alapjai
 *
 * Keleti Márton, 2018. őszi félév.
 *
 * Specifikáció:
 *    Input: egy pozitív egész szám
 *    Output: az 1-től n-ig terjedő zárt intervallumba eső négyzetszámok
 *
 * Algoritmustervezés:
 *    A beolvasást a főprogram végzi, a működés lényegi része külön
 *    függvényben van. Csak a do-while szerkezetet használjuk.
 *
 * fordítás:
 *    gcc -Wall -o m0129-3 m0129-3.c
 *
 * futtatás:
 *    ./m0129-3
 */

#include <stdio.h>

void negyzetszamkeres(int n) {
    int i = 1, negyzet = 1;
    do {
        printf("%d ", negyzet);
        ++i;
        negyzet = i * i;
    } while (negyzet <= n);
    printf("\n");
}

int main() {
    int szam;

    scanf("%d", &szam);
    negyzetszamkeres(szam);

    return 0;
}
m0129-3.c

Kapcsolódó linkek


Utolsó frissítés: 2020-11-19 09:39:47