Czytanie całych linii z pliku tekstowego i dodawanie ich do wektora

0

Witam, chce zapisac dane z pliku tekstowego do wektora i mam taki problem, jak mam 2 wyrazy w jednej linni w pliku tekstowym to w programie ten drugi wyraz spycha do drugiej linii, a ja chce, zeby pozostal w tej samej. Co mam zrobic?

Wczytaj(){

    plik.open( "pokoje.txt", ios::in );
    if( plik.good() )
    {
        while( !plik.eof() )
        {
            string napis;
 
            getline(plik,napis);
            Bufor.push_back(napis);
 
 
  
        }
        plik.close();
    } else cout << "Error! Nie udalo otworzyc sie pliku!" << endl;
    int i = 0;
   while(i < Bufor.size())
   {
 
       string temp = Bufor[i];
       istringstream iss(temp);
       i++;
 
    do
    {
        string sub;
        iss >> sub;
        if(sub.length() != 0)
        data.push_back(sub);
 
 
    } while (iss);
 
   }
    i = 0;
    while(i < data.size())
    {
 
 
 
            cout << data[i] << endl;
            i++;
 
                     
 
 
    }
 
}
0

To ma być funkcja, która wczytuje plik linijka po linijce i zapisuje do wektora?

5
std::ifstream file("pokoje.txt");
std::string line;
std::vector<std::string> result;
while (std::getline(file, line)) {
    result.push_back(std::move(line));
}
1

Ten std::move pasuje tu jak pięść do oka.
Zwróć uwagę, że line jest używane wielokrotnie w pętli, więc wielokrotnie próbujesz robić na nim move.

3
MarekR22 napisał(a):

wielokrotnie próbujesz robić na nim move.

I w czym problem?
Standard zabrania czytania z std-obiektu na którym wykonaliśmy std::move (wspomniane przez kolege @Mokrowski [lib.types.movedfrom]).

17.6.5.15 Moved-from state of library types                                         [lib.types.movedfrom]

Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

Nie zabrania jednak nigdzie operacji write na takim obiekcie - a tak dzieje się w moim kodzie (write -> move -> write -> ...). Po takiej operacji write (w std::getline) obiekt jest jak najbardziej poprawny. Nie jestem w stanie wyobrazić sobie bardziej książkowego użycia std::move - w końcu bez niego będziemy kopiowali każdą linijkę w pliku i zdecydowanie wpłynie to na wydajność.

0

w visual studio się kompiluje, ale nic się nie dzieje. mam tylko press any key to continue

1
MarekR22 napisał(a):

Ten std::move pasuje tu jak pięść do oka.
Zwróć uwagę, że line jest używane wielokrotnie w pętli, więc wielokrotnie próbujesz robić na nim move.

Przecież robi move na różnych obiektach (są wczytywane nowe wartości), nie wielokrotnie na tym samym... Więc ok.

0

Alternatywnie można ew. mieć własny LineReader...
Nie upieram się że szybsze (bo nie ma semantyki przenoszenia a jej dodanie "spulchni kod" z konieczności implementacji własnego back_inserter'a) ale czasem może być wygodniejsze a to także się liczy :-)

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <iterator>

struct LineReader: public std::string {
    friend std::istream& operator>>(std::istream& is, LineReader& lineReader) {
        return std::getline(is, lineReader);
    }
};

int main() {
    std::vector<std::string> vec;
    std::ifstream file("/tmp/data.txt");

    using LineIt = std::istream_iterator<LineReader>;
    std::copy(LineIt(file), LineIt(), std::back_inserter(vec));

    // prezentacja wczytanych danych 
    for(const auto& line: vec) {
        std::cout << line << '\n';
    }
}

PS Dla tych którzy mają wątpliwości co do dziedziczenia z kontenera std (choć tu jest to jak najbardziej poprawne bo nie są dodawane żadne atrybuty które należy niszczyć w specjalizowanym destruktorze wirtualnym), można podać rozwiązanie alternatywne. IMHO mniej uniwersalne:

struct LineReader {
    std::string data;
public:
    friend std::istream& operator>>(std::istream& is, LineReader& lineReader) {
        return std::getline(is, lineReader.data);
    }
    operator std::string() const {
        return data; 
    }
};

Jeszcze innym sposobem jest modyfikacja lokalizacji strumienia (modyfikacja znaczeń separatorów). Ale to IMHO jest już strzelanie z armaty do wróbla.

0
dziadek69 napisał(a):

w visual studio się kompiluje, ale nic się nie dzieje. mam tylko press any key to continue

Czyli program leci od razu do końca.
Sprawdź czy wywołujesz co trzeba i co na pewno zmodyfikowałeś wprowadzając poprawki zgodnie z radami kolegów. Jeśli do niczego nie dojdziesz to debuguj, a potem wrzuć kod.

0

Nie lepiej stworzyć strukturę/klasę, która sama sobie poradzi z wczytywaniem zamiast się bawić z linijkami?

struct Data
{
  std::string first;
  std::string second;
  friend std::istream& operator>>(std::istream& in, Data obj )
  {
    in >> first >> second;
    return in;
  }
};

I wczytywanie upraszcza się do:

std::vector< Data > dataCollection;
std::copy( std::istream_iterator< Data >( file ), std::istream_iterator< Data >(), std::back_inserter( dataCollection ) );

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