zliczenie ilości wierszy w pliku csv - kopiowanie danych do tablicy 2D

0

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!

0

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.

0

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

0
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?

1

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/

1
#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;
  }

http://ideone.com/H88Qb2

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