Du befindest dich hier: FSI Informatik » Prüfungsfragen und Altklausuren » Prüfungen im Bachelor-Studium (1. - 5. Semester) » Lösungsvorschlag   (Übersicht)

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

pruefungen:bachelor:2014s-sp-klausur-loesung [28.07.2015 15:07] – angelegt Anolapruefungen:bachelor:2014s-sp-klausur-loesung [28.07.2015 15:13] (aktuell) Anola
Zeile 103: Zeile 103:
         }         }
                  
-        struct data *video = malloc (sizeof(struct data));//warum mallocen und net aufm stack anlegen  struct data video;//genau so hätte ich es auch gemacht knoti^^+        struct data *video = malloc (sizeof(struct data));
                  
         // Videobilder einlesen und in den Puffer schreiben         // Videobilder einlesen und in den Puffer schreiben
                  
         size_t bytesRead = 0;         size_t bytesRead = 0;
-        while((bytesRead = fread(video->frame, sizeof(byte), 307200, reader)) != 0){ // ich dachte man gibt als Paketgroesse 640 an und dass man 480 pakete lesen will+        while((bytesRead = fread(video->frame, sizeof(byte), 307200, reader)) != 0){ 
                  
  
-            if(bytesRead < 307200){//braucht man hier net eher feof() und kann die byte anzahl einfach untern tisch kehren^^//jo +            if(bytesRead < 307200){
- +
-                    video->eof = 1;//dann brauchst du aber auch noch ein break; oder so+
  
 +                    video->eof = 1;
             }else{             }else{
  
Zeile 125: Zeile 124:
             jbPut(video);             jbPut(video);
  
-            //wenn mit malloc fehlt free, jbPut/Get kopiert den Inhalt, nicht den pointer+  
  
-            video = malloc (sizeof(struct data));//warum?, stack sollte reichen+            video = malloc (sizeof(struct data));
  
                                  
Zeile 134: Zeile 133:
  
                  
-        errno = phtread_join(tid,NULL);//rfür was braucht man pthread_join?//damit wartet man auf die Terminierung des anderen Threads. Das steht so in der Aufgabe "wartet auf dessen Terminierung und beendet sich dann" +        errno = phtread_join(tid,NULL);
                  
         if(errno != 0){          if(errno != 0){ 
Zeile 149: Zeile 148:
         }         }
                  
-        exit(EXIT_FAILURE); //warum failure?? muesste es nicht success heissen?)+        exit(EXIT_FAILURE);
 } }
 // Ende Funktion main // Ende Funktion main
Zeile 155: Zeile 154:
 // Ausgabegeräte suchen // Ausgabegeräte suchen
                  
-void * showFrame(void){//hat  übergabeparameter void , verträgt sich also nicht mit der  pthread_create funktion weil die erwartet ein void * ->voidpointer  als übergabe//aha. also noch mal ne thread-Methode machen, die diese dann aufruft?? +void * showFrame(void){
-        +
         DIR *d;         DIR *d;
         if((dir = opendir("/dev") == NULL){          if((dir = opendir("/dev") == NULL){ 
Zeile 168: Zeile 166:
         FILE * outFiles[10];         FILE * outFiles[10];
                  
-        while((e= readdir(d)) != NULL && nFiles < 10 ){ //ich haette hier eher ne for-Schleife gemacht+        while((e= readdir(d)) != NULL && nFiles < 10 ){ 
                                                  
                         if(fnmatch( "fb*", e->d_name, 0) == 0){                         if(fnmatch( "fb*", e->d_name, 0) == 0){
                                                                  
                                 /********edit changed**********/                                 /********edit changed**********/
-                                char path[strlen("/dev/") + strlen(e->d_name)]; //man braucht noch ein Zeichen mehr fuer das \0 zeichen. also noch mal +1+                                char path[strlen("/dev/") + strlen(e->d_name)]; 
                                 sprintf(path, "/dev/%s", e-d_name);                                 sprintf(path, "/dev/%s", e-d_name);
                                                                  
-                                outFiles[nFiles] = fopen(path, "a+");//VORSICHT:  du musst schon den kompletten pfad übergeben -> strcat mit /dev/ und  e->d_name, oder hab ich des falsch im kopf???? (also könnte schon  stimmen, bin mir gerade net ganz sicher)// habs wie er...ohne pfad//FILE *fopen(const char *path, const char *mode);  - habs angepasst +                                outFiles[nFiles] = fopen(path, "a+");/ 
-                                 // das Arbeitsverzeichnis ist ja nicth in /dev von daher muss man denke  ich schon den absoluten pfad angeben, weil der relative bezieht sich ja  aufs Arbeitsverzeichnis und des kann irgendwo sein, oder? +                                
-                                also ich denke du hast recht - hier muss man wohl den gesamten Pfad übergeben. +
-                        +
                                 if(outFiles[nFiles] == NULL){                                 if(outFiles[nFiles] == NULL){
                                         perror("opening File");                                         perror("opening File");
Zeile 190: Zeile 186:
                  
                  
-        // Videobilder aus Puffer entnehmen und ausgeben+ 
         struct data *video;         struct data *video;
                  
Zeile 199: Zeile 195:
                                  
                 for(int i = 0; i < nFiles; i++){                 for(int i = 0; i < nFiles; i++){
-                        fwrite(video->frame, sizeof(byte), 307200, outFiles[i]);//  ich hab da irgendwas anderes eher sowas: fwrite(datax.frame,  FRAME_SIZE, 1, FRAME,fopeners[anz2]); //aber meins kann auch kompletter  unsinn sein, kannst du mir mal deine lsg erklären, wie man da drauf  kommt?// alsi cih hab fwrite(video->frame,1,FRAME_SIZE,hier muss irgendwie der stream rein^^);//ja schon datax.frame sind meine daten und foperns[anz] mein stream, so aber jetzt geh ich wirklich ins bett gn8 dir+                        fwrite(video->frame, sizeof(byte), 307200, outFiles[i]);
                 }                 }
                                  
                 eof = video->eof;                 eof = video->eof;
-                free(video)//nachdem  du das video geschrieben hast, kannste es ja wieder neubelegen also nen  stack-cache davon, dafür brauchst du kein malloc oder free+                free(video);
                 if(fclose(outFiles[i]) == EOF){                 if(fclose(outFiles[i]) == EOF){
                         die("fclose");                         die("fclose");
Zeile 233: Zeile 229:
                  
         if(waiter == NULL || fullSlots == NULL || freeSlots == NULL){         if(waiter == NULL || fullSlots == NULL || freeSlots == NULL){
-                frpintf("error creating needed sems");//kann man free auf Null aufrufen, ja stimmt müsste gehen....//hier stimmt das meiner meinung nach nicht,da du jenachdem wiewiet du ohne fehle rkommst verschieden freen musst - das glaub ich nicht . is in dem fall ja egal, weil die nicht ineinander                                                          verschachtelt                                                    sind//man darf bei sowas normal nur destroy auf was aufrufen, was auch erfolgreich mit create erzeugt wurde, sonst ist das Verhalten undefiniert. Man muss also leider der Reihe nach erzeugen und dann bei spaetren Fehlschlaegen die vorher erfolgreich erzeugten zerstoeren.+                frpintf("error creating needed sems");
                 semDestroy(waiter);                 semDestroy(waiter);
                 semDestroy(fullSlots);                 semDestroy(fullSlots);
                 semDestroy(freeSlots);                 semDestroy(freeSlots);
                 return 1;                 return 1;
-        } //Annahme: semDestroy(NULL) tut nichts//Aber gut, mit der Annahme ist es dann denke ich wieder ok.+        } 
         itemsBuffered = readPos = writePos = 0;//ist schon implizit auf 0         itemsBuffered = readPos = writePos = 0;//ist schon implizit auf 0
         return 0;         return 0;
 } }
 // Funktion jbPut // Funktion jbPut
-void jbPut(const struct data *data){//returnen und nicht einfach Blockieren? //war schon ein P, ein P wie Plockieren und ein V wie Vreigeben,asooo meine Eselsbrücke+void jbPut(const struct data *data){
         if(itemsBuffered >= CACHE_SIZE)          if(itemsBuffered >= CACHE_SIZE) 
-                return; //wieso das?//verstehe ich auch nicht+                return; 
                                  
         P(freeSlots);         P(freeSlots);
-        cache[writePos] = data; //Sollte hier bzw weiter unten nicht stehen: cache[writePos] = *data; ? Das Array speichert Structs und nicht pointer. geht das so, oder braucht man memcpy?. +        cache[writePos] = data; cache[writePos++] = data; 
-//sollte ohne memcpy gehen. Siehe Rudis kommentar im thread zu der aufgabe im forum//wo steht der kommentar?//sollte eh alles ganz ohne malloc gehen, weil cache ne fixe groesse hat und wie gesagt den dateninhalt statt die pointer speichert XXXXX= *YYYYY holt sich den inhalt von YYYYY und speichert den in XXXXX und das ist sozusgagend ein internes memcpy^^(also das =) //darfst aber den foren link trotzdem noch posten, würde ich mir mal anschauen wollen... +
-//https://fsi.informatik.uni-erlangen.de/forum/thread/12359-vsc-Klausur-s2014 +
-//letzter kommentar in den thread.// ja da steht genau des mit dem = (ich glaube rudi meint, dass das structs kopieren über diese = operation schon seit C89 geht oder aber memcpy????, bin mir da net ganz sicher was er meint, aber = geht aufjedenfall) +
-// = sollte gehen für structs, joa//bei was braucht man eigentlich memcpy überhaupt? realloc implementieren :D ne, memcpy is für zeug aufm heap glaub ich.//naja heap kann ich auch derefernzieren und mit = vollschreiben// eventuell array operationen also wenn ich ganze arrays kopieren will die nicht innerhalb eines structs sind???//das auch, ja. Aber hier liegt ja das ganze array aufm stack, weils im struct ist, ist also hier kein problem. //ja des im struct ist klar, aber würde denke ich auch gehen wenns aufm heap liegen würde (also nicht aufm stack) +
-//hm stimmt, müsste derefenziert werden der pointer, habs zwar jetzt hier nicht getestet, aber sollte schon so sein +
-//ok net ganz richtig für arrays mit variabler länge gilt das nicht da sinds ja nur pointer und da werden pointeradressen einfach kopiert und nicht mehr +
-        //writePos++;//geht glaube ich auch infix, da ++ post-inkrement ist, also danach ausgewertet wird  cache[writePos++] = data; +
                  
-        // writepos wieder auf 0 setzen? +  
-        // if(writePos >= CACHE_SIZE) writePos = 0;+
                  
         V(fullSlots);         V(fullSlots);
         itemsBuffered++;         itemsBuffered++;
-        if(itemsBuffered == BUFFER_SIZE){//ah cool, glaube da wäre ich wirklich net so schnell drauf gekommen des so zu lösen+        if(itemsBuffered == BUFFER_SIZE){
                 V(waiter);                 V(waiter);
         }         }
                  
-         +       Slots
-        //ICH BIN MIR NICHT SICHER ob die Sache mit von Puffer auf Durchzug schalten hier wirklich korrekt ist. Ich habe das so geloest: in der init-Funktion den waiter auf  minus 20 setzen, dann muss 20 mal V(waiter) aufgerufen werden, in Flush mache ich auf waiter noch mal semCreate mit 0. Dann ist der Spuk vorbei. +
-        [//Ich rufe also immer in put V(waiter) und in get P(waiter) auf also genauso wie fullSlots+
 } }
 // Funktion jbGet // Funktion jbGet
Zeile 279: Zeile 265:
                  
         //readPos ++;         //readPos ++;
-        /*+        
         struct data dat = cache[readPos++];         struct data dat = cache[readPos++];
-        itemsBuffered--;                                       // würde der buffer mit folgendem Szenario: itemsBuffered = Buffer_SIZE => V(waiter) , dann Get, Get, dann Put und dann läuft der Buffer wieder in itemsBuffered = Buffer_SIZE => V(waiter)  => V ist jetzt (2) => synch in Get nichtmehr gewährleistet, oder irre ich mich da? +        itemsBuffered--;                                       
- +
-        //das stimmt, aber in itemsBuffered sollte ja die zahl der Elemente im cache stehen oder nicht? +
- +
-    //naja gut, wenn man davon ausgeht, dass man die zahl nie mehr braucht, kann mans auch weglassen. +
- +
-    //ansonsten ist mir das problem schon aufgefallen. Man müsste dann noch in der put funktion prüfen, ob das bereits einmal aktiviert wurde. +
- +
-    //Das gleiche Problem kriegt man aber auch simpler: 2 mal Flushen.... wobei das hier nicht unser problem wäre. +
- +
-    //evtl sollte man dann generell überall wo man V(waiter) macht schauen, ob das schonmal getan wurde. Dann fixt man es für alles gleichzeitig+
  
 +        
         data = &dat;https://wwwcip.cs.fau.de/~ak53efan/sp/         data = &dat;https://wwwcip.cs.fau.de/~ak53efan/sp/
           if(readPos >= CACHE_SIZE) readPos = 0;           if(readPos >= CACHE_SIZE) readPos = 0;
-        */        +
                  
         V(freeSlots);         V(freeSlots);