program TYPETEXT; (****************************************************************************) (********************** D‚claration de l'UNIT TYPETEXT *********************) (****************************************************************************) UNIT Typetext : class; VAR contenu : arrayof char, (* tableau contenant la valeur de la chaŒne de caractŠres *) position : integer; (* entier indiquant la position courante dans le tableau pr‚c‚dent (indice d'un champ) *) (**********************************************************************) (******************** D‚claration de l'UNIT Ecrire ********************) (**********************************************************************) (******** On affiche la valeur du type contenu dans "contenu" ********) (**********************************************************************) UNIT Ecrire : procedure; (* si la variable contenu vaut none, cela signifie qu'elle n'a pas ‚t‚ encore cr‚‚e, donc l'affichage est vierge : on sort de la proc‚dure. sinon du premier indice du tableau (1) jusqu'… la taille du tableau, on lit chaque caractŠre au fur et … mesure et on les affiche. *) VAR i:integer; BEGIN if (contenu=none) then exit fi; for i:=1 to upper(contenu) do write(contenu(i)) od; writeln; END ecrire; (**********************************************************************) (******************* D‚claration de l'UNIT Lecture *******************) (**********************************************************************) (******* On saisie les caractŠres d‚finissant la valeur du type *******) (**********************************************************************) UNIT Lecture : procedure(l:integer); (* On ignore la taille de la chaŒne de caractŠres que va saisir l'utilisateur. Il est donc impossible de cr‚er le tableau contenu car on ne connaŒt pas sa taille. Le principe retenu est le suivant : On cr‚e un tableau temporaire appel‚ temp ayant une taille al‚atoire mais d‚finie par le programmeur, c'- est la variable taille initialis‚e ici … 10. Au fur et … mesure que l'utili- sateur saisi les caractŠres composant sa chaŒne, chacun de ces derniers est mis dans le tableau temp. Si ce tableau est plein, alors par r‚cursivit‚, on rapelle cette proc‚dure Lecture avec pour paramŠtre le nombre de carac- tŠres d‚j… saisi et ainsi de suite. Une fois la saisie finie (rep‚r‚e par 13, le code de la touche ENTER ou RETOUR-CHARIOT), on cr‚e notre tableau contenu ayant pour taille la valeur de la variable l pass‚e en paramŠtre. Pour chaque proc‚dure appel‚e, on part de la fin de leur tableau temp o— on lit les caractŠres que l'on va affecter dans le tableau contenu mais en partant aussi de la fin. *) CONST taille = 10; VAR temp : arrayof char, cpt,i : integer; BEGIN array temp dim(1:taille); (* tableau interne *) cpt := 1; do i:=inchar; (* lecture d'une touche *) write(chr(i)); if ( i = 13) (* si enter ou retour-chariot *) then l := l + cpt -1 ; if (l=0) (* la chaŒne saisie est vide *) then position := 0; (* no elements have been read *) exit; fi; array contenu dim(1:l); (* cr‚ation du tableau contenu *) for i:=(cpt-1) downto 1 do contenu(l) := temp(i); (* remplissage du tableau contenu *) l := l -1; od; exit; (* fin du remplissage donc on peut sortir *) fi; temp(cpt) := chr(i); (* affectation du caractŠre lu dans le tableau *) if (cpt=taille) (* si le tableau est plein, alors on cr‚e *) then (* un autre tableau temporaire par r‚cur- *) l := l + cpt; (* ssivit‚ pour pouvoir sauvegarder les *) call Lecture(l); (* autres caractŠres composant la chaŒne *) for i:=taille downto 1 do contenu(l) := temp(i); l := l - 1; od; exit; fi; cpt := cpt +1; od; position := 1; END Lecture; (**********************************************************************) (******************** D‚claration de l'UNIT Concat ********************) (**********************************************************************) (******* On retourne une variable r‚sultant de la concat‚nation *******) (***************** de deux varibles de type Typetext ******************) (**********************************************************************) UNIT Concat : procedure(t:typetext) ; (* On concatŠne la variable courante avec une variable t d‚finie par l'utili- sateur. - si t est vide, la concat‚nation est inutile. - si la variable courante est vide, la concat‚nation repr‚sente alors la variable … concat‚ner. - sinon, on r‚cupŠre la valeur de la variable contenu du type courant dans un tableau temporaire. On recr‚e cette variable contenu mais avec une taille de longueur ‚gale … la taille du tableau temporaire plus la taille du tableau contenu de la variable … concat‚ner (t). * On r‚‚crit le tableau temporaire dans le nouveau tableau contenu. * On d‚truit le tableau temporaire * On ‚crit le tableau contenu de la variable t dans le nouveau tableau. *) VAR i,j : integer, temp : arrayof char; BEGIN if (t=none) then exit fi; (* la concat‚nation avec une chaŒne vide ne donne rien; on sort donc de la proc‚dure *) if (contenu=none) (* si la variable … laquelle se fait la *) then (* concat‚nation est vide, alors son *) contenu := t.contenu; (* contenu est celle de la variable … *) exit; (* concat‚ner. *) fi; temp := copy(contenu); kill(contenu); array contenu dim (1:upper(temp)+upper(t.contenu)); (* Cr‚ation de la variable contenu avec sa nouvelle taille *) for i:=1 to upper(temp) do (* recopie du tableau temporaire *) contenu(i) := temp(i) od; kill(temp); for j:=1 to upper(t.contenu) do (* recopie de la chaŒne de caractŠ- *) contenu(j+i-1) := t.contenu(j); (* res caract‚risant la variable t *) od; END concat; (**********************************************************************) (********************* D‚claration de l'UNIT Copie ********************) (**********************************************************************) (**** Cette fonction renvoie une sous-chaŒne de la variable contenu ***) (**********************************************************************) UNIT Copie : Function(number:integer) : typetext; (* A partir de la position courante dans le tableau, on recopie la chaŒne de caractŠres sur une longueur number. - Si la chaŒne de caractŠres dans laquelle se fait la recherche est vide ou si la longueur de recopie est nulle ou n‚gative, la proc‚dure ne donne rien, donc on sort. - Sinon, on cr‚e une nouvelle variable typetext dont sa variable contenu a pour longueur la variable number; cependant si longueur de recopie, … partir de la position courante atteint la fin de la chaŒne de caractŠres, alors la longueur de la variable contenu a une longueur ‚gale … la taille de la chaŒne de caratŠres moins la position courante plus 1. Ensuite on recopie les differents caractŠres … partir de la position cou- rante dans le tableau contenu de la variable … retourner *) VAR i : integer; BEGIN if ( (contenu=none) or (number<=0) ) then exit fi; result := new typetext; if (position + number - 1 > upper(contenu)) then number := upper(contenu) - position + 1 fi; array result.contenu dim(1:number); for i:=1 to number do result.contenu(i) := contenu(position+i-1); od; END Copie; (**********************************************************************) (**********************************************************************) (******************** D‚claration de l'UNIT Insert ********************) (**********************************************************************) (********** On insere des caractŠres dans le tableau contenu **********) (**********************************************************************) UNIT Insert : procedure(t:typetext); (* A partir de la position courante du type courant, on insŠre la chaŒne de caractŠres repr‚sent‚e par t. Si la chaŒne … ins‚rer est vide, on quitte la proc‚dure. Si la chaŒne courante, c'est-…-dire qui va recevoir la chaŒne t, est vide alors le r‚sultat est cette chaŒne t. Sinon -On cr‚e une tableau temporaire de longueur ‚gale … la taille de la chaŒne de caractŠres … ins‚rer plus la taille de la chaŒne de caractŠres dans la- quelle va se faire l'insertion. -On recopie dans le tableau temporaire la chaŒne, qui ˆtre modifi‚e, de son d‚but jusqu'… sa position courante moins un. -On y recopie ensuite la chaŒne t. -On y copie enfin le reste de la premiŠre chaŒne, c'est-…-dire de la posi- tion courante plus un jusqu'… sa fin. *) VAR temp:arrayof char, l,i,j : integer; BEGIN if (t=none) then exit fi; if (contenu=none) then contenu := t.contenu; exit; fi; l := upper(contenu)+upper(t.contenu); array temp dim (1:l); for i:=1 to (position-1) do temp(i) := contenu(i) od; for j:=1 to upper(t.contenu) do temp(i) := t.contenu(j); i := i + 1 ; od; for j:= position to upper(contenu) do temp(i) := contenu(j); i := i + 1 ; od; kill(contenu); contenu := copy(temp); kill(temp); END Insert; (**********************************************************************) (******************** D‚claration de l'UNIT Delete ********************) (**********************************************************************) (************* On efface des caractŠres du tableau contenu ************) (**********************************************************************) UNIT Delete : procedure(number:integer); VAR i,j,l : integer; VAR temp : arrayof char; BEGIN if ( (contenu=none) or (number<=0) ) (* ChaŒne vide ou longueur incorrect *) then exit; fi; if ( position + number - 1 > upper(contenu) ) then l := position - 1 else l := upper(contenu) - number; fi; array temp dim (1:l); for i:=1 to (position-1) do temp(i) := contenu(i); od; for j:=(position + number) to upper(contenu) do temp(i) := contenu(j); i := i + 1; od; kill(contenu); contenu := copy(temp); kill(temp); END Delete; (**********************************************************************) (************** D‚claration de l'UNIT Rechercher_Position *************) (**********************************************************************) (**** On recherche une suite de caractŠres dans le tableau contenu ****) (**********************************************************************) UNIT Rechercher_Position : function (s:typetext) : integer; (* la recherche de la chaŒne de caractŠres s revient … comparer tous les ‚l‚ments du tableau s.contenu avec ceux du tableau contenu de la variable courante mais … partir d'une position pr‚cise. On recherche le caractŠre correspondant … l'indice 1 de s.contenu dans le tableau contenu courant, c'est-…-dire de 1 … un certain indice. A partir de cet indice, on compare les caractŠres des indices suivants avec ceux du s.contenu variant donc de 2 jusqu'… trouver un caractŠre different ou la fin du tableau ce qui signifierait que la chaŒne a ‚t‚ trouv‚e, au- quel cas on retourne la valeur de l'entier correspondant … l'indice de commencement de recherche dans contenu. Si la chaŒne n'est pas trouv‚e, on retourne 0. *) VAR i,j,temp : integer, fin,occurence : boolean; BEGIN if (contenu = none) then result := 0; exit; fi; i := 1; j := 1; temp := 0; fin := false; occurence := false; while( ( i <= upper(contenu) ) and not(fin) ) do if (contenu(i) = s.contenu(j)) then j := j+1 else j := 1 fi; if (contenu(i) = s.contenu(1)) then if not(occurence) then temp := i; occurence := true; else if (j=1) then i := temp; occurence := false; fi; fi; fi; if (j>upper(s.contenu)) then fin := true; else i := i + 1; fi; od; if fin then result := i - upper(s.contenu) + 1 else result := 0 fi; END Rechercher_Position; (**********************************************************************) (******************** D‚claration de l'UNIT Suivant *******************) (**********************************************************************) (* On incr‚mente la variable position rep‚rant la position courante *) (********************* du tableau contenu *********************) (**********************************************************************) UNIT Suivant : procedure ; (* On incr‚mente simplement la variable position, sauf si : - on est … la fin de la chaŒne de caractŠres - si cette chaŒne est vide *) BEGIN if (contenu=none) then exit fi; if ( position < upper(contenu) ) then position := position +1 fi; END Suivant; (**********************************************************************) (******************* D‚claration de l'UNIT Precedent ******************) (**********************************************************************) (** On d‚cr‚mente la variable position rep‚rant la position courante **) (************************ du tableau contenu *************************) (**********************************************************************) UNIT Precedent : procedure ; (* On d‚cr‚mente simplement la variable position, sauf si : - on est au d‚but de la chaŒne de caractŠres - si cette chaŒne est vide *) BEGIN if (contenu=none) then exit fi; if ( position <> 1 ) then position := position -1 fi; END Precedent; (**********************************************************************) (******************* D‚claration de l'UNIT Majuscule ******************) (**********************************************************************) (* On transforme les lettres minuscules du tableau contenu en lettres *) (******** majuscules sur une longueur d‚finie par l'utilisateur *******) (**********************************************************************) (***************************************************************************** Si la chaŒne de caractŠres est vide, le traitement est inutile. Sur une longueur l, on va transformer les lettres minuscules en majuscules pour la proc‚dure Majuscule, et les lettres majuscules en minuscules pour la proc‚dure Minuscules. Pour ces deux traitements l'algorithme est le mˆme sauf pour la conversion. Il repose sur la constatation suivante : - la conversion ne marche que pour les lettres alphab‚tiques … savoir : * de 'a'..'z' pour la proc‚dure Majuscule * de 'A'..'Z' pour la proc‚dure Minuscule - les caractŠres ascii ont une valeur d‚cimale * de 65 --> 90 pour 'A' --> 'Z' * de 97 --> 122 pour 'a' --> 'z' - le passage, pour la valeur d‚cimale du code ascii, : * d'une lettre Majuscule … une lettre Minuscule est de +32 * d'une lettre Minuscule … une lettre Majuscule est de -32 - Deux fonctions sont disponibles en loglan, avec int un entier (INTEGER) et chr un caractŠre (CHAR) * chr(int) = car : retourne le caractŠre car du code ascii int. * ord(car) = int : retourne le code ascii int du caractŠte car. Il suffit donc, suivant la proc‚dure appel‚, de v‚rifier si le caractŠre correspond bien … l'intervalle … traiter, puis de faire la conversion, … savoir r‚cup‚rer le code ascii du caractŠre et de lui ajouter ou retancher 32 et de reconvertir dans le caractŠre correspondant … cette nouvelle va- leur calcul‚e. *****************************************************************************) UNIT Majuscule : procedure(l:integer); VAR i,pos,value : integer; BEGIN if (contenu=none) then exit fi; pos := position; for i:=1 to l do if (pos>upper(contenu)) then exit fi; value := ord(contenu(pos)); if ((value>=97) and (value<=122)) then contenu(pos) := chr(value-32) fi; pos := pos + 1; od; END Majuscule; (**********************************************************************) (******************* D‚claration de l'UNIT Minuscule ******************) (**********************************************************************) (* On transforme les lettres majuscules du tableau contenu en lettres *) (******* minuscules sur une longueur d‚finie par l'utilisateur ******) (**********************************************************************) UNIT Minuscule : procedure(l:integer); (* voir explication dans la unit Majuscule *) VAR i,pos,value : integer; BEGIN if (contenu=none) then exit fi; pos := position; for i:=1 to l do if (pos>upper(contenu)) then exit fi; value := ord(contenu(pos)); if ((value>= 65) and (value<=90)) then contenu(pos) := chr(value+32) fi; pos := pos + 1; od; END Minuscule; (**********************************************************************) (*************** D‚claration de l'UNIT Position_courante **************) (**********************************************************************) (****** On transmet la position courante dans le tableau contenu ******) (**********************************************************************) UNIT Position_courante : function : integer; (* On retourne la valeur de la position courante du type concern‚. Il suffit de donner la valeur de la variable position. Si la chaŒne concern‚e est vide, on retourne 0 *) BEGIN if (contenu<>none) then result := position else result := 0 fi; END Position_Courante; (**********************************************************************) (*************** D‚claration de l'UNIT Nouvelle_Position **************) (**********************************************************************) (******* On change la position courante dans le tableau contenu *******) (**********************************************************************) UNIT Nouvelle_Position : procedure(pos:integer); (* A partir d'une position, repr‚sent‚e par la variable pos donn‚e par l-utili sateur, on repositionne la position courante dans le tableau contenu sur un autre ‚l‚ment de celui-‡i. Cela revient donc … affecter … la variable position cette valeur pos. Cependant, - Si la chaŒne est vide ou si la nouvelle position d‚sir‚e est inf‚rieure ou ‚gale … 0, on ne fait rien. - Si la nouvelle position est sup‚rieure … la taille de la chaŒne de ca- ractŠres, on se positionne sur le dernier ‚l‚ment de cette chaŒne. *) BEGIN if ( (pos <= 0) or (contenu=none) ) then exit fi; if (upper(contenu) < pos) then position := upper(contenu) else position := pos fi; END Nouvelle_Position; (**********************************************************************) (******************** D‚claration de l'UNIT Length ********************) (**********************************************************************) (********** On transmet la longueur dans le tableau contenu ***********) (**********************************************************************) UNIT Length : function : integer; (* On retourne la longueur de la chaŒne de caractŠres caract‚risant le type courant. Il suffit de donner la taille de la variable contenu le caract‚- risant, sauf si la chaŒne est vide, dans quel cas on retourne 0. *) BEGIN if (contenu=none) then result := 0 else result := upper(contenu); fi; END Length; END typetext; (****************************************************************************) (***************** Fin de la D‚claration de l'UNIT TYPETEXT ****************) (****************************************************************************) (****************************************************************************) (************************ Proc‚dures et fonctions *************************) (****************************************************************************) (***************************************************************************** Cette fonction retourne la valeur d‚cimale correspondant … la touche s‚lectionn‚e *****************************************************************************) UNIT Inchar : IIUWgraph function : integer; VAR i:integer; BEGIN do i:=inkey; if (i<>0) then exit fi; od; result := i; END Inchar; (***************************************************************************** Cette proc‚dure efface l'‚cran *****************************************************************************) UNIT clear : procedure ; BEGIN write(chr(27),"[2J"); END clear; (***************************************************************************** Cette proc‚dure positionne le curseur l'‚cran em mode texte (80 x 25) *****************************************************************************) UNIT SetCursor : procedure(row,column : integer); VAR c,d,e,f : char, i,j : integer; BEGIN i := row div 10; j := row mod 10; c := chr(48+i); d := chr(48+j); i := column div 10; j := column mod 10; e := chr(48+i); f := chr(48+j); write(chr(27),"[",c,d,";",e,f,"H"); END SetCursor; (***************************************************************************** Cette proc‚dure initialise l'‚cran. Elle : - affiche le menu - pr‚pare l'‚cran pour y ‚crire les diff‚rents r‚sultats *****************************************************************************) UNIT initialisation : procedure ; VAR i,j : integer; BEGIN call clear; write("É"); for i:=1 to 78 do write("Í") od; write("»"); writeln(" 1. Saisie du TEXTE1 2. Saisie du TEXTE2"); writeln(" 3. Longueur du TEXTE1 4. ConcatŠne le TEXTE1 avec le TEXTE2"); writeln(" a. Position courante dans TEXTE1 n. Nouvelle position dans TEXTE1"); writeln(" s. Position suivante dans TEXTE1 p. Position pr‚c‚dente dans TEXTE1"); writeln(" c. Copie une chaŒne du TEXTE1 d. Supression d'une chaŒne dans TEXTE1"); writeln(" i. Insertion d'une chaŒne dans TEXTE1"); writeln(" u. Conversion de majuscules en minuscules"); writeln(" m. Conversion de minuscules en majuscules ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"); writeln(" r. Recherche la position d'une chaŒne dans TEXTE1 º ESC. Quitter "); write("È"); for i:=1 to 78 do write("Í") od; write("¼"); for j:=0 to 1 do for i:=0 to 8 do call setcursor(2+i,1+79*j); write("º"); od; od; call setcursor(12,1); write("Question : "); call setcursor(15,1); write("R‚sultat : "); call setcursor(17,1); writeln("TEXTE1"); for i := 1 to 80 do write("Ä") od; call setcursor(23,1); for i := 1 to 80 do write("Ä") od; call setcursor(24,32); writeln("Votre choix : "); (* attente d'un choix du menu *) call SetCursor(24,46); END initialisation; (***************************************************************************** Cette proc‚dure affiche certains messages et r‚initialise l'‚cran pour pouvoir y afficher les prochains r‚sultats *****************************************************************************) UNIT reinitialisation : procedure(inout choix:integer); VAR i : integer; BEGIN if ( (choix=49) or (choix=52) or (choix=100) or (choix=105) or (choix=109) or (choix=117) ) then call setcursor(19,1); for i:=1 to 150 do write(" ") od; call setcursor(19,1); if (t1<>none) then call t1.ecrire fi; call SetCursor(15,12); write("Voir TEXTE1"); fi; call SetCursor(24,46); writeln(" "); call SetCursor(24,46); choix := inchar; writeln(chr(choix)); call setcursor(12,11); for i := 1 to 180 do write(" ") od; call setcursor(15,12); for i := 1 to 80 do write(" ") od; END reinitialisation; (**************************************************************************** Cette proc‚dure traite la demande de l'utilsateur et appelle donc les proc‚dures ou fonctions correspondantes. On travaille sur le code ascii des touches s‚lectionn‚es. 27 ---> touche ESC 49 ---> touche 1 50 ---> touche 2 51 ---> touche 3 52 ---> touche 4 97 ---> touche a 99 ---> touche c 100 ---> touche d 105 ---> touche i 109 ---> touche m 110 ---> touche n 112 ---> touche p 114 ---> touche r 115 ---> touche s 117 ---> touche u *****************************************************************************) UNIT traiter_choix : procedure ; VAR posit,num,choix : integer, s:string; BEGIN choix := inchar; write(chr(choix)); do call setcursor(12,12); case choix when 27 : call clear; return; when 49 : writeln("Saisie de TEXTE1"); call setcursor(19,1); t1 := new typetext; call t1.Lecture(0); when 50 : writeln("Saisie de TEXTE2"); call SetCursor(15,12); t2 := new typetext; call t2.Lecture(0); when 51 : writeln("Longueur de TEXTE1"); call SetCursor(15,12); if (t1=none) then writeln('0') else writeln(t1.length) fi; when 52 : writeln("ConcatŠne TEXTE1 avec TEXTE2"); call setcursor(19,1); if (t1=none) then t1:=t2 else call t1.concat(t2) fi; when 97 : writeln("Position courante dans TEXTE1"); call SetCursor(15,12); if (t1=none) then writeln("0") else writeln(t1.Position_Courante) fi; when 99 : Writeln("Copie une chaŒne de TEXTE1"); Writeln("Donnez la longueur de la chaŒne … retourner : "); call Setcursor(13,47); readln(num); call SetCursor(15,12); if (t1<>none) then t3 := t1.Copie(num); if (t3<>none) then call t3.ecrire else writeln("ChaŒne vide") fi; else writeln("ChaŒne vide"); fi; when 100 : Writeln("Suppression d'une chaŒne de TEXTE1"); Writeln("Donnez la longueur de la chaŒne … supprimer : "); call SetCursor(13,47); readln(posit); if (t1<>none) then call t1.delete(posit); fi; when 105 : Writeln("Ins‚rer une chaŒne dans TEXTE1"); Writeln("Entrez la chaŒne … ins‚rer : "); call SetCursor(13,30); t3 := new typetext; call t3.Lecture(0); call SetCursor(15,12); if (t1<>none) then call t1.Insert(t3) else t1 := t3 fi; when 109 : Writeln("Conversion de lettres minuscules en majuscules"); Writeln("Donnez la longueur de la chaŒne … modifier : "); call SetCursor(13,46); readln(num); if (t1<>none) then call t1.majuscule(num); fi; when 110 : writeln("Saisie de la nouvelle position dans TEXTE1"); writeln("Donnez la nouvelle position : "); call SetCursor(13,31); if (t1<>none) then readln(posit); call t1.Nouvelle_Position(posit); call SetCursor(15,12); writeln(t1.position); else writeln("Texte1 non d‚fini"); fi; when 112 : writeln("Position pr‚c‚dente … la position courante dans TEXTE1"); call SetCursor(15,12); if (t1<>none) then call t1.Precedent; writeln(t1.position); else writeln("0"); fi; when 115 : writeln("Position suivante … la position courante dans TEXTE1"); call SetCursor(15,12); if (t1<>none) then call t1.Suivant; writeln(t1.position); else writeln("0"); fi; when 114 : writeln("Recherche de la position d'une sous-chaŒne dans TEXTE1"); writeln("Donnez la valeur de la sous-chaŒne : "); call SetCursor(13,38); if (t1<>none) then t3 := new typetext; call t3.Lecture(0); num := t1.Rechercher_Position(t3); call SetCursor(15,12); writeln(num); else writeln("TEXTE1 non d‚fini"); fi; when 117 : writeln("Conversion de lettres majuscules en minuscules"); writeln("Donnez la longueur de la chaŒne … modifier : "); call SetCursor(13,46); readln(num); if (t1<>none) then call t1.minuscule(num); fi; otherwise writeln("Mauvaise touche");; esac; call reinitialisation(choix); od; END traiter_choix; (****************************************************************************) (****************************************************************************) (* PROGRAMME PRINCIPAL *) (****************************************************************************) VAR t1,t2,t3 : typetext; BEGIN call initialisation; (* affichage du menu *) call traiter_choix; (* traitement de la demande de l'utilisateur *) END TYPETEXT; (****************************************************************************)