2017-11-15 6 views
0

Ich möchte Daten aus einer CSV-Datei extrahieren, aber ich muss zuerst die Anzahl der Zeilen und Spalten der Tabelle erhalten.Alternative für gelöschte Kopie Konstruktor von Ifstream

Was ich bisher habe, ist die folgende:

 std::ifstream myfile(filename); // filename is a string and passed in by the constructor 
     if (myfile.is_open()) 
     { 
      // First step: Get number of rows and columns of the matrix to initialize it. 
      // We have to close and re-open the file each time we want to work with it. 
      int rows = getRows(myfile); 
      std::ifstream myfile1(filename); 
      int columns = getColumns(myfile1); 

      if (rows == columns) // Matrix has to be quadratic. 
      { 
       std::ifstream myfile2(filename); 
       abwicklungsdreieck.set_Matrix(QuantLib::Matrix(rows, columns, 0)); // abwicklungsdreieck is initialised before 
       //... 
      } 
      else 
      { 
       std::cout << "\nNumber of rows has to equal number of columns."; 
      } 
     } 
    // [...] 
    int getRows(std::ifstream &myfile) 
    { 
     std::string line; 
     int rows = 0; 

     while (std::getline(myfile, line)) // While-loop simply counts rows. 
     { 
      rows++; 
     } 
     myfile.close(); 
     return rows - 1; 
    } 

    int getColumns(std::ifstream &myfile) 
    { 
     std::string line; 
     char delimiter = ';'; 
     size_t pos = 0; 
     int columns = 0; 

     while (std::getline(myfile, line) && columns == 0) // Consider first line in the .csv file. 
     { 
      line = line + ";"; 
      while ((pos = line.find(delimiter)) != std::string::npos) // Counts columns. 
      { 
       line.erase(0, pos + 1); 
       columns++; 
      } 
     } 
     myfile.close(); 
     return columns - 1; 
    } 

Dieser Code funktioniert. Allerdings muss ich die Datei dreimal öffnen, was mir nicht gefällt. Gibt es eine Möglichkeit, dies zu umgehen?

Ich dachte über die Arbeit mit TEMP-Dateien in getRows() und getColumns(), aber das Kopieren von Streams ist nicht möglich, da es keinen Sinn ergibt, wie ich kürzlich gelernt habe.

Also, gibt es einen anderen Weg, das zu tun? Oder kann ich beispielsweise die Methoden getline() und line.erase() umgehen?

+1

Warum denken Sie, dass Sie die Datei dreimal öffnen müssen? – user463035818

+1

vielleicht ist das die Quelle Ihres Missverständnisses: Sie können keinen Stream kopieren, aber Sie können Referenzen nach Belieben weitergeben. Öffne es einmal, führe es herum, mach ein paar Sachen, schließe es einmal. – user463035818

+0

Ja, aber wie gebe ich es weiter? getLine (& myfile) funktioniert nicht .. –

Antwort

0

Sie können die Datei Zeile für Zeile lesen, jede Zeile in einen Strom umwandeln, dann die Spalten auf dem Stream lesen:

std::ifstream myfile(filename); 
if(!myfile) return 0; 

std::string line; 
while(std::getline(myfile, line)) 
{ 
    std::stringstream ss(line); 
    std::string column; 
    while(std::getline(ss, column, ';')) 
    { 
     cout << column; 
    } 
    cout << "\n"; 
} 

getline(myfile, line) wird jede Zeile in zu line kopieren.

Zeile in ss umwandeln.

getline(ss, column, ';') wird die Zeile in Spalten umbrechen.

Verwenden Sie std::stoi, um die Zeichenfolge in Ganzzahl zu konvertieren.

Wenn Ihre Matrix auf std::vector basiert, können Sie den Vektor eine Zeile nach der anderen vergrößern, so dass Sie die Größe nicht im Voraus wissen müssen.

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

void readfile(const std::string &filename) 
{ 
    std::vector<std::vector<int>> matrix; 
    std::ifstream myfile(filename); 
    if(!myfile) return; 
    std::string buf; 
    while(std::getline(myfile, buf)) 
    { 
     int maxrow = matrix.size(); 
     std::stringstream ss(buf); 
     matrix.resize(maxrow + 1); 
     cout << "break in to columns:" << buf << "\n"; 
     while(std::getline(ss, buf, ';')) 
     { 
      try { 
       int num = std::stoi(buf); 
       matrix[maxrow].push_back(num); 
      } 
      catch(...) { } 
     } 
    } 

    for(auto &row : matrix) { 
     for(auto col : row) 
      cout << col << "|"; 
     cout << "\n"; 
    } 
} 
+0

Danke für Ihre Antwort. Ich weiß, dass das Erstellen der Matrix über Vektoren dies einfacher macht, aber ich möchte QuantLib :: Matrix verwenden, da ich einige Funktionen davon im weiteren Code brauche. Daher muss ich im Voraus wissen, wie viele Zeilen und Spalten es gibt. Nach der setMatrix wird eine Funktion readFile (abwicklungsdreieck, myfile2) aufgerufen, die die Datei liest und die Werte daraus in die Matrix des Abwicklungsdreiecks setzt. –

Verwandte Themen