Info 2 első gyakorló zárthelyi feladatsor

Utolsó módosítás: 2009. március 5.

Prímfelbontás

A alábbi forráskódot elmentettem z0g0.c néven, és lefordítottam a gcc -lm -Wall -O -o z0g0 z0g0.c paranccsal.

A program a bemenetnek megadott szám prímfelbontását keresi meg, mégpedig a prímtényezőket megfelelő multiplicitással kiírja növekvő sorrendben. Például ha a kapott programot lefuttatjuk, és a bemenetre beírjuk, hogy 63, akkor a kimenet a következő.

3
3
7

A prímfelbontást egyszerűen úgy állítjuk elő, hogy 2-től indulva minden egész számmal megpróbáljuk elosztani a számot. A 13–14. sorok meggyorsítják a keresés végét, ugyanis e miatt egy nagy n prímszámot nem kell minden számmal elosztanunk 2-től n-ig, elég csak 2-től n négyzetgyökéig megvizsgálni az osztókat. Valóban, ha az n számot ezek közül egyik sem osztja, akkor az biztosan prím. (A 7–10 sorok a hibás bemeneteket próbálják meg kiszűrni, ezekkel most ne foglalkozzunk.)

01 #include <stdio.h>
02 #include <math.h>
03 
04 int
05 main(void) {
06         long n, p;
07         if (1 != scanf("%ld", &n))
08                 return 1;
09         if (n < 1)
10                 return 1;
11         p = 2;
12         while (1 < n) {
13                 if (1 + sqrt(n) < p)
14                         p = n;
15                 while (0 == n % p) {
16                         printf("%ld\n", p);
17                         n /= p;
18                 }
19                 p++;
20         }
21         return 0;
22 }
23 

Ehhez a programhoz kapcsolódnak a következő feladatok.

1. feladat

El szeretnénk érni, hogy a program a kimenetre ne növekvő, hanem csökkenő sorrendben írja ki a tényezőket. Hogyan módosítaná ehhez a programot? Írja le az ötletét. Nem kell pontos kódot írnia.

2. feladat

Magyarázza meg, miért kell a 15. sorba while ciklust írni, mi történne, ha a while kulcsszót kicserélnénk az if kulcsszóra. Adjon példát olyan bemenetre, amikor az így módosított program hibásan működne.

3. feladat

Módosítsa úgy a program forráskódját, hogy a ciklus a 2 után csak a páratlan számokon lépdeljen végig. (Több páros prím nincs, így ezeket fölösleges is lenne megvizsgálni.) Írja le a változtatásokat pontosan.

Italautomata

Tekintse a következő hibás program forráskódot, amit z0g1.c néven mentettem el. Amikor a programot megpróbáltam lefordítani a gcc -Wall -O -o z0g1 z0g1.c paranccsal, a fordító talált két egyszerű szintaktikai hibát a kódban, ezért a következő hibaüzenetet adta.

z0g1.c: In function 'main':
z0g1.c:8: error: 'k' undeclared (first use in this function)
z0g1.c:8: error: (Each undeclared identifier is reported only once
z0g1.c:8: error: for each function it appears in.)
z0g1.c:10: error: expected expression before ')' token

4. feladat

Keresse meg a két elírást a programban, amik ezeket a hibákat okozták, és adja meg pontosan, hogyan kell kijavítani őket!

(A 3–4. sorok helyesek, és úgy hoznak létre egy öt hosszú tömböt, hogy a tartalmát rögtön inicializálják is a megadott adatokkal, az első szám a 0 indexű elembe kerül, stb.)

01 #include <stdio.h>
02 
03 int
04 coin[5] = {100, 50, 20, 10, 5};
05 
06 int
07 main(void) {
08         int v = 0; k = 0;
09         scanf("%d", &v);
10         for (k = 0; k < 5; k+ +) {
11                 while (coin[k] <= v) {
12                         printf("%d\n", coin[k]);
13                         v -= coin[k];
14                 }
15         }
16         return 0;
17 }

Tegyük fel, hogy a hibákat kijavította. A program ekkor azt fogja megadni, hogy egy italautomata milyen érméket ad vissza, ha a vásárló túl sok pénzt dobott be. A visszajáró összegét (forintban) a standard bemenetről olvassa be, majd a kimenetre kiírja az érméket, amiket az italautomata kiad. Az automata 100, 50, 20, 10 és 5 forintos érméket tud visszaadni, mindegyikből elég sok van benne, és külön rekeszben vannak.

Például ha a helyes programot lefordítjuk, lefuttatjuk, és a bemenetére megadjuk, hogy 25, akkor ezt írja ki:

20
5
mivel az automata egy 20 forintos, és egy 5 forintos érmét ad ki. Ha a bemenet 0, akkor a program semmit nem ír ki, mivel ilyenkor az automatának nem kell semmilyen érmét kidobnia.

Ehhez a programhoz kapcsolódik még egy feladat.

5. feladat

Az italautomata általában úgy van beállítva, hogy minden ital ára 5 forinttal osztható. Mi történne, ha ennek a programnak mégis öttel nem osztható bemenetet adnánk? Mi lenne például a kimenet, ha a bemenet 19, és miért?

Megfordítás

A következő hibás programot z0g2.c néven mentettem el. Amikor a gcc -Wall -O -o z0g2 z0g2.c paranccsal lefordítottam, a fordító a következő üzenetet adta ki.

z0g2.c: In function 'main':
z0g2.c:6: warning: 'pos' may be used uninitialized in this function

Amikor mégis kipróbáltam a programot, miután a bemenetet beolvasta, nem kaptam meg a helyes kimenetet, csak a Segmentation Fault hibaüzenetet kaptam.

6. feladat

Milyen logikai hiba van a programban, amelyre a fordító figyelmeztetni próbált? Hogyan javítaná ki ezt a hibát? Adja meg a pontos változtatást, amely a forráskódban szükséges a javításhoz!

01 #include <stdio.h>
02 
03 int
04 main(void) {
05         char line[100];
06         int pos, c;
07         while ('\n' != (c = getchar())) {
08                 line[pos++] = c;
09         }
10         while (0 < pos)
11                 putchar(line[--pos]);
12         putchar('\n');
13         return 0;
14 }

A javított program arra szolgál, hogy a bemeneten megadott egy sort megfordít, vagyis a karaktereit fordított sorrendben írja ki. Például ha a javított programot lefordítjuk, lefuttatjuk, majd bemenetnek beírjuk, hogy Goromba rab morog. majd egy entert ütünk, a program a következő kimenetet írja ki: .gorom bar abmoroG

7. feladat

Fontos-e, hogy a 11. sorban pos-- helyett --pos-t írjunk? Fejtse ki, miért vagy miért nem!

8. feladat

Ha most a programnak azt a mosolygós bemenetet adjuk, hogy

:-)

akkor a kimenet szomorú lesz:

)-:

Módosítani szeretnénk úgy a programot, hogy e helyett a kimenet is mosolygós legyen:

(-:

Pontosabban azt szeretnénk elérni, hogy a kimenetben a program a bal zárójeleket jobb zárójelre cserélje, és viszont. Más karaktereket ne változtassunk meg. Így például ha a bemenet

jeles (5)

akkor a kimenet legyen

(5) selej

Írja le a pontos változtatásokat a forráskódon, amik után a program így fog működni.