odczyt danych z pliku CSV - błąd związany z klasą istringstream

0

Witam,
mam ogromną prośbę o wyjaśnienie dlaczego poniższy kod wydobywa tylko 1 zmienną z pliku a później są błędy? Chodzi o wydobycie 3 zmiennych w pierwszym wierszu pliku oddzielonych znakiem

';'

        ifstream file;
        file.open(filename);
        string line;
        
        int int_val;
        double double_val;
        string cell;
        istringstream lineS;
        istringstream cellData;
        
        getline(file, line);
            lineS.str(line);
        getline(lineS, cell, ';');
        cellData.str(cell);
        if(cellData >> int_val)
            {
            zmienna1 = int_val;
            if(!(cellData >> ws).eof())
                cerr << " coś poszło nie tak 1" << endl;
            }
        else
            cerr << " error 1" << endl;
        getline(lineS, cell, ';');
        cellData.str(cell);
        if(cellData >> int_val)
            {
            zmienna2 = int_val;
            if(!(cellData >> ws).eof())
                cerr << " coś poszło nie tak 2" << endl;
            }
        else
            cerr << " error 2" << endl;
        getline(lineS, cell, ';');
        cellData.str(cell);
        if(cellData >> int_val)
            {
            zmienna3 = int_val;
            if(!(cellData >> ws).eof())
                cerr << " coś poszło nie tak 3" << endl;
            }
        else
            cerr << " error 3" << endl;

Natomiast, gdy wykonam ten kod w taki oto sposób:

        getline(file, line);
        lineS.str(line);
        vector<int> rowData;

        while(getline(lineS, cell, ';'))
            {
            istringstream cellData(cell);
            int value;
            if(cellData >> value)
                {
                rowData.push_back(value);
                if(!(cellData >> ws).eof())
                    cerr << "Problem in column: " << rowData.size() << " cell contains extra value: " << cell << endl;
                }
            else
                {
                rowData.push_back(100.0);
                cerr << "Problem in column: " << rowData.size() << " cell contains none numerical value: " << cell << endl;
                }
            }

        for(int i = 0; i < rowData.size(); i++)
            cout << "rowData["<< i << "] => " << rowData[i] << endl;

To wszystko działa prawidłowo...
Więc mam pytanie czym się różni jeden kod od drugiego, poza tym, że jeden wydobywa dane pojedynczo (przynajmniej taki jest zamiar) a drugi wykorzystuje pętlę while do wydobywania i zapisywania danych z wiersza...
Z góry dziękuję za pomoc!

0

Naprawdę nikt nie ma żadnego pomysła o co kaman? ;-(
Wydaje mi się, że to może być kwestia metody str, ale jak porównać przykłady to jest ona taka sama jak konstruktor...
Będę wdzięczny za jakiekolwiek wskazówki!
Aha i tak by the way: nie, nie mogę wczytać wszystkiego od razu, bo w pliku są zapisane najpierw zmienne typu int a później (kilka wierszy niżej) zmienne typu double :/
pozdrawiam

0

Uff, udało mi się rozwiązać, a raczej obejść problem... Problem jest z tym, że obiektu klasy istringstream nie można dwukrotnie wykorzystać - przynajmniej ja tego nie potrafię ;(.
Rozwiązałem problem w ten sposób, że tworzę obiekty wspomnianej klasy dynamicznie tj. np.

lineS = new istringstream(line);

. Czyli dla każdego wiersza, który chcę wydobyć z pliku tworzę nowy obiekt. Niestety to jest raczej obejście problemu niż jego rozwiązanie.
W związku z powyższym uprzejmie proszę o wyjaśnienie dlaczego nie mogę dwukrotnie skorzystać z obiektu klasy istringstream -> nawet utworzenie dwóch takich obiektów nie pomaga...

1

Problem jest z tym, że obiektu klasy istringstream nie można dwukrotnie wykorzystać - przynajmniej ja tego nie potrafię ;(.

Zapewne chodzi o to, że strumień wszedł w stan błędu, czyli ma ustawione flagi eofbit lub failbit, które powodują, że strumień przestaje działać. Dlatego przed ponownym użyciem wyzeruj flagi metodą clear.

0

@_0x666_ dziękuję! Pomogło! Grrr do 3 rano nad tym siedziałem :P
Pozdrawiam!

1

jeżeli znasz dokładnie ilość zmiennych w wierszu to wystarczy:

ifstream file(filename);
int  zmienna1,zmienna2,zmienna3;
char delim1,delim2;
while((file>>zmienna1>>delim1>>zmienna2>>delim2>>zmienna3)&&(delim1==';')&&(delim2==';'))
  {
   ...
  }
0

Niestety ale teraz przerabiam taki problem, że nie zawsze będzie to taka sama liczba w wierszu a typy zapisanych zmiennych są w pliku różne więc muszę wydobywać je po kolei. Na szczęście już wszystko działa prawidłowo - wystarczyło dopisać clear() przy stworzonych strumieniach po każdym ich wywołaniu ;).
@_13th_Dragon ale dzięki! ;-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1