home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 07 / silben / silben2.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1989-03-02  |  12.6 KB  |  434 lines

  1. (* -------------------------------------------- *)
  2. (*               SILBEN2.PAS                    *)
  3. (* Fügt in eine Textdatei beliebige Zeichen-    *)
  4. (* sequnzen als Trennstellen ein.               *)
  5. (*    (C) 1989 Matthias Uphoff & TOOLBOX        *)
  6. (* -------------------------------------------- *)
  7.  
  8. USES Crt, Turbo3;(* Für Turbo 3.0 auskommentieren *)
  9.  
  10. CONST MaxTS = 40;  (* Max. Anzahl registrierter *)
  11.                    (* Trennungen pro Textzeile  *)
  12.  
  13. TYPE Str255 = STRING[255];
  14.      Str80  = STRING[80];
  15.      TSArray = ARRAY[1..MaxTS] OF INTEGER;
  16.  
  17. VAR Dateiname: Str80;
  18.     Ausdateiname : Str80;
  19.     TrennStr : Str80;
  20.  
  21.  
  22. (* -------------------------------------------- *)
  23. (* Ermittelt alle Silbentrennungen im String    *)
  24. (* Zeile, gibt die Anzahl und  weiterhin eine   *)
  25. (* Liste der Trennstellen Positionen der nach-  *)
  26. (* folgenden Buchstaben ) zurück                *)
  27. (* -------------------------------------------- *)
  28.  
  29. PROCEDURE SilbenTrennung(Zeile: Str255;
  30.                          VAR Anzahl: INTEGER;
  31.                          VAR Trennstelle: TSArray);
  32.  
  33. (* Wortfragmentlisten einbinden *)
  34. (*$I FRAGMENT.INC *)
  35.  
  36. CONST Vokale: SET OF CHAR =
  37.             ['A','E','I','O','U','Y','Ä','Ö','Ü'];
  38.       Buchstaben: SET OF CHAR =
  39.                        ['A'..'Z','Ä','Ö','Ü','ß'];
  40.  
  41. VAR p,   (* momentane Suchposition in der Zeile *)
  42.     Laenge,
  43.     (* Länge eines von der Funktion InListe     *)
  44.     (* identifizierten Wortfragments            *)
  45.     Startp,Endp,   (* Anfang u. Ende des *)
  46.                    (* aktuellen Wortes   *)
  47.     linksp:      INTEGER;
  48.     Konsonanten: SET OF CHAR;
  49.     getrennt:    BOOLEAN;
  50.     (* zeigt an, ob im aktuellen Wort schon eine*)
  51.     (* Trennstelle registriert wurde            *)
  52.  
  53.  
  54. (* -------------------------------------------- *)
  55. (* Zunächst einige lokale Prozeduren/Funktionen *)
  56. (* -------------------------------------------- *)
  57.  
  58. (* Umwandlung in Großbuchstaben mit Umlauten *)
  59.  
  60. PROCEDURE UpperCase(VAR Zeile: Str255);
  61.           VAR i: INTEGER;
  62.  
  63. BEGIN
  64.    FOR i := 1 TO Length(Zeile) DO
  65.       CASE Zeile[i] OF
  66.         'a'..'z': Zeile[i]
  67.                         := Chr(Ord(Zeile[i])-$20);
  68.              'ä': Zeile[i] := 'Ä';
  69.              'ö': Zeile[i] := 'Ö';
  70.              'ü': Zeile[i] := 'Ü';
  71.       END;
  72. END;
  73.  
  74.  
  75. (* Diese Funktion sucht das Wortfragment ab     *)
  76. (* Zeilenposition p in der (untypisiert über-   *)
  77. (* gebenen) Liste. Ist die Suche erfolgreich, so*)
  78. (* wird true zurückgegeben, und die Variable    *)
  79. (* Laenge  enthält  die Anzahl der übereinstim- *)
  80. (* menden  Buchstaben.  Ansonsten  liefert  die *)
  81. (* Funktion false, und Laenge enthält 0.        *)
  82.  
  83. FUNCTION InListe(VAR NoType; p: INTEGER): BOOLEAN;
  84.  
  85. VAR Liste: ARRAY[0..999] OF CHAR ABSOLUTE NoType;
  86.                i,q: INTEGER;
  87.              found: BOOLEAN;
  88. BEGIN
  89.    i := 0;
  90.    q := p;
  91.    found := FALSE;
  92.    WHILE (Liste[i] <= Zeile[q])
  93.          AND (NOT found) DO BEGIN
  94.                     (* Test auf Übereinstimmung *)
  95.       WHILE (Liste[i] = Zeile[q])
  96.              AND (Liste[i] <> ' ') DO BEGIN
  97.          i := i + 1; q := q + 1;
  98.       END;
  99.       IF Liste[i] = ' ' THEN(*Fragment gefunden *)
  100.          found := TRUE
  101.       ELSE BEGIN(* i auf nächsten Fragmentanfang*)
  102.          REPEAT
  103.             i := i + 1;
  104.          UNTIL Liste[i] = ' ';
  105.          i := i + 1;
  106.          q := p;
  107.       END;
  108.    END;
  109.    Laenge := q - p;
  110.    InListe := found;
  111. END;
  112.  
  113.  
  114. (* Hier  wird  die  Position  einer Trennstelle *)
  115. (* p registriert. Einbuchstabige Silben werden  *)
  116. (* nicht erfaßt.                                *)
  117.  
  118. PROCEDURE Registriere(p: INTEGER);
  119.  
  120. BEGIN
  121.    IF (p > Startp+1) AND (p < Endp-1)  THEN BEGIN
  122.                       (* mehr als ein Buchstabe *)
  123.       IF Anzahl < MaxTS THEN BEGIN
  124.          Anzahl := Anzahl + 1;
  125.          Trennstelle[Anzahl] := p;
  126.       END;
  127.       Startp := p; (* Neue Startposition merken *)
  128.    END;
  129.    getrennt := TRUE;
  130. END;
  131.  
  132.  
  133. (* Gibt true zurück, wenn in der Zeile ab       *)
  134. (* Position p ein plausibler Silbenanfang       *)
  135. (* vorliegt.                                    *)
  136.  
  137. FUNCTION Silben_Start(p: INTEGER): BOOLEAN;
  138. BEGIN
  139.   IF (Zeile[p] IN Vokale)
  140.      OR (Zeile[p+1] IN Vokale)
  141.         THEN Silben_Start := TRUE
  142.   ELSE IF InListe(Konsonant_Beginn,p)
  143.           AND (Zeile[p+Laenge] IN Vokale)
  144.           AND (Zeile[p-1] <> 'C')
  145.              THEN Silben_Start := TRUE
  146.   ELSE Silben_Start := FALSE;
  147. END;
  148.  
  149.  
  150. (* Diese  Prozedur untersucht den Wortanfang ab *)
  151. (* Zeilenposition  p. Falls eine Vorsilbe er-   *)
  152. (* kannt wird, setzt sie p auf den Anfang der   *)
  153. (* nächsten Silbe.                              *)
  154.  
  155. PROCEDURE Wortbeginn(VAR p: INTEGER);
  156.  
  157. (*Vorsilbe der Länge lng nur abtrennen, wenn ein*)
  158. (*plausibler Silbenanfang folgt:                *)
  159.      PROCEDURE Vor_Test(lng: INTEGER);
  160.      BEGIN
  161.         IF Silben_Start(p+lng) THEN BEGIN
  162.            p := p + lng;
  163.            Registriere(p);
  164.         END;
  165.      END;
  166.  
  167. BEGIN  (* Wortbeginn *)
  168.    IF NOT InListe(Beginn_Ausnahmen,p) THEN BEGIN
  169.       IF InListe(Vorsilben,p) THEN BEGIN
  170.          Vor_Test(Laenge);
  171.          IF InListe (Vorsilben,p) THEN
  172.            Vor_Test(Laenge);
  173.       END;
  174.       IF InListe(Beginn_Spezial,p) AND
  175.          (Zeile[p+Laenge] <> 'E') THEN
  176.            Vor_Test(Laenge)
  177.       ELSE IF InListe(Beginn_5,p) THEN
  178.              Vor_Test(5)
  179.       ELSE IF InListe(Beginn_4,p) THEN
  180.              Vor_Test(4)
  181.       ELSE IF InListe(Beginn_3,p) THEN
  182.              Vor_Test(3)
  183.       ELSE IF InListe(Beginn_2,p) THEN
  184.              Vor_Test(2)
  185.    END;
  186. END;   (* Wortbeginn *)
  187.  
  188.  
  189. (* Hier  werden  Trennstellen zwischen Vokalen *)
  190. (* behandelt. linksp gibt die Position des     *)
  191. (* ersten Vokals an, rechtsp die Position des  *)
  192. (* nächsten Konsonanten                        *)
  193.  
  194. PROCEDURE Vokal_Vokal(linksp,rechtsp: INTEGER);
  195.  
  196. BEGIN
  197.    IF rechtsp - linksp >= 2 THEN
  198.       (* 2 oder mehr Vokale *)
  199.       IF InListe(Vokal_Trenn,linksp)
  200.          AND (Zeile[linksp-1] <> 'Q') THEN
  201.          Registriere(linksp+1)
  202.       ELSE IF rechtsp - linksp >= 3 THEN
  203.               IF InListe(Diphthong,linksp) THEN
  204.                  Registriere(linksp+2)
  205. END;
  206.  
  207.  
  208. (* Diese Prozedur ermittelt die Trennstelle bei *)
  209. (* einem Konsonant-Vokal-Übergang. linksp gibt  *)
  210. (* die Position des ersten  von eventuell       *)
  211. (* mehreren Konsonanten an, rechtsp die Position*)
  212. (* des nachfolgenden Vokals.                    *)
  213.  
  214. PROCEDURE Konsonant_Vokal(linksp: INTEGER);
  215.         VAR p, rechtsp: INTEGER;
  216.  
  217. BEGIN
  218.  
  219.    (* Trennstellen-Intervall linksp..rechtsp *)
  220.    (* ermitteln                              *)
  221.    rechtsp := linksp;
  222.    WHILE NOT Silben_Start(linksp) DO
  223.      linksp := linksp + 1;
  224.    IF InListe(Konsonant_Ende,rechtsp)
  225.       THEN rechtsp := rechtsp + Laenge;
  226.  
  227.    IF linksp < rechtsp THEN BEGIN
  228.    (* Weitere  Tests,  falls  die Trennstelle *)
  229.    (* nicht eindeutig feststeht:              *)
  230.       p := linksp;
  231.       REPEAT
  232.          IF InListe(Nachsilben,p)
  233.             OR (getrennt
  234.                 AND InListe(Silben_Ende,p-4))
  235.             OR InListe(Vokal_Silben,p)
  236.                THEN linksp := p
  237.          ELSE p := p + 1;
  238.       UNTIL (p > rechtsp) OR (p = linksp)
  239.    END;
  240.  
  241.    Registriere(linksp);
  242.  
  243. END; (* Konsonant_Vokal *)
  244.  
  245.  
  246. (* -------------------------------------------- *)
  247.  
  248. BEGIN  (* der Prozedur Silbentrennung *)
  249.    (* Konsonanten als Differenzmenge, *)
  250.    (* erspart Tipparbeit:             *)
  251.    Konsonanten := Buchstaben - Vokale;
  252.    (* Zeile in Großbuchstaben wandeln:*)
  253.    UpperCase(Zeile);
  254.    (* Zeilenende mit Nicht-Buchstabe  *)
  255.    (* kennzeichnen:                   *)
  256.    Zeile[Length(Zeile)+1] := #0;
  257.    Anzahl := 0;
  258.    Endp := 1;
  259.  
  260.    REPEAT
  261.  
  262.       (* Hier  wird Startp auf den    *)
  263.       (* Anfang und Endp hinter       *)
  264.       (* das Ende des nächsten Wortes *)
  265.       (* der Zeile gesetzt:           *)
  266.       Startp := Endp;
  267.       WHILE NOT (Zeile[Startp] IN Buchstaben)
  268.             AND (Startp <= Length(Zeile)) DO
  269.                 Startp := Startp + 1;
  270.       Endp := Startp;
  271.       WHILE Zeile[Endp] IN Buchstaben DO
  272.         Endp := Endp + 1;
  273.  
  274.       IF Endp - Startp >= 4 THEN BEGIN
  275.          (* Wort lang genug, nach Sil-*)
  276.          (* bentrennungen suchen      *)
  277.          getrennt := FALSE;
  278.          p := Startp;
  279.          (* Wortanfang auf Vorsilben *)
  280.          (* untersuchen:             *)
  281.          Wortbeginn(p);
  282.          (* Nächsten Vokal oder      *)
  283.          (* Wortende suchen:         *)
  284.          WHILE Zeile[p] IN Konsonanten DO
  285.            p := p + 1;
  286.          (* und jetzt weiter bis zum *)
  287.          (* Wortende:                *)
  288.          WHILE Zeile[p] IN Buchstaben DO BEGIN
  289.  
  290.          (* Nächsten Konsonant oder  *)
  291.          (* Wortende suchen, Trenn-  *)
  292.          (* stelle zwischen Vokalen  *)
  293.          (* finden:                  *)
  294.             linksp := p;
  295.             WHILE Zeile[p] IN Vokale DO
  296.               p := p + 1;
  297.             Vokal_Vokal(linksp,p);
  298.  
  299.             (* Nächsten Vokal oder Wortende *)
  300.             (* suchen, Trennstelle bei      *)
  301.             (* Konsonant-Vokal-Übergang:    *)
  302.             linksp := p;
  303.             WHILE Zeile[p] IN Konsonanten DO
  304.               p := p + 1;
  305.             IF Zeile[p] IN Vokale THEN
  306.                Konsonant_Vokal(linksp);
  307.  
  308.          END;  (* While *)
  309.       END;   (* if *)
  310.  
  311.    UNTIL  Startp = Endp;
  312.    (* bis kein Wort mehr vorhanden *)
  313.  
  314. END;  (* von Silbentrennung *)
  315.  
  316.  
  317. (* -------------------------------------------- *)
  318. (* Die folgenden Prozeduren zeigen die Anwendung*)
  319. (* der Silbentrennung in Testroutinen           *)
  320. (* -------------------------------------------- *)
  321.  
  322. (* Hier werden im String Zeile Trennstriche     *)
  323. (* eingefügt und die  Anzahl  der Trennstellen  *)
  324. (* zurückgegeben. Bei einer ck-Trennung wird das*)
  325. (* c durch k ersetzt.                           *)
  326.  
  327. PROCEDURE Trennstriche(VAR Zeile: Str255;
  328.                        VAR Anzahl: INTEGER);
  329.  
  330.           VAR i,j,k:       INTEGER;
  331.               Trennstelle: TSArray;
  332.  
  333. BEGIN
  334.   SilbenTrennung(Zeile,Anzahl,Trennstelle);
  335.   k := 0;
  336.   FOR i := 1 TO Anzahl DO BEGIN
  337.       j := Trennstelle[i] + k;
  338.       Insert(TrennStr,Zeile,j);
  339.       IF (UpCase(Zeile[j-1]) = 'C')
  340.          AND (UpCase(Zeile[j+1]) = 'K')
  341.             THEN Zeile[j-1]
  342.                       := Chr(Ord(Zeile[j-1])+8);
  343.       k := k + 1;
  344.   END;
  345. END;
  346.  
  347.  
  348.  
  349. (* Ausgabe  einer  ASCII-Textdatei  auf  dem   *)
  350. (* Drucker mit sämtlichen Silbentrennungen     *)
  351.  
  352. PROCEDURE DateiUmwandlung(Dateiname,
  353.                           Ausdateiname: Str80);
  354.         VAR Zeile:          Str255;
  355.             AsciiFile:      TEXT;
  356.             AusFile : TEXT;
  357.             gesamt, Anzahl: INTEGER;
  358.  
  359. BEGIN
  360.    Assign(AsciiFile,Dateiname);
  361.    ReSet(AsciiFile);
  362.    Assign(AusFile,Ausdateiname);
  363.    ReWrite(AusFile);
  364.    (* Schmalschrift ein *)
  365.    gesamt := 0;
  366.  
  367.    WHILE NOT Eof(AsciiFile) DO BEGIN
  368.       ReadLn(AsciiFile,Zeile);
  369.       Trennstriche(Zeile,Anzahl);
  370.       gesamt := gesamt + Anzahl;
  371.       WriteLn(AusFile,Zeile);
  372.    END;
  373.    (* Schmalschrift aus *)
  374.    WriteLn(gesamt,
  375.            ' Silbentrennungen vorgenommen');
  376.    Close(AsciiFile);
  377. END;
  378.  
  379. PROCEDURE LiesTrennStr;
  380. VAR ic, count, ErrorCode : INTEGER;
  381.     c : CHAR;
  382.     EinStr : STRING[40];
  383.  
  384.  
  385. BEGIN
  386.   TrennStr := '';
  387.   WriteLn('>    Eingabe der Trennzeichensequenz     <');
  388.   WriteLn('> ASCII-Codes mit führendem "#" eingeben <');
  389.   WriteLn('>      oder normale Zeichen eingeben     <');
  390.   WriteLn('>   Ende der Eingabe mit "leerem" RETURN <');
  391.   WriteLn; WriteLn;
  392.   count := 1;
  393.   REPEAT
  394.     Write('Zeichen ',count,':');
  395.     ReadLn(EinStr);
  396.     IF EinStr <> '' THEN BEGIN
  397.       IF EinStr[1] = '#' THEN BEGIN
  398.         EinStr := Copy(EinStr,2,Length(EinStr)-1);
  399.         Val(EinStr,ic,ErrorCode);
  400.         IF ErrorCode = 0 THEN BEGIN
  401.           TrennStr := TrennStr + CHR(ic);
  402.  
  403.         END
  404.         ELSE BEGIN
  405.           WriteLn('>>>> Fehler bei ASCII-Werteingabe <<<<');
  406.           WriteLn('>>>>     Eingabe wiederholen      <<<<');
  407.           count := count - 1;
  408.         END;
  409.       END
  410.       ELSE BEGIN
  411.         TrennStr := TrennStr + EinStr[1];
  412.       END;
  413.     END;
  414.     count := count + 1;
  415.  UNTIL EinStr = '';
  416. END;
  417. (* ------------------- Main ------------------ *)
  418.  
  419. BEGIN
  420.    WriteLn('--------------------------------');
  421.    WriteLn('          SILBENTRENNER');
  422.    WriteLn('  (C) 1989 TOOLBOX & M.Uphoff');
  423.    WriteLn('--------------------------------');
  424.    WriteLn; WriteLn; WriteLn;
  425.    Write('Eingabe-Datei: ');
  426.    ReadLn(Dateiname);
  427.    Write('Ausgabe-Datei: ');
  428.    ReadLn(Ausdateiname);
  429.    LiesTrennStr;
  430.    DateiUmwandlung(Dateiname,Ausdateiname);
  431. END.
  432.  
  433. (* ------------------------------------------- *)
  434.