Not logged in. · Lost password · Register

Page:  1  2  next 
ingonör
Member since May 2013
67 posts
Subject: Klausur 2013-03
Hallo,

habe mich an der o.g. Klausuraufgabe versucht.
Ich bin mir nicht so sicher, ob ich den Test richtig mache, ob wirklich eine *.c Datei kompiliert wird.
Bin für jeden Hinweis dankbar!

Grüße
ingonör

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <dirent.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7.  
  8. /* Funktiondeklarationen, globale Variablen, etc. */
  9.  
  10. /* Funktion compiledir */
  11. void compiledir(void) {
  12. /* aktuelles Directory oeffnen */
  13.     DIR *p = opendir(".");
  14.     if(p == NULL) {
  15.         perror("opendir");
  16.         return(EXIT_FAILURE);
  17.     }   
  18.    
  19. /* Directory durchsuchen und .c-Dateien compilieren */
  20.     struct dirent *ent;
  21.     char *fname;
  22.     char *pstr;
  23.     while(errno = 0, (ent = readdir(p)) != NULL) {
  24.         fname = ent->d_name;
  25.         pstr = strstr(fname, ".c");
  26.         if((pstr - fname) == strlen(fname) - 2) {
  27.             compile(fname);
  28.         }      
  29.     }
  30. /* Ressourcen freigeben */
  31.     if(errno) {
  32.         perror("readdir");
  33.         exit(EXIT_FAILURE);
  34.     }
  35.     if(closedir(p)) {
  36.         perror("closedir");
  37.         exit(EXIT_FAILURE):
  38.     }
  39. /* Ende der Funktion compiledir */
  40. }
Raim
GSPiC-Guru
Member since May 2011
79 posts
Quote by ingonör:
  1.         pstr = strstr(fname, ".c");
  2.         if((pstr - fname) == strlen(fname) - 2) {
  3.             compile(fname);
  4.         }

Das funktioniert nicht unbedingt. Die Differenz von zwei Zeigern ist ja schließlich auch ein Zeiger, den du dann mit einem Integer vergleichst (warnt da der Compiler nicht?). Das ist sehr unschön und lässt sich auch besser lösen.

Außerdem erkennst du Dateinamen wie z. B. "ab.cd.c" nicht, da das erste ".c" und nicht das am Ende der Zeichenkette findest.
ingonör
Member since May 2013
67 posts
Quote by Raim:
Das funktioniert nicht unbedingt. Die Differenz von zwei Zeigern ist ja schließlich auch ein Zeiger, den du dann mit einem Integer vergleichst (warnt da der Compiler nicht)

Nope, der warnt nicht, obwohl ich es wieder mit allen Parametern, wie bei den Hausaufgaben (-Werror etc.) kompiliere.
Nun gut, und wie lässt es sich besser lösen, wenn ich fragen darf? Mir fällt da partout nichts ein außer String-Vergleich, welcher ja mit strstr durchgeführt wird.
morty
SPiC-Meister
(Moderator)
Member since May 2011
331 posts
Naja du musst dir überlegen, dass eine Zeichenkette auch nur ein Array von chars ist. Wenn du die Länge kennst, kennst du auch die Position der letzten zwei Zeichen und dann kannst du auch überprüfen was da drin steht.
ingonör
Member since May 2013
67 posts
Da hatte ich wohl ein Brett vor'm Kopf.
Besser so?
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <dirent.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7.  
  8. /* Funktiondeklarationen, globale Variablen, etc. */
  9.  
  10. /* Funktion compiledir */
  11. void compiledir(void) {
  12. /* aktuelles Directory oeffnen */
  13.     DIR *p = opendir(".");
  14.     if(p == NULL) {
  15.         perror("opendir");
  16.         return(EXIT_FAILURE);
  17.     }   
  18.    
  19. /* Directory durchsuchen und .c-Dateien compilieren */
  20.     struct dirent *ent;
  21.     char *fname;
  22.     int length;
  23.     while(errno = 0, (ent = readdir(p)) != NULL) {
  24.         fname = ent->d_name;
  25.         length = strlen(fname);  
  26.         if(fname[length-2] == '.' && fname[length-1] == 'c') {
  27.             compile(fname);
  28.         }      
  29.     }
  30. /* Ressourcen freigeben */
  31.     if(errno) {
  32.         perror("readdir");
  33.         exit(EXIT_FAILURE);
  34.     }
  35.     if(closedir(p)) {
  36.         perror("closedir");
  37.         exit(EXIT_FAILURE):
  38.     }
  39. /* Ende der Funktion compiledir */
  40. }
bem
Member since Apr 2011
21 posts
Strings enden in C immer mit '\0'.
Was ich grad echt nicht verstehe: Warum jagst du den Code nicht einfach mal durch den Compiler und schaust dir die Ausgabe an?
ingonör
Member since May 2013
67 posts
Quote by bem:
Strings enden in C immer mit '\0'.
Stimmt! Danke!

Quote by bem:
Was ich grad echt nicht verstehe: Warum jagst du den Code nicht einfach mal durch den Compiler und schaust dir die Ausgabe an?

Weil ich manchmal ein bisschen langsam bin...  :-O

Für die Interessierten, so läuft die Kiste:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <dirent.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7.  
  8. /* Funktiondeklarationen, globale Variablen, etc. */
  9.  
  10. /* Funktion compiledir */
  11. void compiledir(void) {
  12. /* aktuelles Directory oeffnen */
  13.     DIR *p = opendir(".");
  14.     if(p == NULL) {
  15.         perror("opendir");
  16.         exit(EXIT_FAILURE);
  17.     }   
  18.    
  19. /* Directory durchsuchen und .c-Dateien compilieren */
  20.     struct dirent *ent;
  21.     char *fname;
  22.     int length;
  23.     while(errno = 0, (ent = readdir(p)) != NULL) {
  24.         fname = ent->d_name;
  25.         length = strlen(fname);  
  26.         if(fname[length-2] == '.' && fname[length-1] == 'c' && fname[length] == '\0') {
  27.             compile(fname)
  28.         }      
  29.     }
  30. /* Ressourcen freigeben */
  31.     if(errno) {
  32.         perror("readdir");
  33.         exit(EXIT_FAILURE);
  34.     }
  35.     if(closedir(p)) {
  36.         perror("closedir");
  37.         exit(EXIT_FAILURE);
  38.     }
  39. /* Ende der Funktion compiledir */
  40. }
Baum
Member since Jul 2013
8 posts
hätte das Durchsuchen nach kompilierbaren Dateien auch so funktioniert?

  1.     for(struct dirent *d; (d = readdir(ver))!= NULL; errno = 0){
  2.        
  3.         for(int i = 0; d->d_name[i] != '\0' && d->d_name[i+1] != '\0'; i++){
  4.             if(d->d_name[i] =='.' && (d-> d_name[i+1] == 'c'){
  5.                 compile(d->d_name);
  6.             }
  7.         }      
  8.        
  9.     }
This post was edited on 2013-07-20, 16:19 by Baum.
ingonör
Member since May 2013
67 posts
Quote by Baum:
  1. for(int i = 0; d->d_name[i] != '\0' && d->d_name[i+1] != '\0'; i++){

Was willst du mit dieser Stelle testen? Ob du am Ende deines Dateinamens angekommen bist?
Falls ja, dann sehe ich da folgendes Problem: Lass uns davon ausgehen, d_name = "0123.c". Dann würde für d_name[6] = '\0' gelten.
Soweit so gut. Aber deine for-Schleife bricht erst dann ab, wenn an der Stelle i und i + 1 das Nullterminalsymbol steht. Du weißt aber gar nicht, was an d_name[7] steht.
Da kann irgendwas stehen. Vielleicht hast du Glück und da steht wirklich '\0'. Aber das wäre dann Zufall.

Also, ich für meinen Geschmack finde dieses Konstrukt etwas verwirrend. Bin allerdings selber kein C/POSIX-Profi...
Musil
Member since Jul 2013
10 posts
ja, das hätte dann eher
    for(int i = 0; d->d_name[i] != '\0' || d->d_name[i+1] != '\0'; i++){
heißen sollen... passt das so?
ingonör
Member since May 2013
67 posts
Erkläre doch mal, was du mit der Abbruchbedingung aussagen willst. Die Schleife soll abbrechen, wenn ... ?

|| d->d_name[i+1] != '\0'
ist in meinen Augen völlig unnötig, da sie IMMER abbrechen wird, wenn an der Stelle 'i' bereits das Null-Terminalsymbol gefunden worden ist.

Kleiner Tipp: Die Linux Aufgaben kann man ja wirklich kompilieren (im Gegensatz zu den Mikrocontroller Aufgaben aus den Klausuren).
Mach das doch mal und schreibe dann in die Zeile "compile(foo)" einfach sowas wie:
  1. printf("Kompiliert wird: %s\n", d->d_name);

Dann siehst du ja, ob das Programm das tut, was es tun sollte.
Baum
Member since Jul 2013
8 posts
mit der Abbruchbedinung ist folgendes gemeint (ich sehe nicht, warum das && falsch ist):
links von &&:
d->d_name[i] != '\0'

wenn ich ein Zeichen untersuche, soll das nicht das Nullbyte sein

rechts von &&:
d->d_name[i+1] != '\0'
gleichzeitig darf das nächste Zeichen auch nicht das Nullbyte sein, sonst kann ich ja nicht zwei Zeichen hintereinander abfragen

wenn die Abfragebedingung in der for Schleife geklappt hat, dann kann ich mir
d->d_name[i]
sowie
d->d_name[i+1]
anschauen und prüfen ob sie '.' bzw. 'c' sind

ich komm mal wieder auf dein Beispiel zurück

"0123.c"
wenn i == 4, dann ist d->d_name[4] == '.' und d->d_name[4+1] == 'c', somit sind beide nicht das Nullbyte und die Datei würde kompilieren.

Dagegen z.B. bei
"0123.h"
würde mich die for Schleife bei i == 5 rauswerfen
ingonör
Member since May 2013
67 posts
Also, irgendwie steige ich da gerade aus. Wenn du ein Zeichen untersuchst, soll das nicht das Nullbyte sein und das nächste darf auch nicht Nullbyte sein. Für welchen Dateinamen wäre das denn z.B. so?

Vielleicht sollte sich hier mal noch ein etwas erfahrenerer C-Programmierer melden. :)

Edit: Aber noch eine Frage: Tut dein Programm denn das, was es soll? Also, hast du schon mal versucht es so zu kompilieren, wie ich es oben beschrieben habe?
Raim
GSPiC-Guru
Member since May 2011
79 posts
Im Prinzip ist die Bedingung schon richtig. Der Teil mit d->d_name[i] == '\0' ist eigentlich unnötig, weil d->d_name[i+i] == '\0' schon immer vorher zutreffen wird.
Fufu der Radiergummi
Member since Apr 2012
25 posts
hey ingonör,
fehlt bei deinem Code nicht irgendwo eine errno Abfrage?
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O :troll:
Special characters:
Page:  1  2  next 
Go to forum
Powered by the Unclassified NewsBoard software, 20110527-dev, © 2003-8 by Yves Goergen