VIII. Filekezelés és szövegfeldolgozás

Elsõ nekifutás: filekezelés, elemenkénti feldolgozás és elõreolvasás

A szekvenciális és direkt file-ok kezelésének részletes leírását ld. a 2. Pascal füzetke 1. fejezetében. A lényeg, hogy a szekvenciális file-ok elemei csak sorban egymás után dolgozhatók fel, míg a direkt file-ok bármelyik rekordját egy lépésben elérhetjük. A direkt file azonos hosszúságú rekordok egymás utánja, míg a szekvenciális file változó hosszúságú rekordokból állhat. Erre példa egy szöveges sorokból álló file. Természetesen szöveges file (a Pascal TEXT típusa) is kezelhetõ byte-okból álló direkt file-ként, de ez általában nem segítség (ha a 100. sorra van szükségünk, mindenképpen végig kell olvasni byte-onként a file-t a 100. sorig).

A direkt file felfogható egy lemezen elhelyezkedõ tömbként is: azonban a tömb egyes elemeinek nem sorrendben történõ kiolvasása, a rekord-mutató helyének sûrû változtatása idõigényes. Ha a tömböknél használt rendezési módszereket direkt file-oknál alkalmaznánk, elfogadhatatlanul lassú programokat kapnánk. Éppen ezért igyek szünk a file-t minél kevesebbszer végigolvasni: a szekvenciális file-oknál használt módszereknek direkt file-oknál is jó hasznát vesszük. (Természetesen ha pl. meg kell cserélnünk a file elsõ és második byte-ját, direkt file-ként kezelve sokkal gyorsabban célt érünk, mintha a szekvenciális file-oknál használt módszer szerint a byte-okat az elsõ kettõ megcserélésével másik file-ba másolnánk.)

Egy file-t egy feladatban elemenként feldolgozhatónak nevezünk, ha a feladatot a következõ séma szerint oldhatjuk meg:

Megnyitás
Ciklus amíg nincs vége a file-nak
   Beolvas(X)
   Kiír(f(X))
Ciklus vége
Lezárás

A kiírás többnyire egy másik file-ba történik. f(X) egy X-tõl függõ érték. A következõ egyszerû feladat az elemenkénti feldolgozásra példa.

1. feladat: írj programot, mely egy szöveges file-t ékezettelenít (a program kimenete egy másik szöveges file)!

Nehezebb a helyzet, ha X feldolgozásához ismerni kell az X-et követõ értéket. Ekkor is követhetõ az elemenkénti feldolgozás sémája, de a beolvasás, lezárás és esetleg a filevég-ellenõrzés feladatát eljárások veszik át. Az elõreolvasás módszerénél egy elemmel mindig elõrébb tartunk a file-ban. Ezt az elemet már megnyitáskor beolvas suk. Speciális módon kell kezelni a file végét, mert az utolsó elõtti elem beolvasásánál már filevég-jelet kapunk, hiszen a beolvasó eljárás az utolsó elemet is kiolvasta. Az egyik módszer, ha az így kimaradó utolsó elemet a Lezár eljárással dolgoztatjuk fel. A másik lehetõség, ha a programunk nem az eredeti filevég-jelet veszi figyelembe, hanem a Beolvas eljárás jelzését, mely így még visszaadhatja az utolsó elemet is. Erre lássunk egy példát. A következõ algoritmusoknál a saját eljárásoktól való megkülönböztetés miatt az eredeti filekezelõ eljárásokat _ jellel jelölöm. 0 hosszúságú file-ra ez a módszer nem mûködik.

Megnyitás:
 _megnyitás
 _beolvas(E)
 Vége:=hamis

Beolvas(X):
 X:=E
 Ha nincs _vége   akkor _beolvas(E)
               különben Vége:=igaz, E-be megfelelõ ál-érték helyezése

2. feladat: írj programot, mely egy repülõ ékezetes (az e'kezetes betu"ket ke't karakter i'rja le) szöveges file-t közönséges ékezetes file-lá fordít le! Mit jelent az ál-érték? Ha a file utolsó karaktere pl. „o", akkor végül ez kerül X-be, és E-ben most nem lehet repülõ ékezet, hiszen akkor a fõprogram rosszul értelmezné a betût. Ehelyett természetesen vizsgálhatja a program azt is, hogy a file utolsó karakterérõl van-e szó.

3. feladat: írj programot, mely egy file-t úgy tömörít, hogy az egymás utáni egyforma karaktereket \, karakter, ismétlõdés karakterhármassal jelzi. Az ismétlõdés egy byte-os érték, ezért 255-nél nagyobb ismétlõdésszámot már csak két részletben tud kódolni a program. Figyelj arra is, hogy magát a „\" karaktert hogyan kódolod, hogy a dekó dolásnál ne okozzon félreértést! Készítsd el a kibontó programot is (az már egyszerû elemenkénti feldolgozással, elõreolvasás nélkül megoldható).

Ha a file olyan rövid, hogy befér a memóriába, a legtöbb mûvelet nagyon egyszerû, hiszen így nem kell törõdnünk az adatok lassú elérésével. A legtöbb file-kezelési feladat akkor lesz érdekes, ha a file hossza elõre nem ismert, vagy nem fér a memóriába.

4. feladat: egy szöveges file szavakat tartalmaz (soronként egyet). Írj programot, amely megfordítja a szavak sorrendjét! Tipp: ha az egész file nem is, egy része biztosan befér egy tömbbe (feltehetõ, hogy az egyes sorok hossza 256 karakternél kisebb, vagyis stringben tárolható).

5. feladat: készíts programot, amely két rendezett file rekordjait egy harmadik rendezett file-ba futtatja össze (ld. összefuttatás algoritmusa, IV. fejezet).

File rendezésénél használt módszer a következõ: a file-t akkora szeletekre vágjuk, melyek beférnek a memóriába. Ezeket a szeleteket rendezzük. A rendezett szeleteket felváltva kiírjuk két file-ba (ezek tehát rendezett szeletek egymás utánjait fogják tartalmazni). Ezután a két segédfile-ból egy-egy szeletet kiolvasva azokat összefuttatjuk, így kétszer akkora rendezett szeleteket kapunk, melyeket felváltva kiírunk egy harmadik és negyedik segédfile-ba. Az elsõ két segédfile törölhetõ. Most a harmadik és negyedik segédfile-ból olvassuk a rendezett szeleteket, és összefuttatva két segédfile-ba írjuk felváltva stb... Így végül az egész file-t rendezhetjük (összefuttató rendezés 4 segédfile-lal).

Egyszerûbbnek tûnne az a módszer, amikor egy kis szeletet mindig „hozzáfuttatunk" az így egyre nagyobbra hízó segédfile-hoz, de ebben az esetben sokkal több file-mûveletet végeznénk, míg az elsõ módszer minden lépésben megduplázza a rendezett szeletek hosszát.

6. feladat: írj programot hosszú file rendezésére!

Második nekifutás: szövegfeldolgozás

Mivel a szöveges file-okat gyakran byte-onként, vagyis karakterenként dolgozzuk fel, fontos tudni, hogy a DOS a sor végét CR, LF (13, 10 kódú) karakterekkel jelzi. (UNIX rendszereknél ez csak LF.)

1. feladat: írj programot, mely eltünteti szöveges file-ból a felesleges szóközöket! (Egynél több egymás melletti szóköz felesleges.)

A továbbiakban olyan szövegekkel foglalkozunk, melyek a CR, LF karaktereket bekezdésvég jelzésére használják, s a bekezdés szavai szóközzel elválasztva folyamatosan következnek.

2. feladat: írj programot, mely egymás alá kiírja egy szöveges file szavait! A program a bekezdésvéget * szóként jelölje.

3. feladat: írj programot, mely egy szöveges file-t adott karakterszámú sorokra tördelve ír ki! Ha egy szó nem fér ki teljes egészében egy sorba, akkor az egész szót a következõ sorba kell írni. Tipp: érdemes követni a következõ szerkezetet (Pascal):

While not eof(f) do begin
   read(f,c);
   if c=CR then read(f,c);
   Sorbaír(c);
End;

A kiírt sorok még mindig igazíthatók balra, jobbra, középre, illetve az üres helyek a szavak között is szétoszthatók (sorkizárt mód). Ez úgy valósítható meg áttekinthetõ módon, ha az elõzõ feladat Sorbaír eljárása nem közvetlenül nyomtat, hanem a kiírandó sort egy másik eljárásnak adja át, amely elvégzi az igazítás utolsó simításait.

4. feladat: módosítsd a 3. feladat programját úgy, hogy a sorokra tördelt szöveget jobbra és középre zárva, illetve sorkizárva is képes legyen kiírni!

5. feladat: további módosítások. A kiírt szöveget adott sorszámhoz, lapokra tördelve kell kiírni (a lap végét 12-es kódú karakter jelezze). Lap tetején legyen fejléc, lap alján pedig lábléc (pl. oldalszámozás).

Következõ fejezet
Elõzõ fejezet
Tartalomjegyzék
Honlap