Info 2 harmadik házi feladat: "keresés", általánosabb keresés szövegben

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

Gyakorlaton megnéztük, hogy lehet egy szövegben megkeresni egy bizonyos szövegrészletet.

Az h6g0.c program lényegében ez a gyakorlaton vizsgált program. Ha lefordítja a programot a gcc -Wall -O -o h6g0 h6g0.c paranccsal, majd lefuttatja a ./h6g0 < h5g0be0 paranccsal, ahol a h5g0be0 szöveges fájl Arany János Tetemre hívás című versét tartalmazza, akkor ezt a kimenetet kapjuk.

Ki *se terítteti, meg se mosatja:
   "Lélek ez ajtón *se be, se ki..."
   Legyen a *seb vérzése tanú.
   Déli verőn *sem süt oda nap;
Hiába! nem indul *sebe a holtnak
   Erre *se vérzik Bárczi fia.
Megkönnyezetlen *senki se hagyja,
   Nem fakad a *seb könnyre megint.
   Mindre nem érez *semmit a holt:
Könnye *se perdűl, jajja se hallik,
   Tanum az Ég, s minden *seregi!
S vadul a *sebből a tőrt kiragadja,
   S vérc*se-visongással rohan el.
   Vetni kezet rá *senki se mer.
   Táncolni, dalolni *se szégyell;

A program tehát csak azokat a sorokat írja ki, amikben szerepel a "se" sztring, és megjelöli ennek az első előfordulását egy csillaggal.

A program legérdekesebb része az a sor volt, ahol egy függvénynek egy tömb valamelyik belső elemére mutatót adtunk át argumentumként, de a függvény erről nem tud semmit.

40                         putstring(line + pos, len - pos);

Ugyanezt lehet felhasználni arra, hogy egy találat után a változatlan search függvénnyel megkeressük a következő előfordulását is a "se" sztringnek a beolvasott sorban. Gyakorlásként érdemes lehet megpróbálkoznia megírni ezt a változatot is, ami egy sorban több találatot is megtalál, tehát a kimenet a következő. (Ha nincs kedve, akkor csalhat is úgy, hogy megnézi a már megírt programot, de akkor legalább találja meg rá a linket a gyakorlati anyagok oldalról.)

Ki *se terítteti, meg *se mosatja:
   "Lélek ez ajtón *se be, *se ki..."
   Legyen a *seb vérzé*se tanú.
   Déli verőn *sem süt oda nap;
Hiába! nem indul *sebe a holtnak
   Erre *se vérzik Bárczi fia.
Megkönnyezetlen *senki *se hagyja,
   Nem fakad a *seb könnyre megint.
   Mindre nem érez *semmit a holt:
Könnye *se perdűl, jajja *se hallik,
   Tanum az Ég, s minden *seregi!
S vadul a *sebből a tőrt kiragadja,
   S vérc*se-visongással rohan el.
   Vetni kezet rá *senki *se mer.
   Táncolni, dalolni *se szégyell;

A soronként több találatnak azonban nincs sok köze a mostani házi feladathoz, amiben ugyanis a kereső programot más irányban kell továbbfejlesztenie.

Írjon ugyanis egy olyan programot, ami nem csak a "se" sztringre, hanem tetszőleges sztringre tud keresni a standard bemenet soraiban. A program a sztringet parancssori argumentumként kell, hogy megkapja. A sztring hossza is tetszőleges lehet. Továbbra is csak soronként az első találatot jelezze csillaggal, és azokat a sorokat, ahol nincs találat, ne írja ki.

Ha tehán a futtatható program neve h6g6, akkor a ./h6g6 se < h5g0be0 parancs eredménye ugyanaz kell, hogy legyen, mint korábban a ./h6g0 < h5g0be0 parancsé.

További példák. A ./h6g6 Bárc < h5g0be0 eredménye

   Halva találták *Bárczi Benőt.
"Hát ki?..." riad fel *Bárczi sötéten,
   Erre se vérzik *Bárczi fia.
   Jöjjön elő *Bárc, a falu, mind!"
"*Bárczi Benőt én meg nem öltem

A ./h6g6 "l a" < h5g0be0 eredménye pedig

Kastélyába vitette fö*l atyja,
Ál*l a tetemnél tiszti pörosztó,
   Állva fejéné*l az, vagy emez:
   Vádda*l az önnön szívemig ér:
   Csak odakap, hol fészke*l az agy:
   Döbbenet álta*l a szív ere fagy:
S vadu*l a sebből a tőrt kiragadja,

(az idézőjel arra kell, hogy a shell a szóközt tartalmazó három karakteres sztringet egy argumentumként adja át a programnak, ne pedig két külön argumentumként.)

A parancssori argumentumokat az operációs rendszer és a C futtatási környezet indításkor bemásolja a program memóriájába, és mutatókon keresztül teszi elérhetővé. Ahhoz, hogy ezt használjuk a main függvényt úgy kell definiálni, hogy két paramétere legyen a következő módon.

int main(int argc, char **argv)

Az első paraméter (hagyományosan argc a neve) eggyel nagyobb, mint ahány parancssori argumentummal van meghívva a program, tehát ebben a példában 2 (érdemes ezt ellenőrizni is a programban). A második paraméter (argv) egy char * típusú elemekből álló tömbre mutat, amely argc elemből áll, és minden eleme egy parancssori argumentumhoz tartozik. Minden ilyen elem egy karaktertömbre mutat, ezek mindegyike 0 értékű karakterrel van lezárva. A 0 karakteren kívül máshonnan nem derül ki, milyen hosszúak az egyes argumentumok. Az argv[0] nem argumentumra mutat, hanem a program nevére, ezt általában nem szoktuk elérni, az argv[1] mutat az első argumentumra, stb, az argv[argc-1] az utolsóra. Minden program, például a gcc vagy a cat is ezeken a mutatókon keresztül éri el a parancssori argumentumokat.

A programot érdemes a h6g0.c egy másolatának módosításával előállítani, de akár teljesen új programot is kezdhet, ha azt könnyebbnek találja.

A megoldást e-mailben küldje el az ambrus@@mmaatthh..bbmmee..hhuu (a dupla karaktereket csak egyszer kell beírni) címre. Az emailben csatolmányként küldje el a megoldáshoz használt forráskódot, és írhat bármilyen megjegyzéseket, amit a megoldással kapcsolatban lényegesnek talál. Az emailben feltétlenül adja meg a nevét, nem szeretnék névtelen házi feladatokat azonosítani. Írja továbbá az emailbe az "info2" szöveget, valamint a feladat rövid nevét, jelen esetben azt, hogy "keresés", hogy könnyebben szét tudjam válogatni a feladatokat. (Ez utóbbi új szabály, korábban nem gondoltam rá, hogy a házi feladatokat meg is kéne különböztetni egymástól.)

Ha a feladathoz bármilyen kérdése van, vagy elakad a megoldással, akkor keressen meg emailben vagy személyesen, akár a gyakorlaton, akár azon kívül.

A feladatot 2009. március 19-én illetve 20-án tűzom ki. A megoldás határideje ehhez képest két hét, vagyis április 3. péntek (aznap még be lehet küldeni).