getline - String wird falsch übergeben



  • die.ina schrieb:

    Ich bin übrigens noch absoluter Anfänger und für Verbesserungsvorschläge absolut offen 😉

    Was mir sofort ins Auge sticht ist

    char* a = new char[256];
    

    Zumal du vergisst, den Speicher wieder mit delete[] freizugeben.

    Hier kannst du einfach

    char a[256];
    

    nehmen oder noch besser gleich einen std::string (dafür gibts auch eine eigene getline()-Funktion, da hast du keine Probleme mehr, wenn die Strngs doch einmal länger als 256 Zeichen werden.)



  • 27 int Parser::parsen(string Dateiname)
     28 {
     29 
     30   ifstream f;
     31   ofstream index; //ifstream = Lesen, ofstream = Schreiben, fstream = flexibel 
     32   f.open(Dateiname.c_str()); //bei fstream zusätzlicher Parameter nötig
     33   index.open("index");
     34   if(f.is_open()) //testet ob Datei wirklich geöffnet ist
     35   {
     36     char c;
     37     char zeichendavor = ' ';
     38 
     39 /* Problematik: 
     40  * - Problem bei fehlenden Leerzeichen */
     41 
     42     while(!f.eof()) //testet ob Datei zuende ist
     43     {
     44       f.get(c);
     45 
     46 
     47         switch(c)
     48       {
     49         case ' ': case '\n':
     50          switch(zeichendavor)
     51           {
     52             case ' ': case '\n': break;
     53             default:
     54             index << "\t\t" << Dateiname << "\n";
     55             break;
     56           }
     57           break;
     58         case ',': case '!': case '?': case '.': case '"': break;
     59         default:
     60           switch(zeichendavor)
     61           {
     62             case ',': case '!': case '?': case '.': case '"':
     63                 index << "\t\t" << Dateiname << "\n" << c; break;
     64             default:  index << c;
     65             break;
     66           }
     67           break;
     68       }
     69      zeichendavor = c;
     70 
     71     }
     72 
     73   }
     74  f.close();
     75  index.close();
     76   return 0;
     77 }
     78
    

    Also, das ist parsen(string Dateiname)

    Wenn ich den Dateiname direkt einfüge, also z.b.: parsen(test.txt) funktioniert alles tadellos (abgesehen von etlichen Ausnahmefällen die ich noch nicht drinne habe, aber das stört erstmal nicht) und in der index steht dann z.B.

    Ich test.txt
    weiß test.txt
    nicht test.txt
    mehr test.txt
    weiter test.txt

    Wenn ich genau das allerdings mithilfe de getline-Funktion probiere und die Dateinamen aus einer Liste ziehe, ist die index vollkommen leer. Warum?



  • Debugge doch einfach und schau mal, was in 'Dateiname' genau steht und ob er dann die Datei auch öffnen kann...

    Ich empfehle aber auch std::string mit der zugehörigen freien Funktion 'getline(string, istream)' zu benutzen.

    Außerdem kannst du das Öffnen der Datei gleich beim Konstruktor vornehmen:

    ifstream f(Dateiname.c_str());
    


  • Also, die genannten Dinge habe ich geändert, das Problem bleibt aber leider dasselbe.
    Ich habe bereits versucht zu Debuggen und er kommt auch in parsen(string Dateiname) herein, aber dennoch wird nichts daraus. Habe ddd (GUI für gdb unter Ubuntu) benutzt, werde allerdings aus den Werten für die Variablen nicht schlau. Auf jeden Fall scheint er alles in der parsen-Funktion auszuführen.

    Ich gehe ja auch richtig in der Annahme, dass er in der Index nur anhängt und diese nicht jedes Mal neu erstellt oder gegebenenfalls irgendetwas löscht, oder?

    Mache ich in die parsen eine Ausgabe für den Dateinamen rein, so gibt er diesen auch korrekt aus.

    Danke auf jeden Fall schoneinmal für die Tipps.

    EDIT: Ich habe gerade einmal einen else-Zweig reingemacht, um zu schauen, ob er die Dateien öffnet, ... und siehe da, er tut es nicht.
    Woran könnte das liegen?



  • Mach aus:

    int Parser::parsen(string Dateiname)
    

    doch einfach mal:

    int Parser::parsen(const char *Dateiname)
    

    Ich weiß nämlich nicht ob es da Datenverluste/-veränderungen geben kann. Einfach mal ausprobieren und debuggen...



  • Ich habe jetzt die andere getline Funktion genommen, so dass ich prinzipiell einen String ausgegeben bekomme und keinen char-array mehr, ... ohne es jetzt ausprobiert zu haben, ... wird das nicht auf eine Fehlermeldung hinauslaufen, wenn ich nun sage, der Parameter sei ein char*? Weshalb in diesem Fall eigentlich das "const"?

    EDIT: Ich habe es nun vollständig mit const char* probiert, doch bleibt das Problem dasselbe: Er kann die Dateien nicht öffnen, obwohl er den richtigen Dateinamen überliefert bekommt und die Dateinamen innerhalb der parsen-Funktion auch korrekt ausgeben kann.



  • Ich habe jetzt die andere getline Funktion genommen, so dass ich prinzipiell einen String ausgegeben bekomme und keinen char-array mehr, ... ohne es jetzt ausprobiert zu haben, ... wird das nicht auf eine Fehlermeldung hinauslaufen, wenn ich nun sage, der Parameter sei ein char*? Weshalb in diesem Fall eigentlich das "const"?

    EDIT: Ich habe es nun vollständig mit const char* probiert, doch bleibt das Problem dasselbe: Er kann die Dateien nicht öffnen, obwohl er den richtigen Dateinamen überliefert bekommt und die Dateinamen innerhalb der parsen-Funktion auch korrekt ausgeben kann.

    EDIT2: Ich seh gerade, dass er ungewöhnlicherweise, trotz 2er Dateien, nur einmal "Kann Datei nicht öffnen!" ausgibt.

    Nocheinmal der vollständige Code, wie er jetzt ist:

    #include "Parser.h" 
      Parser::Parser(string Liste)
      {
        //parsen("test.txt"); //funktioniert
        ifstream l(Liste.c_str());
        if(l.is_open())
        {
          string a;
          while(!l.eof())
          {
           getline(l, a); //delim = \n
           parsen(a); //funktioniert nicht
           cout << a << " ";
          }
          l.close();
        }
        else
        {
          cout << "Datei nicht lesbar!!" << endl;
        }
    
      }
    
      int Parser::parsen(string Dateiname)
      {
        ifstream f(Dateiname.c_str());
        ofstream index; //ifstream = Lesen, ofstream = Schreiben, fstream = flexibel 
        index.open("index");
        if(f.is_open()) //testet ob Datei wirklich geöffnet ist
        {
          char c;
          char zeichendavor = ' ';
    
      /* Problematik: 
       * - Problem bei fehlenden Leerzeichen */
    
          while(!f.eof()) //testet ob Datei zuende ist
          {
            f.get(c);
    
              switch(c)
            {
              case ' ': case '\n':
               switch(zeichendavor)
                {
                  case ' ': case '\n': break;
                  default:
                  index << "\t\t" << Dateiname << "\n";
                  break;
                }
                break;
              case ',': case '!': case '?': case '.': case '"': break;
              default:
                switch(zeichendavor)
                {
                  case ',': case '!': case '?': case '.': case '"':
                      index << "\t\t" << Dateiname << "\n" << c; break;
                  default:  index << c;
                  break;
                }
                break;
            }
           zeichendavor = c;
          }
          f.close();
           index.close();
        }
         else
          cout << "Kann Datei nicht öffnen!" << endl;
         return 0;
      }
    


  • Aus

    l.open(Liste.c_str());
    

    mal

    l.open(Liste.c_str(), std::ios::in);
    

    machen...



  • Keine Änderung.

    Ausgabe:

    test.txt test2.txt Kann Datei nicht öffnen!

    Ändere ich den else-Zweig auf:

    else
         cout << "Kann " << Dateiname << " nicht öffnen!" << endl;
    

    Bekomme ich:

    test.txt test2.txt Kann nicht öffnen!

    Er kennt also den Dateinamen nicht mehr. Hat das einen Grund?

    Setze ich jedoch eine Ausgabe des Dateinames an die erste Stelle in parsen, so kann er es noch.



  • Dann check mal den Pfad. Haste text1.txt auch im richtigen Projekteordner?



  • Ja, befindet sich alles in einem Ordner.
    Und wie gesagt, wenn ich parsen("test.txt"), bzw. parsen("test2.txt") aufufe und ausführe, macht er auch alles, wie er es soll, kann die Datei lesen und in der Index steht das gewünschte.



  • Kóyaánasqatsi schrieb:

    Mach aus:

    int Parser::parsen(string Dateiname)
    

    doch einfach mal:

    int Parser::parsen(const char *Dateiname)
    

    Ich weiß nämlich nicht ob es da Datenverluste/-veränderungen geben kann. Einfach mal ausprobieren und debuggen...

    Kóyaánasqatsi schrieb:

    Aus

    l.open(Liste.c_str());
    

    mal

    l.open(Liste.c_str(), std::ios::in);
    

    machen...

    Hauptsache wild im Zeug rumraten...
    Der erste Vorschlag ist nicht wirklich ratsam, wenn die.ina mit std::getline() flexibel sein will. Wie kommst du eigentlich darauf, dass man durch den std::string Daten verlieren könnte? Allerdings könnte sich eine Const-Referenz, also const std::string& Dateiname aus Performancegründen empfehlen.

    Dein zweiter Vorschlag bringt überhaupt nichts.

    die.ina schrieb:

    index.open("index");
    

    Bist du sicher, dass die Datei "index" heisst (ohne Endung)?

    Was willst du eigentlich genau erreichen? In einer Datei die Namen anderer Dateien lesen, die du dann einzeln parst? Übrigens rate ich dir, so schnell wie möglich den Umgang mit dem Debugger zu lernen. Das ist eines der hilfreichsten und mächtigsten Werkzeuge eines Programmierers.



  • Also, vll ist es etwas umständlich, aber ich weiß nicht, wie ich es besser machen soll.
    1. Schritt: 1000e von Textdateien als Liste in einer Datei speichern.
    2. Schritt: Die einzelnen Wörter aus den Textdateien in einer weiteren Datei speichern, inklusive dem Namen der Textdatei in welcher sie gefunden wurden.
    3. Schritt: Diese Textdatei dann sortieren und bei gleichen Wörtern die Dateinamen als Liste hinter dem jeweiligen Wort speichern.
    4. Schritt: Nach Wörtern suchen und eben anzeigen, wo sie zu finden sind.
    ...

    Momentan hänge ich zwischen Schritt 1 und 2, wobei 1 eigentlich noch vollkommen fehlt.

    Index ohne Endung ist kein Problem, ... Linux.



  • Hmm. Oben hast du aber gesagt, dass es ja funktioniert..

    Also klappt das browsen durch die Ordner nicht? Respektive hast du Probleme mit Pfaden?


Anmelden zum Antworten