Hochschule Ravensburg-Weingarten Schriftliche Prüfung Programmieren Prof. Dr. M. Zeller Datum, Zeit, 08:00 09:30 Uhr (90 min) Aufgabenblätter 14 Seiten (einschl. Deckblatt) erreichbare Punktzahl 54 zugelassene Hilfsmittel A (s. Prüfungsplan) Studiengang Prf. Nr. Raum AI 3600 C004 EI 2210 C004 WI 4104 H061 Name, Vorname: Matrikelnummer: Hinweise: Schreiben Sie bitte Name und Matrikelnummer auf jedes Aufgabenblatt. Schreiben Sie Ihre Lösung zu den Aufgaben auf den freien Platz, direkt anschließend an die Fragestellungen. Wenn Sie zusätzliche Blätter verwenden, so schreiben Sie bitte Name und Matrikelnummer auf jedes Blatt. Schreiben Sie lesbar! Vom Prüfer auszufüllen: Aufgabe 1 2 3 4 Summe Max. Punkte 12 12 20 10 54 Punkte
Seite 2 (14) Vorbemerkung Die Klausur ist ziemlich umfangreich. Lassen Sie sich nicht verunsichern, Sie benötigen nicht alle Punkte für die Note 1,0; Sie benötigen weniger als die Hälfte der Punkte für die Note 4,0. Bei den gezeigten Programmen ist/sind die Zeile(n) #include... nicht abgedruckt. Dies dient dazu, Platz zu sparen; gehen Sie davon aus, dass die Programme jeweils alle notwendigen Bibliotheken einbinden. Aufgabe 1 Gegeben ist ein Programm, das neben der Funktion main() drei weitere Funktionen enthält. int insertspaces (char [ ] ) ; int startswith (char [ ], char [ ] ) ; int commonstart (char [ ], char [ ] ) ; int main (void){ char l ine [ 1 0 0 ] ; char word [ 3 0 ] ; int r esult ; p r intf ( \n Text : ) ; scanf ( %99s, line ) ; p r intf ( \n Text2 : ) ; scanf ( %29s, word ) ; r esult = insertspaces ( line ) ; p r intf ( \n insertspaces : %s %d, line, r esult ) ; r esult = startswith ( line, word ) ; p r intf ( \n startswith : %s %s %d, line, word, r esult ) ; r esult = commonstart ( line, word ) ; p r intf ( \n commonstart : %s %s %d, line, word, r esult ) ; p r intf ( \n ) ; Beispiele für Programmläufe: Text: abc_die-katze_sitzt-im_schnee Text2: abc insertspaces: abc die Katze sitzt im Schnee 5 startswith: abc die Katze sitzt im Schnee abc 1 commonstart: abc die Katze sitzt im Schnee abc 1
Seite 3 (14) Text: abc Text2: abc_die-katze_sitzt-im_schnee insertspaces: abc 0 startswith: abc abc_die-katze_sitzt-im_schnee 0 commonstart: abc abc_die-katze_sitzt-im_schnee 1 Text: abc_die-katze_sitzt-im_schnee Text2: XYZ insertspaces: abc die Katze sitzt im Schnee 5 startswith: abc die Katze sitzt im Schnee XYZ 0 commonstart: abc die Katze sitzt im Schnee XYZ 0 1.1 (3 Punkte) Die Funktion insertspaces(char line[]) ersetzt alle Bindestriche und alle Unterstriche im gegebenen String durch Leerzeichen. Die Buchstaben können Sie in Ihrem Programm in einfachen Anführungszeichen angeben ( -, _, ) oder als Zahlen durch die entsprechenden ASCII-Werte: 45 und 95 für Bindebzw. Unterstrich und 32 für Leerzeichen. Die Funktion gibt die Anzahl der Ersetzungen als Rückgabewert zurück. Vervollständigen Sie die Funktion insertspaces(), definieren Sie dabei keine zusätzlichen Variablen, verwenden Sie keine existierenden Funktionen. int insertspaces (char l i ne [ ] ) { int i int repcount return 1.2 (3 Punkte) Die Funktion startswith(char text [], char word []) prüft, ob der String text mit dem String word beginnt. Wenn dies der Fall ist, gibt die Funktion den Wert 1 zurück, ansonsten den Wert 0. Sie dürfen davon ausgehen, dass der
Seite 4 (14) String text stets länger ist, als der String word. Die Funktion soll sich also nur nach der Länge von word richten. Vervollständigen Sie die Funktion startswith(), definieren Sie dabei keine zusätzlichen Variablen, verwenden Sie keine existierenden Funktionen. int startswith (char text [ ], char word [ ] ) { int i return 1.3 (3 Punkte) Die Funktion commonstart(char text [], char word []) prüft, ob der eine String ein Anfangsstück des anderen ist. Die Funktion arbeitet also wie startswith() aber symmetrisch. Wenn text ein Anfangsstück von word ist oder umgekehrt, gibt die Funktion den Wert 1 zurück, ansonsten den Wert 0. Vervollständigen Sie die Funktion commonstart(), definieren Sie dabei keine zusätzlichen Variablen, verwenden Sie keine existierenden Funktionen. int commonstart (char text [ ], char word [ ] ) { int i return
Seite 5 (14) 1.4 (3 Punkte) Das folgende Programm enthält eine Funktion terminatestring(char line [], char mark). Wenn der String line den Buchstaben mark enthält, so setzt die Funktion die Endemarkierung neu. Die Endemarkierung wird so gesetzt, dass die Funktion printf den Buchstaben mark als letzten Buchstaben ausgibt. Ansonsten bleibt der String unverändert. void terminatestring (char line [ ], char mark ) ; int main (void){ char l ine [ 1 0 0 ] ; p r intf ( \n Eingabe : ) ; scanf ( %99s, line ) ; p r intf ( \n (1) line : %s, l ine ) ; terminatestring ( line, X ) ; p r intf ( \n (2) line : %s, l ine ) ; terminatestring ( line, d ) ; p r intf ( \n (3) line : %s, l ine ) ; Beispiel für einen Programmlauf: Eingabe: abcdefxghidxjk (1) line: abcdefxghidxjk (2) line: abcdefx (3) line: abcd Vervollständigen Sie die Funktion terminatestring(), definieren Sie dabei keine zusätzlichen Variablen, verwenden Sie keine bereits existierenden Funktionen. void terminatestring (char line [ ], char mark){ int i return
Seite 6 (14) Aufgabe 2 Gegeben ist die Definition einer Funktion in drei Abschnitten: rofl(s,u) mit s,u R: rofl(s,u) = s + u und s u für s u > 0 Fall 1 s u und s/u für 10 < s u 0 Fall 2 (s + u)/(s u) sonst Fall 3 Falls s u > 10 gilt (Fall 1 und Fall 2), liefert die Funktion also zwei Werte, ansonsten einen Wert. Im Folgenden sollen Sie die Funktion auf zwei verschiedene Arten implementieren. Beide Teilaufgaben können unabhängig voneinander bearbeitet werden. 2.1 (6 Punkte) Schreiben Sie eine C-Funktion, die die Funktion rof l(s, u) implementiert. Die C-Funktion soll vier Parameter erhalten, der beiden ersten sind die Aufrufparameter s und u, die beiden anderen dienen dazu, das bzw. die Ergebniss(e) in die aufrufende Funktion zu übertragen (call-by-reference). Der Rückgabewert vom Typ int gibt an, welcher der drei oben definierten Fälle vorliegt: 1 für Fall 1, 2 für Fall 2 und 3 für Fall 3. Beispiele für Programmabläufe: Wert für s: 1.5 Wert für u: 5.2 Fall 1, r1: 6.70, r2: -3.70 Wert für s: 12.5 Wert für u: -4.2 Fall 3, r1: -0.16 Ergänzen Sie die Funktion rofl(s,u) und das gegebene Hauptprogramm. int r o f l ( float s, float u,........,....... ){
Seite 7 (14) int main (void){ int f lag ; float res1 ; float res2 ; float s ; float u ; p r intf ( \n Wert für s : ) ; scanf ( %f, &s ) ; p r intf ( \n Wert für u : ) ; scanf ( %f, &u ) ; f lag = r o f l ( s, u,.......,......... ) ; switch ( f lag ){ case 1: p r intf ( Fall 1, r1 : %5.2 f, r2 : %5.2 f, res1, res2 ) ; case 2: p r intf ( Fall 2, r1 : %5.2 f, r2 : %5.2 f, res1, res2 ) ; case 3: p r intf ( Fall 3, r1 : %5.2 f, res1 ) ; default : p r intf ( Fehler ) ; 2.2 (6 Punkte) Schreiben Sie eine C-Funktion, die die Funktion rof l(s, u) implementiert. Die C-Funktion soll zwei Parameter erhalten, die Aufrufparameter s und u. Der Rückgabewert vom Typ ROFL_RESULT enhält drei Komponenten: Zwei Gleitkommanzahlen, um die Ergebniswerte aufzunehmen und eine ganze Zahl um anzuzeigen, welcher der drei oben definierten Fälle vorliegt: 1 für Fall (1), 2 für Fall (2) und 3 für Fall (3). Das Programm soll das gleiche Verhalten zeigen wie in Teilaufgabe 2.1 gezeigt. Definieren Sie eine geeignete Datenstruktur struct rofl_result und ergänzen Sie die Funktion rofl(s,u) und das gegebene Hauptprogramm. struct r o f l r e s u l t { ; typedef.............. ROFL RESULT;
Seite 8 (14) ROFL RESULT r o f l ( float s, float u){ ROFL RESULT r esult ; return int main (void){ ROFL RESULT rvalues ; float s ; float u ; p r intf ( \n Wert für s : ) ; scanf ( %f, &s ) ; p r intf ( \n Wert für u : ) ; scanf ( %f, &u ) ; rvalues = r o f l ( s, u ) ; switch (........... ){ case 1: p r intf ( Fall 1, r1 : %5.2 f, r2 : %5.2 f,......,...... ) ; case 2: p r intf ( Fall 2, r1 : %5.2 f, r2 : %5.2 f,......,...... ) ; case 3: p r intf ( Fall 3, r1 : %5.2 f,...... ) ; default : p r intf ( Fehler ) ;
Seite 9 (14) Aufgabe 3 Gegeben ist folgendes Programm: #define LEN 30 struct person { char givenname [LEN] ; char lastname [LEN] ; int id ; struct person chain ; ; typedef struct person PERSON; PERSON makepersons (char [ ] ) ; int f i l l Person (PERSON, int, FILE ); int savepersons (PERSON, char [ ] ) ; void printperson (PERSON person ) ; int main (void){ char infilename [ ] = personin. dat ; char outfilename [ ] = personout. dat ; int r esult = 0; PERSON persontop ; persontop = makepersons ( infilename ) ; r esult = savepersons ( persontop, outfilename ) ; p r intf ( \n ) ; 3.1 (4 Punkte) Die folgenden Ausdrücke bezeichnen entweder einen Datentyp oder eine Variable. Kreuzen Sie jeweils an, ob es sich bei dem Ausdruck um einen Typ oder um eine Variable handelt. Wenn es sich um eine Variable handelt, so geben Sie auch den Typ der Variablen an. Ausdruck Typ Variable wenn Variable, welcher Typ? struct person persontop outfilename PERSON * persontop->chain
Seite 10 (14) 3.2 (1 Punkt) Die Funktion printperson(person *person) gibt die Werte der Variablen auf die person zeigt aufdem Bildschirm aus. Ergänzen Sie die Funktion an den mit... gekennzeichneten Stellen. void printperson (PERSON person ){ p r intf ( \n %s, person..... ) ; p r intf ( %s, person...... ) ; p r intf ( %d, person..... ) ; return ; 3.3 (5 Punkte) Die Funktion fillperson(person *person,... ) füllt Werte in die Variable, auf die der Parameter person zeigt. Die Funktion liest eine Zeile aus dem gegebenen Stream und kopiert den gelesenen Wert in die Komponente givenname. Anschließend setzt sie ebenso den Nachnamen lastname. Zuletzt setzt sie den Wert der Komponente id. Wenn alle Komponenten mit einem Wert belegt werden konnten, gibt die Funktion den Wert 1 zurück, ansonsten den Wert 0. Ergänzen Sie die Funktion an den mit... gekennzeichneten Stellen. int f i l l Person (PERSON person, int pid, FILE infile ){ char nametxt[len] ; char testptr ; testptr = f gets (.......,....,........ ) ; if (.......... ){ strncpy (.......,....,........ ) ; testptr = f gets (.......,....,........ ) ; if (.......... ){ strncpy (.......,....,........ ) ;......... = pid ; return 1;
Seite 11 (14) 3.4 (5 Punkte) Die Funktion PERSON *makepersons(char []) soll eine Liste von dynamischen Variablen vom Typ PERSON erzeugen und mit Werten füllen. Die Funktion öffnet zunächst eine Text-Datei zum Lesen. In der Datei stehen zeilenweise Namen und Vornamen. Die Funktion legt anschließend in einer Schleife eine neue dynamische Variable an. Die Funktion fillperson() füllt Werte in die neue Variable. Dann wird die neue Variable mit der Liste der Variablen verkettet. Die Funktion printperson() gibt die Werte der Variablen auf dem Bildschirm aus. Wenn der Rückgabewert der Funktion fillperson() nicht 1 ist, verlässt das Programm die Schleife. Ergänzen Sie die Funktion an den mit... gekennzeichneten Stellen. PERSON makepersons (char filename [ ] ) { static int pid = 0; int f lag = 1; PERSON firstperson = NULL; PERSON newperson ; FILE instream = fopen ( filename,..... ) ; if ( instream........ ){ return NULL; while( f lag == 1){ newperson =...... malloc (......... ) ; if ( newperson....... ){ return NULL; f lag = f i l l Person ( newperson, pid, instream ) ; if ( f lag!= 1){ f r ee ( newperson ) ; return firstperson ; pid = pid + 1; newperson >chain =......... ;......... = newperson ; printperson ( firstperson ) ; f c l o s e (....... ) ; return firstperson ;
Seite 12 (14) 3.5 (5 Punkte) Die Funktion savepersons() schreibt alle Variablen, die über den ersten Parameter erreichbar sind, in eine Datei. Die Datei soll dabei neu angelegt bzw. überschrieben werden. Ergänzen Sie die Funktion an den mit... gekennzeichneten Stellen. int savepersons (PERSON plist, char outfilename [ ] ) { FILE outstream = fopen (......,...... ) ; int outcount ; if (........... ){ p r intf ( \n Fehler beim Öffnen der Ausgabe Datei ) ; return 1; while( plist.......... ){ outcount = fwrite (.............. ) ; if ( outcount....... ){ p r intf ( \n Fehler beim Schreiben ) ; return 1;................ ; f c l o s e (........... ) ;
Seite 13 (14) Aufgabe 4 Gegeben ist folgendes Programm: void boo( int start, int end, int numbers [ ] ) { int middle ; if ( start == end){ return ; middle = ( start + end )/2; p r intf ( \n middle : %2d,, middle ) ; p r intf ( numbers [ middle ] : %2d, numbers [ middle ] ) ; boo( start, middle, numbers ) ; boo( middle + 1, end, numbers ) ; return ; int main (void){ int values [ ] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13,14, 15, 16; boo (2, 14, values ) ; 4.1 (6 Punkte) Welche Ausgabe erzeugt das Programm? Ergänzen Sie die folgenden Zeilen an den mit... gekennzeichneten Stellen. middle:..., numbers[middle]:... middle:..., numbers[middle]:... middle:..., numbers[middle]:... middle:..., numbers[middle]:... middle:..., numbers[middle]:... middle:..., numbers[middle]:.... Es genügen die ersten 6 Zeilen das Ausgabe.
Seite 14 (14) 4.2 (4 Punkte) Gegeben ist die Definition einer rekursiven Funktion far(u,d) mit u,d N 0 : { far(u,d) = u + d far(2u,d) + far(u,d/2) für 2u > d sonst Schreiben Sie eine rekursiven Funktion in C, die die Funktion f ar(u, d) realisiert. int far (unsigned int u, unsigned int d){