przekazywanie linii z pliku do vectora

0

Zamysł jest taki aby odczytać z pliku txt linie osobno, to znaczy pierwsza linia pliku tekstowego to ilość zestawów danych, 2 linia to liczba elementów podanych w 3 linii, 3 linia to elementy, 4 linia to liczba elementów podanych w 5 linii, 5 linia to elementy. Chciałbym linie 1,2,4 przechować w zmiennych, natomiast linie 3,5 przechować w tablicy. Stoje w miejscu i nie wiem jak rozwiązać ten problem ponieważ, moja funkcja znajdując się w 3 linii pliku tekstowego pobiera wszystkie liczby do końca. Chciałem to zrobić tak(niestety nie działa,pewnie przez spacje w txt):

for (size_t j = 0; j < size1; j++)
                {
                    v1.push_back(value);
                {

//////////////////////////////////////

Mój plik wyjściowo wygląda tak:

1
4
-5 -1 0 8 
7
7 9 2 0 -7 2 -5 

Wynik dla powyższych danych który otrzymuje to:

line1:1
line2:4
line3: -5 -1 0 8 7 7 9 2 0 -7 2 -5
line4:6422004
line5:

Poprawny wynik dla powyższych danych którego nie otrzymuje:

line1:1
line2:4
line3:-5 -1 0 8  
line4:7
line5:7 9 2 0 -7 2 -5

Kod:

void fromFile(std::fstream &myFile)
{
    int dataSets, size1, size2, value;
    std::vector<int> v1, v2;
    string line;
    if (myFile.is_open())
    {
        myFile >> dataSets;
        goToLine(myFile, 2);
        for (std::size_t i = 0; i < dataSets; ++i)
        {
            myFile >> size1;
            goToLine(myFile, 3);
            while (getline(myFile, line))
            {
                std::istringstream ss(line);
                for (size_t j = 0; j < size1; j++)
                {
                    while (ss >> value)
                    {
                        v1.push_back(value);
                    }
                }
            }
            goToLine(myFile, 4);
            myFile >> size2;
            goToLine(myFile, 5);
            while (getline(myFile, line))
            {
                std::istringstream ss(line);

                while (ss >> value)
                {
                    v2.push_back(value);
                }
            }
        }
    }
    cout << "line1:" << dataSets << endl;
    cout << "line2:" << size1 << endl;
    cout << "line3: ";
    for (size_t i = 0; i < v1.size(); i++)
        cout << v1[i] << " ";
    cout << endl;
    cout << "line4:" << size2 << endl;
    cout << "line5: ";
    for (size_t i = 0; i < v2.size(); i++)
        cout << v2[i] << " ";
}

std::fstream &goToLine(std::fstream &file, unsigned int num)
{
    file.seekg(std::ios::beg);
    for (int i = 0; i < num - 1; ++i)
    {
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return file;
}
1

Wygląda jak zadanie SPOJ/hackerrank lub pokrewny.
Podaj linka, żeby było wszystko jasne.

Poza tym twoje pytanie cierpi na problem XY. Pytasz jak naprawić twój pomysł na rozwiązanie problemu, zamiast pytać jak rozwiązać jakiś problem i czy twoje podejście do niego ma sens.

2

Chciałbym linie 1,2,4 przechować w zmiennych, natomiast linie 3,5 przechować w tablicy

Masz tu szkielet.

size_t i= 1;
for(std::string line; std::getline(inFile, line); ++i)
{
   if(i == 1 /*2 lub 4*/)
       /* przypisanie do zmiennej*/;
   else if(i == 3 || i == 5)
       /* wpisnanie do tablicy*/;
}
0

Można coś takiego.
Pobieranie danych z pliku do wektora:

std::pair<int,std::vector<std::vector<int>>> getDataFromFile(std::fstream &file){
	int data_pack = getNumbersFromLine(file,1)[0];

	std::vector<std::vector<int>> data;
	while(file.good() && !file.eof()){
		try{
			int number_of_numbers = getNumbersFromLine(file,1)[0];
			data.push_back(getNumbersFromLine(file,number_of_numbers));
		}catch(std::runtime_error&){}
	}
	return std::pair<int,std::vector<std::vector<int>>>(data_pack,data);
}

Odczyt samych danych z pliku może wyglądać tak:

std::vector<int> getNumbersFromLine(std::fstream &file,int number_of_numbers){
	std::string str;
	std::getline(file,str);
	
	std::stringstream ss(str);
	std::vector<int> out_value;
	for(int tmp;ss >> tmp;){
		out_value.push_back(tmp);
	}
	if(static_cast<int>(out_value.size()) != number_of_numbers){
		throw std::runtime_error("Bad number of numbers ");
	}

	return out_value;
}

A wyświetlanie jakoś tak:

data = getDataFromFile(file);
std::cout << "Data packs: " << data.first << "\n";
for(std::vector<int> &line : data.second){
    std::cout << "Number of elements: " << line.size() << "\nElements:\n";
    for(int value : line){
        std::cout << value << " ";
    }
    std::cout << "\n";
}

Powinno odczytywać tylko te dobre "dwójki" i działać poprawnie PRAWIE we wszystkich przypadkach.

0

Z komentarza

a co gdy mamy 3 zestawy czyli 13 linijek w pliku?(bo 1 linijka to ilosc zestawow)

W czym konkretnie problem? Jeżeli umiesz przypisywać do zmiennej i napisać sam swojego if to to nie powinienem być problem mając kod który podałem.

no i jaki bedzie argument dla push_back ?

Dla którego wektora? Bo masz dwa. Zresztą i tak Ci nie odpowiem bo Twój kod nie jest najprzyjemniejszy do analizy. Zresztą nie wiem czemu potrzebujesz jakiś wektorów tutaj. Patrząc na wejście i poprawne wyjście to jedyne co potrzebujesz to coś takiego:

size_t i= 1;
for(std::string line; std::getline(inFile, line); ++i)
{
     std::cout << "line" << i << ":" << line << "\n";
}
1

Jesli to zadanie ze SPOJa lub pokrewne to te dane bym przechowywal nigdzie tzn po odczytaniu kolejnego zestawu po prostu go przetworzyl. To taka ogolna zasada ktora ulatwia rozwiazanie, ale bywaja wyjatki.

0
vpiotr napisał(a):

Jesli to zadanie ze SPOJa lub pokrewne to te dane bym przechowywal nigdzie tzn po odczytaniu kolejnego zestawu po prostu go przetworzyl. To taka ogolna zasada ktora ulatwia rozwiazanie, ale bywaja wyjatki.

Z przeciwnej strony jest powołanie klasy, która odwzorowuje dane jednej paczki (tak bym zrobił). Wczytanie tego sekwencyjne w 10ciu liniach (a nie kilkudziesięciu), i przetwarzanie ja się chce.

// pseudokod
class Zestaw {
   int ilość1;
   std::vector elementy1;
  int ilosc2;
  std::vector elementy2;
// opcjonalnie, puryści nie krzyczeć
  void wczytaj( & std::fstream);
}

Jak się da zrozumieć, bez "globalnego" vectora i danych, bardzo czysta metoda wczytaj() (i tylko wczytaj, reszta przetwarzania, w tym drukowanie, jest gdzie indziej)
Jak na razie @micw zrobiłeś niemal wszystko, aby to zamotać.

0
micw napisał(a):

std::fstream &goToLine(std::fstream &file, unsigned int num)

Kicanie po pliku to najlepszy sposób na zamotanie się na amen. To się bardzo prosto da przeczytać sekwencyjnie

MarekR22 napisał(a):

Poza tym twoje pytanie cierpi na problem XY. Pytasz jak naprawić twój pomysł na rozwiązanie problemu, zamiast pytać jak rozwiązać jakiś problem i czy twoje podejście do niego ma sens.

Tego nie da się NAPRAWIĆ. Tylko zaorać, i zrobić od początku

0

problem jest dla na przyklad 100 zestawow, wtedy jest 401 linii w kodzie i nie wiem jak dla kazdego zestawu osobno wywołać funkcje ktora bedzie zwracac wartosc operacji na elementach z tych 4 linii

0

@several: zrobiłem to tak, ale wszystko źle się przypisuje

size_t i = 1;
    int n;
    for (std::string line; std::getline(myFile, line); ++i)
    {
        int n;
        if (i == 1)
            myFile >> dataSets;
        else if (i == 2)
            myFile >> size1;
        else if (i == 3)
        {
            while (myFile >> n)
                v1.push_back(n);
        }
        else if (i == 4)
            myFile >> size2;
        else if (i == 5)
        {
            while (myFile >> n)
                v2.push_back(n);
        }
       
    }
1

Dlaczego w ogóle skupiasz się na pierdołach typu "numer linii"?
Całe wczytywanie z pliku powinnno wyglądać mniej więcej:

std::ifstream file{"plik.txt"};
 if (!file) return 0;
auto const num = read_datasets_num(file);
std::vector<dataset> datasets(num);
std::copy_n(std::istream_iterator<dataset>{file}, num, datasets.begin());
/*... rób dalej co chcesz ...*/

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