Witam ponownie :)
mam następujący problem: chcę skopiować dane z pliku do tablicy 2D. Plik jest typu csv i zawiera N wierszy w których są umieszczone dane liczbowe typu double, które są odseparowane znakiem ";". Ilość wierszy jest nieokreślona, ale może być ich nawet kilka milionów.
Problem jest taki, że nie wiem ile jest wierszy a ile zmiennych w każdym wierszu, przy czym w każdym wierszu na pewno jest tyle samo znaków.
Moje pytanie brzmi: jak mogę najszybciej policzyć liczbę wierszy, by móc później utworzyć tablicę 2D o rozmiarze tablica[liczba_wierszy][liczba_kolumn]; i skopiować owe dane?
Jedno z rozwiązań to użycie funkcji getline ale zastanawiam się, czy nie da się tego zrobić optymalniej? tzn. zamiast kopiować całe linie może da się je tylko zliczać?
Z góry dzięki za pomoc!
Poczytaj o tablicach dynamicznych. Jeżeli zawsze te dane będą lądować w tablicy 2D to nie musisz liczyć wierszy. Kolejno czytasz wiersze za pomocą fgets i po prostu reallokujesz. Potem może wyślę Ci przykładzik.
jeśli każdy wiersz ma dokladnie tyle samo znaków tak jak powiedziałeś to sprawdzasz długość pierwszej linii i potem:
liczba_linii = wielkosc_pliku[bajty] / wielkosc_pierwszej_linii[bajty]
pamiętaj, żeby do wielkosci pierwszej linii wliczyc znaki typu: \r,\n
karolinaa napisał(a):
Poczytaj o tablicach dynamicznych. Jeżeli zawsze te dane będą lądować w tablicy 2D to nie musisz liczyć wierszy. Kolejno czytasz wiersze za pomocą fgets i po prostu reallokujesz. Potem może wyślę Ci przykładzik.
No właśnie nie wiem, czy to dobry pomysł, gdy danych jest dużo. Wydaje mi się, że taka realokacja jest dość kosztowna i lepiej już policzyć te wiersze np. tak:
unsigned int line_number = 0;
string line = "";
while(getline(file, line))
line_number++;
a następnie zaalokować odpowiednio dużą tablicę.
krwq napisał(a):
jeśli każdy wiersz ma dokladnie tyle samo znaków tak jak powiedziałeś to sprawdzasz długość pierwszej linii i potem:
liczba_linii = wielkosc_pliku[bajty] / wielkosc_pierwszej_linii[bajty]pamiętaj, żeby do wielkosci pierwszej linii wliczyc znaki typu: \r,\n
W sumie rzeczywiście tak można, chociaż chwilowo coś mi się obliczenia nie zgadzają :/ -> muszę jeszcze nad nimi popracować ;)
A przy okazji mam drugie pytanie:
dane w wierszu mogą wyglądać np. tak:
423.213;12.3424;3.3423;
Ja każdy wiersz wyciągam przy pomocy getlinu, który jest zapisywany do stringa.
Mam pytanko jak najprościej wydobyć te zmienne i zapisać do tablicy?
Rzeczywiście masz rację. Jeżeli wszystkie wiesze mają po tyle samo znaków i wyglądają jak ten przykładowy może te kilka funkcji http://ideone.com/CxuvgG Ci pomoże. A może skorzystaj po prostu z http://sourceforge.net/projects/libcsv/
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;
struct WS
{
static char skip[];
bool newline;
WS():newline(true) {}
friend istream &operator>>(istream &s,WS &w)
{
w.newline=false;
int ch;
while((ch=s.get())!=EOF)
{
if(ch=='\n') { w.newline=true; break; }
if(strchr(skip,ch)) break;
}
return s;
}
};
char WS::skip[]=";";
int main()
{
vector<vector<double> > Tb;
WS ws;
while(cin)
{
if(ws.newline) Tb.resize(Tb.size()+1);
unsigned y=Tb.size()-1,x=Tb[y].size();
Tb[y].resize(x+1);
cin>>Tb[y][x]>>ws;
}
for(unsigned y=0;y<Tb.size();++y,cout<<endl) for(unsigned x=0;x<Tb[y].size();++x) cout<<"\t"<<Tb[y][x];
return 0;
}