MODULE BubbleSortFiles; IMPORT Read, Write, Conclusions, ConstStrings, UnixArguments, Strings, Streams, UnixFiles, StreamDisciplines, Process; CONST lengthArray = 10; (* max. 10 Studenten *) lengthName = 40; lengthFach = 30; TYPE Name = ARRAY lengthName OF CHAR; Fach = ARRAY lengthFach OF CHAR; Student = RECORD vorname, nachname: Name; fach: Fach; matrnr, semester: INTEGER; END; Studenten = ARRAY lengthArray OF Student; Compare = PROCEDURE(stud1, stud2: Student):INTEGER; Faecher = ARRAY lengthArray OF Fach; Anzahl = ARRAY lengthArray OF INTEGER; Summe = ARRAY lengthArray OF INTEGER; VAR studis: Studenten; fachis: Faecher; anz: Anzahl; sum: Summe; w1, w2: ConstStrings.String; counter1: INTEGER; counter2: INTEGER; file, string: ARRAY 256 OF CHAR; filestream, stringstream: Streams.Stream; flag: CHAR; PROCEDURE CompareVorname(s1, s2: Student) : INTEGER; (* Vergleicht die Vornamen von 2 Studenten *) VAR str1, str2: ConstStrings.String; i :INTEGER; BEGIN ConstStrings.Create(str1,s1.vorname); ConstStrings.Create(str2,s2.vorname); RETURN ConstStrings.Compare(str1,str2); END CompareVorname; PROCEDURE CompareNachname(s1, s2: Student) : INTEGER; (* Vergleicht die Nachnamen von Studenten *) VAR str1, str2: ConstStrings.String; i :INTEGER; BEGIN ConstStrings.Create(str1,s1.nachname); ConstStrings.Create(str2,s2.nachname); RETURN ConstStrings.Compare(str1,str2); END CompareNachname; PROCEDURE CompareFach(s1, s2: Student) : INTEGER; (* Vergleicht das Studienfach von 2 Studenten *) VAR str1, str2: ConstStrings.String; i :INTEGER; BEGIN ConstStrings.Create(str1,s1.fach); ConstStrings.Create(str2,s2.fach); RETURN ConstStrings.Compare(str1,str2); END CompareFach; PROCEDURE CompareMatr(s1, s2: Student) : INTEGER; (* Vergleicht die Matrikelnummern von 2 Studenten *) BEGIN IF s1.matrnr < s2.matrnr THEN RETURN -1; ELSIF s1.matrnr > s2.matrnr THEN RETURN 1; ELSE RETURN 0; END; END CompareMatr; PROCEDURE CompareSemester(s1, s2: Student) : INTEGER; (* Vergleicht die Anzahl der Semester von 2 Studenten *) BEGIN IF s1.semester < s2.semester THEN RETURN -1; ELSIF s1.semester > s2.semester THEN RETURN 1; ELSE RETURN 0; END; END CompareSemester; PROCEDURE Swap(VAR s1,s2: Student); (* Vertauscht s1 und s2 *) VAR tmp: Student; BEGIN tmp := s1; s1 := s2; s2 := tmp; END Swap; PROCEDURE Sort(VAR std: ARRAY OF Student; cmp: Compare); (* Sortiert nach dem Bubblesort Algorithmus *) VAR i, j, h: INTEGER; BEGIN i := 0; WHILE (i < LEN(std)) DO j := i + 1; WHILE (j < LEN(std)) DO IF cmp(std[i], std[j]) > 0 THEN Swap(std[i],std[j]); END; INC(j); END; INC(i); END; END Sort; PROCEDURE Print(std: ARRAY OF Student); (* Ausgabe *) VAR i: INTEGER; BEGIN i := 0; WHILE (i < LEN(std)) DO Write.String("Student "); Write.Int(i + 1,0); Write.String(": "); Write.String(" "); Write.String(studis[i].vorname); Write.String(" "); Write.String(studis[i].nachname); Write.String(" "); Write.String(studis[i].fach); Write.String(" "); Write.Int(studis[i].matrnr,10); Write.String(" "); Write.Int(studis[i].semester,3); Write.Ln; INC(i); END; END Print; PROCEDURE WriteDaten(f: ARRAY OF CHAR); BEGIN IF UnixFiles.Open(filestream, f, 4+1, 1, NIL) THEN (* Der Wert 5 bedeutet hier, dass die Datei sortiert.txt ueberschrieben * wird (Laenge 0), falls sie existiert bzw. neu angelegt wird, wenn * sie nicht existiert (create = 4) und beschreibbar ist (write = 1). *) counter1 := 0; WHILE counter1 < LEN(studis) DO Write.StringS(filestream, studis[counter1].vorname); Write.StringS(filestream, " "); Write.StringS(filestream, studis[counter1].nachname); Write.StringS(filestream, " "); Write.StringS(filestream, studis[counter1].fach); Write.StringS(filestream, " "); Write.IntS(filestream, studis[counter1].matrnr,10); Write.StringS(filestream, " "); Write.IntS(filestream, studis[counter1].semester,5); Write.LnS(filestream); INC(counter1); END; END; IF Streams.Close(filestream) THEN END; END WriteDaten; BEGIN (* Init... *) UnixArguments.Init("[file] [-vVnNfFmMsS]"); IF ~UnixArguments.GetArg(file) THEN (* Ist FileArgument vorhanden? *) Write.Ln; UnixArguments.Usage; END; (* Studentendaten aus einer Datei lesen *) IF UnixFiles.Open(filestream, file, UnixFiles.read, 1, NIL) THEN StreamDisciplines.SetFieldSep(filestream, ":"); counter1 := 0; WHILE ~filestream.eof DO IF Read.FieldS(filestream, string) THEN Strings.Open(stringstream, string); Read.StringS(stringstream, studis[counter1].vorname); END; IF Streams.Close(stringstream) THEN END; IF Read.FieldS(filestream, string) THEN Strings.Open(stringstream, string); Read.StringS(stringstream, studis[counter1].nachname); END; IF Streams.Close(stringstream) THEN END; IF Read.FieldS(filestream, string) THEN Strings.Open(stringstream, string); Read.StringS(stringstream, studis[counter1].fach); END; IF Streams.Close(stringstream) THEN END; IF Read.FieldS(filestream, string) THEN Strings.Open(stringstream, string); Read.IntS(stringstream, studis[counter1].matrnr); END; IF Streams.Close(stringstream) THEN END; IF Read.FieldS(filestream, string) THEN Strings.Open(stringstream,string); Read.IntS(stringstream,studis[counter1].semester); END; IF Streams.Close(stringstream) THEN END; Read.LnS(filestream); INC(counter1); END; ELSE Write.Ln; Write.String("Datei "); Write.String(file); Write.String(" existiert nicht!"); Write.Ln; Write.Ln; Process.Exit(0); END; IF Streams.Close(filestream) THEN END; (* Pruefen, ob Flags vorhanden *) IF ~UnixArguments.GetFlag(flag) THEN (* Sind Sortargumente vorhanden? *) Write.Ln; Write.String("Keine Sortargumente angegeben, nichts zu tun!"); Write.Ln; Write.Ln; UnixArguments.Usage; ELSE UnixArguments.UngetArg; Write.Ln; Write.String("Die Orginaldaten:"); Write.Ln; Print(studis); END; (* Sortieren der Daten und in Datei schreiben *) WHILE UnixArguments.GetFlag(flag) DO CASE flag OF | "v", "V": Sort(studis, CompareVorname); Write.Ln; Write.String("Sortiert nach Vorname:"); Write.Ln; Print(studis); WriteDaten("SortVorname.txt"); | "n", "N": Sort(studis, CompareNachname); Write.Ln; Write.String("Sortiert nach Nachname:"); Write.Ln; Print(studis); WriteDaten("SortNachname.txt"); | "f", "F": Sort(studis, CompareFach); Write.Ln; Write.String("Sortiert nach Fach:"); Write.Ln; Print(studis); WriteDaten("SortFach.txt"); | "m", "M": Sort(studis, CompareMatr); Write.Ln; Write.String("Sortiert nach Matrikelnummer:"); Write.Ln; Print(studis); WriteDaten("SortMatrikelnummer.txt"); | "s", "S": Sort(studis, CompareSemester); Write.Ln; Write.String("Sortiert nach Semester:"); Write.Ln; Print(studis); WriteDaten("SortSemester.txt"); ELSE Write.Ln; Write.String("Ungültiges Argument (-"); Write.Char(flag); Write.String(")"); Write.Ln; END; END; Write.Ln; Write.String("Die sortierten Daten stehen in den entprechenden Dateien "); Write.Ln; Write.String("SortNachname.txt, SortVorname.txt, ... bzw. SortSemester.txt!"); Write.Ln; Write.Ln; (* Durchschnittliche Studienzeit berechnen *) (* Hierzu ein Array anlegen, in dem alle Studienfaecher, die in *) (* den Daten vorkommen, abgespeichert werden. *) (* Arrays mit null Werten initialisieren *) counter1 := 0; WHILE counter1 < LEN(fachis) DO fachis[counter1] := "null"; anz[counter1] := 0; sum[counter1] := 0; INC(counter1); END; counter1 := 0; WHILE counter1 < LEN(studis) DO ConstStrings.Create(w1, studis[counter1].fach); counter2 := 0; LOOP ConstStrings.Create(w2, fachis[counter2]); (* Falls das Fach bereits im Array eingetragen ist *) IF (ConstStrings.Compare(w1,w2) = 0) THEN INC(anz[counter2]); sum[counter2] := sum[counter2] + studis[counter1].semester; EXIT; END; (* Falls das Fach immer Array noch nicht eingetragen ist *) IF (fachis[counter2] = "null") THEN fachis[counter2] := studis[counter1].fach; INC(anz[counter2]); sum[counter2] := sum[counter2] + studis[counter1].semester; EXIT; END; (* Dieser Fall sollte eigentlich nie eintreten *) IF (counter2 = lengthArray) THEN Write.String("FEHLER IM SYSTEM"); EXIT; END; INC(counter2); END; INC(counter1); END; (* Durchschnittswerte berechnen und ausgeben *) counter1 := 0; WHILE counter1 < LEN(fachis) DO IF (fachis[counter1] # "null") THEN Write.String(fachis[counter1]); Write.String(": Mittlere Studienzeit: "); Write.Real(sum[counter1] / anz[counter1], 2); Write.Ln; END; INC(counter1); END; Write.Ln; Write.Ln; END BubbleSortFiles.