Text einlesen und "scannen"



  • Hallo Leute ,

    ich habe eine Textdatei die ungefähr so aufgebaut ist :

    3
    
    4
    
    Text 1 
    Text 2 
    15.06.2015 14 Uhr
    

    Allso immer einen int, eine Leerzeile, einen int, eine Leerzeile, 2 Zeilen kuren Txt, Date_Time , eine Leerzeile und dann wieder von vorne. Interessant für mich sind nur die beiden Textzeilen und das Datum/Zeit

    Scheinbar Simpel, für die Pro´s ist es das wohl auch, aber ich bin mir nicht wirklich sicher wie ich das am besten einelsen soll.

    Erster Gedanke war etwas wie :

    std::ifstream is ("test.txt" , ios_mode::in)
    
    std::string line;
    
    while(is)[
    
       int x;
       if (! (is >> x) ){
            is.clear();
            getline(is, line);
            // my_vec.push_back(line)   //später
        }
    }
    

    Aber das ist doch Käse so. Das war auch noch nie so wirklich meine Stärke.
    Kann mir mal jmd. ein paar Tipps geben und evtl. auch beschreiben wie man an sowas "ran-geht" ?



  • Wenn das Format wirklich immer so ist, und nicht etwa die Anzahl der Zeilen variiert, würde ich einfach die ersten 4 Zeilen mit ignore überspringen und dann die 3 gewünschten Zeilen einlesen. Brauchst du nur die Zeilen oder soll das Datum auch noch in irgendwas handhabbares konvertiert werden?



  • class Data {
    public:
      Data() 
        : m_valid(false)
        , m_number1(0)
        , m_number2(0)
      {
      }
    
      virtual ~Data() {
      }
    
      void readFrom(std::istream& stream) {
        stream >> m_number1;
        std::getline(stream, std::string());
        stream >> m_number2;
        std::getline(stream, std::string());
        std::getline(stream, std::string());
        std::getline(stream, m_line1);
        std::getline(stream, m_line2);
        std::getline(stream, m_dateTime);
      }
    
      void writeTo(std::ostream& stream) const {
        if (m_valid) {
          // write data block
        }
      }
    
    private:
      bool m_valid;
    
      int m_number1;
      int m_number2;
    
      std::string m_line1;
      std::string m_line2;
    
      std::string m_dateTime;
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      std::ifstream file("C:/tmp/test.txt", std::ios_base::in);
      if (file.is_open()) {
        std::vector<Data> data_blocks;
        while (file.good()) {
          Data data;
          data.readFrom(file);
          data_blocks.push_back(data);
        }
      }
    	return 0;
    }
    

    Wenn das Format vorgegeben ist, würde ich das auch in Code gießen.

    Mein Vorschlag siehe oben (in VS2013 kompiliert) ... wobei das mit "ignore" die saubere Lösung ist anstelle von dem "getline(stream,std::string())"...



  • würde es mit isdigit und peek machen.
    in etwa so

    void foo( std::istream& s )
    {
      while(s >> std::ws)
      {
        if(! std::isdigit(s.peek()) )
          return;
    
        while( std::isdigit(s.peek()) )
          s.ignore();
      };
    }
    


  • Danke für die tipps und Codes, das hilft mir weiter.

    Wenn das Format wirklich immer so ist, und nicht etwa die Anzahl der Zeilen variiert, würde ich einfach die ersten 4 Zeilen mit ignore überspringen und dann die 3 gewünschten Zeilen einlesen.

    Ja, das Format ändert sich nicht wirklich. Wie kann ich die ersten Zeilen mit ignore übersrpingen ? MIr fällt jetzt da nur ein in einer for schleife ...

    for (int i = 0; i < 4 ; ++i){
               is.ignore(256, '\n');
    }
    

    ...aber so wird das nicht gemeint sein ?


  • Mod

    cpp_offl schrieb:

    ...aber so wird das nicht gemeint sein ?

    Wieso nicht? Ist natürlich ein bisschen ungünstig, wenn die Zeilen mehr als 256 Zeichen haben. Mit std::numeric_limits<std::streamsize>::max() als Länge überspringt ignore beliebig viele Zeichen.



  • nebler schrieb:

    ... wobei das mit "ignore" die saubere Lösung ist anstelle von dem "getline(stream,std::string())"...

    Vor allem auch weil getline(stream,std::string()) nicht standardkonform ist und mit Compilern wie GCC oder Clang nicht kompilieren wird.
    MSVC frisst es trotzdem wie wir wissen, aber das ist halt ne nonstandard Extension.


Anmelden zum Antworten