Ebben a fejezetben megmutatom, hogyan lehet a szöveget karakterenként kezelni. Ezen kívül, a korábban tanultak felhasználásával, már összetettebb feladatokkal is találkozhatsz, melyek általános programozási technikákat mutatnak be. A továbbiakban az ilyen példák egyre gyakoribbak lesznek, tehát akkor is érdemes egy fejezetet elolvasnod, ha éppen az a téma (most a szövegkezelés) nem érdekel.
A szöveg karaktereiEgy string típusú változó úgy viselkedik, mint egy karakterekből álló tömb. Így
s[2] a string második karakterét jelenti. Ha minden karaktert fel szeretnénk dolgozni, szükségünk lesz a string hosszára: ezt a length függvény adja meg.A következő példa kiírja a szöveget függőlegesen (soronként egy karaktert):
Var s:string; i:integer; BEGIN write('Írj be valamit: '); readln(s); for i:=1 to length(s) do writeln(s[i]); write('nyomj entert'); readln; END. Figyelem! Ezek a példák ékezetes karakterekkel csak úgy fognak működni, ha a fájl kódolását CP852-re állítottad! (2. fejezet). Ennek okáról és az utf-8 kódolásról később, a grafikus felület kezelésénél lesz szó.
Számoljuk meg egy string magánhangzóit! A ciklusunk ilyesféle feltételt tartalmazna:
if (s[i]='a') or (s[i]='A') or (s[i]='á') or (s[i]='Á')... ez így, a kis- és nagybetűket figyelembe véve, nagyon hosszadalmas lenne. Ha azonban a magánhangzók listája szerepelne egy változóban, csak azt kellene megvizsgálni, hogy az adott karakter szerepel-e ebben.
m:='öüóeuioőúaéáűíÖÜÓEUIOŐÚAÉÁŰÍ' Hogyan állapítsuk meg, hogy a szövegünk
s[i] karaktere szerepel-e m -ben? Egy ciklussal végiglépkedünk m összes karakterén, amíg nem találunk egyezést s[i] -vel, vagy m végére nem érünk. Ez most nem for-ciklus lesz, mert nem tudjuk előre, meddig kell számolnia. Az elöltesztelős ciklusnak viszont a végrehajtás feltételét kell megadni, ami az, hogy nem találtunk egyezést és nem értünk a végére.j:=1; while (j<=length(m)) and (s[i]<>m[j]) do j:=j+1; A ciklus kétféleképpen állhat le. Ha a második feltétel nem teljesül, akkor
s[i] szerepel m -ben a j . helyen, vagyis magánhangzó. Ha az első feltétel nem teljesül, akkor j>length(m) , vagyis végigmentünk m -en, de nem találtunk egyezéstHa végig nincs egyezés, akkor az utolsó lépésben
j=length(m) , és s[i]<>m[j] , tehát j nő eggyel. A következő vizsgálatnál az első részfeltétel hamis lesz, hiszen j>length(m) . Mi a helyzet a második feltétellel? Az értelmetlen, mert m -nek nincs annyiadik karaktere. Nem fog ez hibát okozni a programban?Nem. A Pascal (az alapbeállítások használata esetén) az AND-del összekapcsolt feltételeket úgy vizsgálja, hogy ha az első feltétel hamis, a másodikat már nem ellenőrzi (mert az eredmény úgyis hamis). Hasonlóképpen, az OR-ral összekapcsolt két feltétel közül ha az első igaz, a másodikat már nem vizsgálja. Ezért nem mindegy, hogy a feltételeket milyen sorrendben írjuk be.
Végül a magánhangzóvizsgálatot betesszük egy
mgh nevű függvénybe. A függvényérték típusa most boolean lesz (igaz, ha a karakter magánhangzó).Var s:string; i,c:integer; Function mgh(c:char):boolean; var m:string; j:integer; begin m:='öüóeuioőúaéáűíÖÜÓEUIOŐÚAÉÁŰÍ'; j:=1; while (j<=length(m)) and (c<>m[j]) do j:=j+1; mgh:=(j<=length(m)); end; BEGIN write('Írj be valamit: '); readln(s); c:=0; for i:=1 to length(s) do if mgh(s[i]) then c:=c+1; writeln(c,' magánhangzó volt benne.'); write('nyomj entert'); readln; END. Magyarázat: az eljárásnak a vizsgálandó karaktert paraméterként adjuk át, ez
c lesz, nem keverendő a főprogram számláló c -jével. mgh igazságértéke abból derül ki, hogy j nem lépte túl m hosszát.További hasznos szövegkezelő lehetőségekA Pascal sok szövegkezelő függvényt és eljárást ismer, amelyekkel az egyes karakterek vizsgálatánál gyorsabban megoldhatjuk a feladatokat.Pos( string1,string2) kereső függvény megadja, hogy string1 hányadik karakternél kezdődik string2-ben. 0 lesz a végeredmény, ha nem szerepel benne. Az első előfordulás számít, tehát pos('ép','szép kép') eredménye 3 lesz.Így az előző program függvénye egyszerűbben is megoldható, ciklus nélkül:
mgh:=(pos(c,m)>0) Copy( string,szám,darab) függvény eredménye olyan részszöveg, mely string szám-adik karakterétől kezdődik, és darab hosszú. Vagyis copy('malac',3,2) eredménye a 'la' string.Delete( string,szám,darab) eljárás, mely módosítja string változót (változóparaméter!) úgy, hogy töröl belőle a szám-adiktól kezdve darab karaktert.Insert( mit,mibe,szám) eljárás, mely mibe string típusú változóba szám-adik karakterétől beszúrja mit szöveget.Ne feledkezzünk meg a stringek közötti
+ műveletről, mely az összefűzésüket jelenti.Ez a példa kitörli S stringből az összes kettőspontot:
while pos(':',S)>0 do delete(S,pos(':',S),1); Ez pedig, ha NEV egy "vezetéknév szóköz keresztnév" formátumú string, K-ba beteszi a keresztnevet.
K:=copy(NEV,pos(' ',NEV)+1,length(NEV)- pos(' ',NEV)); Feladatok34. Írj programot, amely a beírt szövegben megszámolja az "e" betűket!megoldás 35. írj programot, amely a B változóba beteszi az A változóban tárolt szöveg megfordítását! 36. Írj programot, amely a beírt szöveget szavanként írja ki!
37. Írj programot, amely a megadott stringből törli a fölösleges szóközöket (ahol egymás mellett több van)!
38. Írj programot, amely a beírt szövegből csak a mássalhangzókat írja ki! Használd benne a fenti mgh függvényt.
39. Írj programot, amely a beírt szöveget "madárnyelven" írja ki! (pl. tulipán->tuvulivipáván)
40. Készíts függvényt, amelynek eredménye a megadott szöveg, az összes "j"-t "ly"-ra cserélve!
|