Datei in Verzeichnis finden



  • Hallo Forum!

    Hab mal wieder ein Problem und weiß nicht genau, wo der Fehler ist. Es soll ein Ordnername und eine Datei angegeben werden, und die Datei dann ausgegeben wenn gefunden:

    int main(int argc, char *argv[]) {
    
       DIR *dir;
       struct dirent *dirzeiger;
    
       /* das Verzeichnis öffnen */
       if((dir=opendir(argv[optind])) == NULL) {
          fprintf(stderr,"Fehler beim Öffnen des Ordners\n");
          return EXIT_FAILURE;
       }
       /* das komplette Verzeichnis auslesen */
       while((dirzeiger=readdir(dir)) != NULL)
          {
              printf("%s\n",(*dirzeiger).d_name);    //gibt mir alle Dateien im Verzeichnis aus
    
              if ( (strcmp((*dirzeiger).d_name, argv[++optind])) == 0)  //vergleiche Datei im Ordner mit angegebenen Namen
              {
                  printf("Übereinstimmung gefunden\n");
                  optind--;
                  fprintf(stdout, "%s\n",(*dirzeiger).d_name); //gibt gefundene Datei aus
    
              }
             else
              {
                 printf("keine Übereinstimmung gefunden\n");
    
              }              
          }
    
       /* Lesezeiger wieder schließen */
       if(closedir(dir) == -1)
          printf("Fehler beim Schließen von %s\n", argv[optind]);
       return EXIT_SUCCESS;
    }
    

    So, das sollte mir eigentlich ausgeben:
    Datei 1
    gefunden -ja oder nein
    wenn gefunden nochmal Datei 1
    Datei 2
    ...

    die getopt Funktion hab ich wegen der Übersicht Mal weggelassen, aber optind stimmt schon soweit, ist erstmal das Verzeichnis, ++optind der Dateiname der gesucht wird

    es funktioniert aber nur, wenn die Datei im Order an erster Stelle ist! Sobald das anders ist, bekomme ich in der Kommandozeile den Error: "Speicherzugriffsfehler".

    Programmiere unter Linux.. Könnt ihr mir helfen?

    MFG Zoltar



  • Weißt du was ++optind macht?
    Welchen Wert hat opind in einer Schleife beim zweiten (dritten, ...) Durchlauf?
    Was kann dann das Problem sein, wenn du optind als Arrayindex verwendest?

    PS:
    Bei Struktur-Zeigern greift man auf die Elemente mit -> zu: dirzeiger->d_name .



  • Ja weiß ich: optind gibt mir das Argument, das nach den Options kommt
    Bei mir soll die Eingabe so aussehen:
    [Optionen] Suchordner Suchdatei

    Die Optionen hab ich mit getopt schon verarbeitet, also gibt mir optind den Suchordner.

    ++optind erhöht optind, somit zeigt optind auf die Suchdatei, weil das das nächste Argument ist.

    Nunja, da es eine while Schleife ist und immer mit ++ erhöht wird und dann wieder mit -- niedriger gesetzt, immer den Wert des 2.Arguments, oder nicht?

    Das mit Struktur Zeigern: Ok, geht auf beide Arten, hab ich geändert.

    Was das Problem sein könnte weiß ich ehrlich gesagt nicht, klar man könnte den Index vertauschen, etc., aber was ist hier das Problem?

    MFG Zoltar



  • Zoltamor schrieb:

    Nunja, da es eine while Schleife ist und immer mit ++ erhöht wird und dann wieder mit -- niedriger gesetzt, immer den Wert des 2.Arguments, oder nicht?

    Das machts du aber nur, wenn die Dateinamen übereinstimmen, wenn sie das nicht tun, wird optind munter weitergezählt.

    Wie rufst du das Programm denn auf?
    Geraten: programmname pfad Dateiname

    Was ist wenn als erstes dateinme steht oder meinedatei oder ..

    Nimm den Debugger oder bau ein paar besser printf ein, in denen auch argv und optind mit ausgegeben werden.

    Und poste mal compilierbaren Code (in dem alle Variablendefinitionen und auch die #include stehen)



  • Natürlich, ich bin ein Idiot 🙄

    Das Problem war ganz klar, dass das --optind auch in den else Zweig gehört... Sonst zählt es immer weiter..

    oder ich ersetze das argv[++optind] durch ein argv[optind+1], dadurch gibts dann auch keine Probleme mehr und ich brauch gar nix mehr abziehen...

    Vielen Dank 😉

    BTW: Mit der Eingabe hattest du Recht, ja, aber die soll auch so sein und nicht umgedreht

    MFG Zoltar



  • Zoltamor schrieb:

    Das Problem war ganz klar, dass das --optind auch in den else Zweig gehört... Sonst zählt es immer weiter..

    oder ich ersetze das argv[++optind] durch ein argv[optind+1], dadurch gibts dann auch keine Probleme mehr und ich brauch gar nix mehr abziehen...

    Das Problem ist, dass du nicht überprüfst, ob optind noch zu argc passt.

    Zoltamor schrieb:

    BTW: Mit der Eingabe hattest du Recht, ja, aber die soll auch so sein und nicht umgedreht

    Ich wollte dich auch darauf hinweisen, das du nicht genug Informationen gegeben hast.
    Es ist ja auch programmname pfad Datei1 Datei2 Datei3 ... möglich. Denn sonst macht dein ++optind keinen Sinn (bzw. das -optind im else auch keinen).



  • Moment, da hast du was interessantes angesprochen, eigentlich WILL ich nämlich sogar dass mehrere Dateien angegeben werden können.

    Hab es jetzt ein wenig anders probiert, und zwar mit einer for-Schleife. Es sollte so ablaufen:

    Der Zeiger zeigt auf die 1.Date im Ordner. Anschließend wird verglichen, ob die erste Eingabe übereinstimmt. Wenn nicht, die 2te,... wenn es übereinsimmt, soll sie ausgegeben werden, wenn nicht dann nicht.

    Sollte so aussehen:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <string.h>
    #include <getopt.h>
    #include <math.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <errno.h>
    
    int main(int argc, char *argv[]) {
    
       int c=0;
       int coptions=0;
       int i=1;
    
    pid_t child_pid;
    
       while ( (c = getopt(argc, argv, "iR")) != EOF ) {
            switch ( c ) {
                case 'i':
                    coptions++;
                    break;
                case 'R':
                    coptions++;
                    break;
                case '?':
                    fprintf(stderr,"Falsche Option angegeben\n");
                    exit(EXIT_FAILURE);
                default:
                    exit(-1);
                    break;
            }
        }
    
    if(coptions >= 3) {
          fprintf(stderr,"Zu viele Optionen angegeben!\n");
          return EXIT_FAILURE;
    
       }
    
        child_pid = fork();
    
        switch ( child_pid ) {
            case -1:            //Error
    
                    fprintf(stdout, "Child could not be started.\n");
                    exit(EXIT_FAILURE);
                    break;
    
            case 0:     //Child
    
                   DIR *dir;
                   struct dirent *dirzeiger;
    
                   /* das Verzeichnis öffnen */
                   if((dir=opendir(argv[optind])) == NULL) {
                      fprintf(stderr,"Fehler beim Öffnen des Ordners\n");
                      return EXIT_FAILURE;
                   }
                   /* das komplette Verzeichnis auslesen */
    
                   while((dirzeiger=readdir(dir)) != NULL)
                      {
    
                            fprintf(stdout, "in Optind: %s Optind selbst: %d gezeigt wird auf: %s \n", argv[optind],optind,dirzeiger->d_name);
    
                            for (i=1;i<=(argc-coptions);i++)
                            {
                                    if ( (strcmp(dirzeiger->d_name, argv[optind+i])) == 0)  //vergleiche Datei im Ordner mit angegebenen Namen, bei 0 Übereinstimmung
                                      {
                                          fprintf(stdout, "<%d> : <%s> : <%s/%s>\n", getpid(), dirzeiger->d_name, argv[optind], dirzeiger->d_name); //Übereinstimmung
    
                                          fprintf(stdout, "if Zweig: in Optind: %s Optind selbst: %d gezeigt wird auf: %s \n", argv[optind],optind,dirzeiger->d_name);
    
                                      }
                                      else  //keine Übereinstimmung
                                      {
                                             fprintf(stdout, "else Zweig: in Optind: %s Optind selbst: %d gezeigt wird auf: %s \n", argv[optind],optind,dirzeiger->d_name);
                                      }
    
                            }
    
                      }
    
                   /* Lesezeiger wieder schließen */
                   if(closedir(dir) == -1)
                      printf("Fehler beim Schließen von %s\n", argv[1]);
    
            default:    //Vater
    
                    fprintf(stdout, "Ich bin der Vater\n");
    
        }
    
       return EXIT_SUCCESS;
    }
    

    Hab das ganze jetzt noch zusätzlich in einen Kind-Prozess verpackt, ist aber nebensächlich für dieses Problem. Auch bei den Optionen passiert noch nichts, sind erst für später gedacht, aber sonst macht optind keinen Sinn.

    Mein Problem ist jetzt, dass der dirzeiger nicht weiterspringt, also immer nur auf die erste angegebene Datei zeigt. Warum?

    MFG Zoltar



  • Die Fehlt ein wait(2) im Vaterzweig.



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum C (C89 und C99) in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Spielt das wait wirklich eine Rolle, auch wenn ich mit dem Kindprozess noch gar nicht fertig bin? Dass der Vaterprozess dann evtl. dazwischen ist, ok, aber trotzdem müsste der Kind Prozess so funktionieren oder?

    Und stimmt es dass ein normales

    waitpid()

    auf alle Kindprozesse wartet, und nicht nur auf eine bestimmte pid?

    MFG Zoltar



  • Wenn sich der Elternprozess beendet, dann wird auch der Childprozess beendet.



  • Ok, jetzt hab ich zu Testzwecken Mal ein sleep in den Elternprozess gesetzt, sodass der Kindprozess auf jeden Fall vorher ausgeführt wird.

    Es wird allerdings trotzdem immer nur auf die erste Datei im Verzeichnis zugegriffen 😞


Anmelden zum Antworten