Ihnen ist das folgende Oberon-Programm als Grundgerüst vorgegeben:
MODULE StringOps; IMPORT Read, Write, Conclusions; CONST NameMaxLen = 30; AddressMaxLen = 80; TYPE Name = ARRAY NameMaxLen OF CHAR; Address = ARRAY AddressMaxLen OF CHAR; VAR name: Name; adresse: Address; PROCEDURE CharCount(s: ARRAY OF CHAR; ch: CHAR): INTEGER; (* Zaehlt, wie oft das Zeichen ch in s vorkommt. Der String * s muss nicht durch ein Null-Byte terminiert sein. In diesem * Fall sollen alle Zeichen des Arrays nach ch durchsucht werden. *) PROCEDURE LowerCase(VAR s: ARRAY OF CHAR); (* Wandelt alle Grossbuchstaben in s in Kleinbuchstaben um. * s muss kein Null-Byte am Ende besitzen. In diesem Fall * Sollen alle Zeichen des Arrays bearbeitet werden. *) BEGIN (*** Name und Adresse einlesen ***) Write.String("Name: "); Read.Line(name); Write.String("Adresse: "); Read.Line(adresse); Write.Ln; (*** Anzahl der a's in Name und Adresse bestimmen ***) Write.String("Anzahl von 'a' in Name und Adresse: "); Write.Int(CharCount(name, "a") + CharCount(adresse, "a"), 0); Write.Ln; Write.Ln; (*** Name und Adresse in Kleinbuchstaben umwandeln ***) Write.String("Name in Kleinbuchstaben: "); LowerCase(name); Write.String(name); Write.Ln; Write.String("Adresse in Kleinbuchstaben: "); LowerCase(adresse); Write.String(adresse); Write.Ln; END StringOps.In diesem Programm sind die beiden Prozeduren
CountChar
und
LowerCase
noch nicht implementiert. Sie haben nun die Aufgabe,
diese beiden Prozeduren zu schreiben und das zugehörige Definitions-Modul
zu erstellen.
(Hinweis: Durch das Importieren des Moduls Conclusions
erhalten
sie auch bei Laufzeitfehlern, die einen Core-Dump verursachen,
eine Fehlermeldung. Beispiele für Fehler dieser Art:
Zugriff auf nicht vorhandenes Array-Element, Verlassen einer
Funktionsprozedur ohne Wert zurückzugeben.
Es empfiehlt sich also dieses Modul zu verwenden!)
Lösung:
DEFINITION StringOps; END StringOps.
MODULE StringOps; IMPORT Read, Write, Conclusions; CONST NameMaxLen = 30; AddressMaxLen = 80; TYPE Name = ARRAY NameMaxLen OF CHAR; Address = ARRAY AddressMaxLen OF CHAR; VAR name: Name; adresse: Address; PROCEDURE CharCount(s: ARRAY OF CHAR; ch: CHAR): INTEGER; (* Zaehlt, wie oft das Zeichen ch in s vorkommt. Der String * s muss nicht durch ein Null-Byte terminiert sein. In diesem * Fall sollen alle Zeichen des Arrays nach ch durchsucht werden. *) VAR i, count : INTEGER; BEGIN count := 0; i := 0; (* bis zu einem Null-Byte, aber nicht weiter * als das letzte Array-Element *) WHILE (i < LEN(s)) & (s[i] # 0X) DO IF s[i] = ch THEN INC(count); END; INC(i); END; RETURN count; END CharCount; PROCEDURE LowerCase(VAR s: ARRAY OF CHAR); (* Wandelt alle Grossbuchstaben in s in Kleinbuchstaben um. * s muss kein Null-Byte am Ende besitzen. In diesem Fall * Sollen alle Zeichen des Arrays bearbeitet werden. *) VAR i: INTEGER; BEGIN i := 0; WHILE (i < LEN(s)) & (s[i] # 0X) DO CASE s[i] OF | "A" .. "Z" : s[i] := CHR(ORD(s[i]) - ORD("A") + ORD("a")); ELSE END; INC(i); END; END LowerCase; BEGIN (*** Name und Adresse einlesen ***) Write.String("Name: "); Read.Line(name); Write.String("Adresse: "); Read.Line(adresse); Write.Ln; (*** Anzahl der a's in Name und Adresse bestimmen ***) Write.String("Anzahl von 'a' in Name und Adresse: "); Write.Int(CharCount(name, "a") + CharCount(adresse, "a"), 0); Write.Ln; Write.Ln; (*** Name und Adresse in Kleinbuchstaben umwandeln ***) Write.String("Name in Kleinbuchstaben: "); LowerCase(name); Write.String(name); Write.Ln; Write.String("Adresse in Kleinbuchstaben: "); LowerCase(adresse); Write.String(adresse); Write.Ln; END StringOps.