Obsługa pliku tekstowego w C++

0

Sorry, że nazwa tematu jest niezbyt dokładna. Zamiast zakładać milion różnych tematów, to wyłącznie w tym temacie chciałbym zadawać proste pytania co do obsługi .txt.

Zawartość mojego pliku:

1 2  
3 4
5 6
7 8
9 10
11 12

Chciałbym lewą kolumnę załadować do pierwszej tablicy intów, drugą kolumnę do drugiej tablicy intów. I wszystko działa dobrze:

#include <iostream>
#include <fstream>
//#include <vector>

int main()
{
    std::ifstream MyFile;
    MyFile.open("D:/zapis.txt");

    if (MyFile.good())
        std::cout << "MyFile.open has succeeded\n\n";
    else {
        std::cout << "MyFile.open has failed\n\n";
        return -1;
    }

    // count number of lines inside .txt to precisely determine arrays' size
    int number_of_lines = 0;
    std::string line;
    while (!MyFile.eof()) {
        std::getline(MyFile, line);
        number_of_lines++;
        }

    MyFile.seekg(0, std::ios::beg); // go to beginning of .txt

    int FirstColumn[number_of_lines], SecondColumn[number_of_lines];

    // read into arrays
    for (int i = 0; !MyFile.eof(); i++)
        MyFile >> FirstColumn[i] >> SecondColumn[i];

    // display arrays
    for (int i = 0; i < number_of_lines; i++)
        std::cout << FirstColumn[i] << '\t' << SecondColumn[i] << '\n';
}

Co jeśli mój plik tekstowy zawierałby więcej kolumn (nieznana liczba), ale chciałbym tylko dwie pierwsze kolumny ładować do dwóch tablic/wektorów? W różnych wierszach różna liczba kolumn np. taki plik .txt:

1 2 555 656
3 4 444
5 6 3
7 8
9 10
11 12 11162 4 5 5 4

Myślałem żeby zrobić coś w stylu:

// read into arrays
    for (int i = 0; !MyFile.eof(); i++) {
        MyFile >> FirstColumn[i] >> SecondColumn[i];
        (Wymuś przejście do następnej linii);
        }

Jakiś pomysł jak najprościej to zapisać?

1

Sposobów możesz sobie znaleźć parę ale na szybko:

  1. Wczytać linie,
  2. Przetwarzać liczbę aż do napotkania spacji(poczytaj o isspace) wtedy mamy pierwszą liczbę wczytaną,
  3. Przetwarzać dalej aż do napotkania następnej spacji czyli druga liczba wczytana
  4. Idziesz do nastęþnej lini
    Albo oprzeć się na find_if , szukać spacji ale dane pobierać jako pod stringi(początek-koniec(koniec to znalezienie spacji).
    https://stackoverflow.com/questions/2594502/count-white-spaces-to-the-left-of-a-line-in-a-text-file-using-c
0

@revcorey: @_0x666_

Po co korzystać z isspace lub istringstream?

Jak najłatwiej przejść do następnej linii? Jest jakiś sposób, żeby od razu przejść np. 441 linii w dół?

0
  1. Po co używać? A po to żeby znaleźć spację a jak ją znajdziesz to znaczy że jakieś tam słowo w tym wypadku się skończyła np. wczytuję sobie i wyciągam do zmiennej(pseudokod):
    sting napis = "10 20 30"
    int x;
    string tmp;
    for(auto& c : napis)
    { if (czyJestSpacją(c))
    x = tmp.toInt();
    tmp.clear();
    else
    tmp += c;
    }
    Sam pseudo kod nie ma większego sensu ale chyba rozumiesz do czego dążę.
    co do istringstream masz przykład z stacka
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
    std::string input = "abc,def,   ghi";
    std::istringstream ss(input);
    std::string token;
    size_t pos=-1;
    while(ss>>token) {
      while ((pos=token.rfind(',')) != std::string::npos) {
        token.erase(pos, 1);
      }
      std::cout << token << '\n';
    }
}
  1. Nie w prosty sposób. Jeśli nie znasz długości linii bądź w twoim ciągu są spacje(a to i tak taki trick bardzo jest) nie ma prostego sposobu.
1

@Hodor:

std::string line;
size_t i = 0;

while(std::getline(MyFile, line))
{
	std::istringstream iss(line);

	iss >> FirstColumn[i] >> SecondColumn[i];
	++i;
}

Choć jak chcesz odczytać tylko pierwsze dwie kolumny, to wystarczy:

size_t i = 0;

while(MyFile >> FirstColumn[i] >> SecondColumn[i])
{
	MyFile.ignore(std::numeric_limits<int>::max(), '\n');
	++i;
}

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