HS Ravensburg-Weingarten Schriftlich Prüfung Programmieren Prof. Dr. M. Zeller Datum, Zeit, 08:00 10:00 Uhr (120 min) Aufgabenblätter 16 Seiten (einschl. Deckblatt) erreichbare Punktzahl 58 zugelassene Hilfsmittel A (s. Prüfungsplan) Studiengang Prf. Nr. Raum AI 1804 C004 IK 2138 C004 WI 4004 D002 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! Falls Sie es wünschen, dass Ihr Prüfungsergebnis auf einer Liste mit Matrikelnummern und Zensuren ausgehängt bzw. per Internet veröffentlicht wird, unterschreiben Sie bitte folgende Erklärung. Ich bin damit einverstanden, dass mein Klausurergebnis auf diese Weise veröffentlicht wird. Unterschrift: Bitte haben Sie dafür Verständnis, dass aus Gründen das Datenschutzes keine telefonischen Auskünfte gegeben werden können. Vom Prüfer auszufüllen: Aufgabe 1 2 3 4 5 Summe Max. Punkte 13 6 7 22 10 58 Punkte
Seite 2 (16) Vorbemerkung 1. 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. Tipp: Aufgabe 2 ist m.e. relativ schwierig evtl. sollten Sie sie zuletzt bearbeiten. 2. Bitte nehmen Sie sich sofern noch nicht geschehen in den nächsten Tagen ein paar Minuten Zeit und bewerten Sie die Vorlesung und das Praktikum Programmieren. Die Zugangsdaten zum Umfragesystem der FH wurden Ihnen vor einigen Wochen (28.06.2005) per E-Mail zugesendet. Aufgabe 1 Die Funktion countchar() zählt bestimmte Buchstaben in einem String. Die Funktion hat drei Parameter: start: Der Wert dieses Parameter gibt die Stelle im String line an, ab dem die Funktion zählen soll. cntchar: Der Vergleichsbuchstabe line: Der String in dem die Funktion suchen soll Die Funktion soll im String line nach dem Buchstaben cntchar suchen, aber erst ab der durch start angegebenen Stelle. Wenn start den 4 hat und cntchar den Wert a, soll die Funktion feststellen, wie oft der Buchstabe a ab dem 4.(!) Buchstaben des Strings line vorkommt. Die Funktion zählt also, wie oft der Buchstabe cntchar im Rest von line enthalten ist und gibt diesen Wert zurück (s. Bsp. unten). Das Programm: #include <stdio. h> int countchar( int start, char cntchar, char l i n e [ ] ) { : int main(void){ char testchar = a ; int result ; result = countchar (4, testchar, aabaabab ) ; printf ( \n es sind %d Buchstaben %c enthalten \n, result, testchar ) ; return 0; Ausgabe des Programms: es sind 3 Buchstaben a enthalten
Seite 3 (16) 1.1 (5 Punkte) Vervollständigen Sie die Funktion. Sie dürfen annehmen, dass der String line stets mehr als start Buchstaben enthält. int countchar( int start, char cntchar, char l i n e [ ] ) { int countchar( int start, char cntchar, char l i n e [ ] ) { int sum = 0; int i = start 1; while ( l i n e [ i ]!= 0){ if ( l i n e [ i ] == cntchar ){ sum++; i++; return sum ; 1.2 switch-anweisung (4 Punkte) Ersetzen Sie folgende switch-anweisung durch äquivalente if-anweisungen. Die Variable testchar ist definiert (Datentyp char). switch-anweisung: switch ( testchar ){ case a : printf ( \n found an a ); break ; case b : printf ( \n found a b ); default : printf ( \n found nothing ); Äquivalentes Programmstück mit if-anweisung(en): if ( testchar == a ){
Seite 4 (16) if ( testchar == a ){ printf ( \n found an a ) ; else { if ( testchar == b ){ printf ( \n found a b ) ; printf ( \n found nothing );
Seite 5 (16) 1.3 if-anweisung (4 Punkte) Gegeben ist folgende Formel der Aussagenlogik: (a > b) (b = c) Schreiben Sie eine if-anweisung, die diesen Ausdruck auswertet und entsprechend verzweigt. D. h. wenn die Formel den Wert true liefert, soll das Programmstück den String true auf dem Bildschirm ausgeben, ansonsten den String false. Die Variablen a, b und c sind als int definiert. if { printf ( \n true ) ; else { printf ( \n f a l s e ); if (! ( ( a > b) && (b == c ))){... Schreiben Sie die if-anweisung um, so dass kein!-zeichen vor einer Klammer steht. Die Anweisung soll aber ebenfalls die oben gegebene logische Formel realisieren. if { printf ( \n true ) ; else { printf ( \n f a l s e ); if (( a <= b) (b!= c )) {...
Seite 6 (16) Aufgabe 2 Gegeben ist folgendes C-Programm: #include <stdio. h> char mark = B ; float boo( int num, char test ){ float result = num / test ; printf ( \n result = %f, result ) ; test = mark ; test = NULL; return result ; char far (char mark, int values [ ] ) { float test = boo( values [ 1 ], &mark ) ; printf ( \n test = %f, mark = %c, test, mark ) ; if ( test > 0.5){ values [ 1 ] = 99; else { values [ 1 ] = 1; return mark + 1; int main(void){ char mark = a ; int numbers [ ] = {1, 2, 3, 4 ; int i ; mark = far (mark, numbers ) ; printf ( \n main : mark = %c \n, mark ) ; for ( i = 0; i < 4; i++){ printf ( %d,, numbers [ i ] ) ; return 0; Der ASCII-Code von a ist 97, der von A ist 65. 2.1 (6 Punkte) Welche Ausgabe erzeugt das Programm?
Seite 7 (16) result = 0.0000 test = 0.0000, mark = B Main: mark = C 1, -1, 3, 4
Seite 8 (16) Aufgabe 3 Eine Funktion test() erhält drei int-werte als Parameter. Die Funktion soll die Summe der drei Parameter berechnen und den Durchschnitt. Außerdem soll die Funktion prüfen, ob alle drei Parameter gleich groß sind. Die Funktion soll drei Werte an die aufrufende Funktion zurückliefern: die Summe als int-wert der Durchschnitt als float-wert ein char-wert, der angibt ob alle drei Parameter gleich groß sind ( g für gleich groß, u für ungleich). 3.1 (7 Punkte) Definieren Sie eine geeignete Datenstruktur für den Rückgabewert der Funktion test() und ergänzen Sie die Funktion testresult(). struct testresult { ; typedef struct testresult T RESULT; T RESULT test ( int num1, int num2, int num3){ T RESULT result ; return result ;
Seite 9 (16) struct testresult { int sum ; float average ; char equal ; ; typedef struct testresult T RESULT; T RESULT test ( int num1, int num2, int num3){ T RESULT result ; result. sum = num1 + num2 + num3; result. average = ( float ) result. sum / 3; result. equal = u ; if ((num1 == num2) && (num2 == num3)){ result. equal = g ; return result ;
Seite 10 (16) Aufgabe 4 Gegeben ist folgendes Programm: #include <stdio. h> struct persdata { char name [ 3 0 ] ; int matrnr ; char std gang [ 3 0 ] ; ; typedef struct persdata PERS DATA; struct ergebnis { char fach [ 1 0 ] ; float bewertung ; struct ergebnis rest ; ; typedef struct ergebnis ERGEBNIS; struct student { PERS DATA person ; ERGEBNIS noten ; ; typedef struct student STUDENT; void printstud (STUDENT student ){ : : int main (void){ PERS DATA pers = { Anna, 12345, AI ; ERGEBNIS erg1 = { PROG, 1.7, NULL; ERGEBNIS erg2 = { MATH1, 2.7, NULL; ERGEBNIS erg3 = { ENGL, 3.3, NULL; ERGEBNIS erg4 = { INET1, 2.0, &erg1 ; STUDENT stud = {pers, &erg2 ; erg2. rest = &erg4 ; erg1. rest = &erg3 ; printstud ( stud ) ; p r intf ( \n ) ; return 0;
Seite 11 (16) 4.1 (4 Punkte) Skizzieren Sie die Datenstruktur, die in der Funktion main() angelegt wird. Zeichnen Sie für jede Variable, die eine Struktur darstellt ein Kästchen, für jede Komponente der Struktur ein Fach innerhalb des Kästchens. Zeichnen Sie für jeden Pointer einen Pfeil. Es genügt, wenn Sie die Namen der Variablen und die Namen der Komponenten eintragen. Sie müssen nicht für jede Komponenten den Wert eintragen. Beispiel für ein Variable name der Variable Komponente Komponente : : : 4.2 (5 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? ERGEBNIS pers.std_gang erg1.bewertung &pers PERS_DATA
Seite 12 (16) Ausdruck Typ Variable wenn Variable, welcher Typ? ERGEBNIS X pers.std_gang X char [] erg1.bewertung X float &pers X PERS DATA * PERS_DATA X 4.3 (5 Punkte) Ergänzen Sie die Funktion printstud() gemäß dem vorgegebenen Prototyp. Die Funktion soll zu einem Studenten folgendes auf dem Bildschirm ausgeben: Name und Matrikelnummer zu jedem gespeicherten Prüfungsergebnis den Namen des Faches und die Note Die Datenstruktur darf dabei nicht verändert werden. void printstud (STUDENT student ){ void printstud (STUDENT student ){ ERGEBNIS currenterg = student. noten ; printf ( \n %s,, student. person. name ) ; printf ( Matr. Nr : %d, student. person. matrnr ) ; while ( currenterg!= NULL){ printf ( \n Fach : %s,, currenterg >fach ) ; printf ( Note : %3.1 f, currenterg >bewertung ) ; currenterg = currenterg >rest ;
Seite 13 (16) return ; 4.4 (5 Punkte) Nehmen Sie an, die Prüfungsergebnisse eines Studenten werden in einem Array gespeichert ERGEBNIS ergebnisse[]; bis sie auf eine Datei geschrieben werden. Ergänzen Sie die Funktion saveergs() gemäß dem unten angegebenen Rahmen. Die Funktion soll folgendes leisten: Sie öffnet eine Datei. Der Datei-Name ist der Wert des Parameters filename. Sie schreibt so viele Ergebnisse aus dem Array in die Datei, wie im Parameter cnt angegeben. Sie schließt die Datei wieder. Beispiel: Bei einem Aufruf saveergs(ergebnisse, 3, myfile.dat ); soll die Funktion die ersten 3 Ergebnisse aus dem Array ergebnisse in die Datei myfile.dat schreiben. void saveergs (ERGEBNIS erg [ ], int cnt, char filename [ ] ) { int savecnt ; FILE outfile = fopen (......,... ) ; if (..........){ printf ( \n can t open f i l e %s,...... ) ; savecnt = fwrite (...,......,...,...... ) ; f c l ose (... ) ; return ; void saveergs (ERGEBNIS erg [ ], int cnt, char filename [ ] ) { int savecnt ; FILE outfile = fopen ( filename, wb ); if ( outfile == NULL){ printf ( \n can t open f i l e %s, filename ) ; savecnt = fwrite ( erg, sizeof (ERGEBNIS), cnt, outfile ) ; if ( savecnt < cnt ){
Seite 14 (16) printf ( \n Fehler beim Schreiben ); f c l ose ( outfile ) ; return ; Wie können/sollten Sie prüfen, ob ein Schreibvorgang erfolgreich war? 4.5 (3 Punkte) Das Programm soll nun dynamische Speicherverwaltung einsetzen. Im folgenden Programmfragment sind die Variablen myname, mynum, mystdgang, myfach und mynote passend definiert und mit Werten belegt. Das Programmfragment soll die Daten eines Studenten, der genau eine Prüfung geschrieben hat, in einer dynamischen Variable anlegen. STUDENT mystud = (STUDENT ) malloc ( sizeof (STUDENT) ) ; strncpy (mystud >person. name, myname, 30); mystud >person. matrnr = mynum; strncpy (mystud >person. std gang, mystdgang, 30); mystud >noten >bewertung = mynote ; strncpy (mystud >noten >fach, myfach, 10); Enhält das Programmfragment einen grundsätzlichen Fehler? Wenn ja, welchen, wie lässt er sich beheben? Für die Variable, die das Prüfungsergebnis aufnehmen soll, wird kein Speicherplatz reserviert. Lösung: mystud >noten = (ERGEBNIS ) malloc ( sizeof (ERGEBNIS) ) ;
Seite 15 (16) Aufgabe 5 Folgendes Programm mit einer rekursiven Funktion ist gegeben: #include <stdio. h> void bar ( int start, int end, char l i n e [ ] ) { if ( start >= end ){ return ; printf ( \n bar : %c, %c, l i n e [ start ], l i n e [ end ] ) ; bar ( start + 1, end, l i n e ) ; bar ( start, end 1, l i n e ) ; return ; int main(void){ bar (2, 5, abcdef ); printf ( \n ); return 0; 5.1 (5 Punkte) Welche Ausgabe erzeugt das Programm? Ergänzen Sie die folgenden Zeilen; die ersten 5 Zeilen genügen. bar: bar: bar: bar: bar: bar: XXX bar: XXX bar: c, f bar: d, f bar: e, f bar: d, e
Seite 16 (16) bar: c, e bar: d, e bar: c, d 5.2 (5 Punkte) Gegeben ist die Definition einer rekursiven Funktion: foo(0) = 1 foo(k) = 1 + foo(k 1)/k k N Schreiben Sie eine rekursiven Funktion in C, die die Funktion foo() realisiert. float foo ( int k){ float foo ( int k){ if (k == 0){ / foo (0) = 1 / return 1; return 1 + foo (k 1)/k ; / foo (k) = 1 + foo (k 1)/k /