Utolsó módosítás: 2009. március 5.
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.
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.
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.
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
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 5mivel 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.
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?
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.
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
Fontos-e, hogy a 11. sorban pos--
helyett --pos
-t
írjunk? Fejtse ki, miért vagy miért nem!
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.