从逗号分隔的数据文件c ++中读取列

时间:2016-04-21 14:09:40

标签: c++ c++11

我一直在尝试读取以下数据表,并为HUB(行)创建一个对象,为洲(列)创建另一个对象。由于我不是C ++经验丰富的用户,因此我遇到了一些困难。数据如下。 HUB和破折号后面的数字显示集线器的订单。每个大陆下的其他数字是HUB和大陆之间的相应成本和关税。我想能够cout例如跟随并获得结果,这将是73。 cout << hub(1)->cont(USA)->transport() << endl;

,USA,EUROPE,ASIA
HUB1-12000,,,
Transportation Cost,73,129,141
Tariffs,5,5,1
ShippingType,a,b,c
OtherFees,0.6,0.3,0.8
HUB2-11000,,,
Transportation Cost,57,101,57
Tariffs,7,7,5
ShippingType,b,b,d
OtherFees,0.7,0.3,0.6

非常感谢您的帮助。这是我到目前为止所尝试的:

    void Hub()
   {
     string file = "/hubs.csv";         

     // 1-First read the first line and save the continent name
     string str, field;
     getline( fin, str );
     vector<string> contList;
     stringstream linestr( str );
     while (  linestr.good() )
     {
       getline( linestr, field, ',' );
       string contname;
       contList.push_back(contname);
     }

     // 2-Then read the rest
     getline( fin, str );
     while ( !fin.eof() )  // Read the whole file
     {
       stringstream linestr( str );
       string contname, order;
       if ( qstr[0] == 'HUB1' || qstr[0] == 'HUB2')         
       {
         // Read the name of the hub
         getline( linestr, hubname, ',' );           // Read the hub name
         getline( linestr, order, ',' );             // Read the order quantityity

         int quantity;
         istringstream orderstream( order);
         orderstream >> quantity;

         // Find the hub and add the order to the hub
         Hub* hub = glob->FindHubName( hubname ); // this returns a pointer 
         if ( glob->FindHubName( hubname ) == nullptr )
         {
           hubNotFound.push_back( hubname );
           getline( fin, qstr );
           continue;
         }
         hub->TotalOrder( quantity );
       }
       else if ( qstr[0] != 'HUB1' || qstr[0] != 'HUB2')   
       {
         // Read costs and tariffs 
         cout << hub(1)->cont(ASIA)->transport() 
        }
       getline( fin, qstr );
     }
     fin.close();
   }

3 个答案:

答案 0 :(得分:0)

这样的事情:

#include <iostream>
#include <fstream>
#include <boost/tokenizer.hpp>
#include <string>

int main() {
   using namespace std;
   using namespace boost;

   string line, file_contents;
   fstream file("test.csv");

   if (!file.is_open()) {
     cerr << "Unable to open file" << endl;
     return 1;
   }


   getline(file, line);
   tokenizer<> tok_head(line);
   int n_columns = 0;
   for (tokenizer<>::iterator beg=tok_head.begin(); beg!=tok_head.end(); ++beg) {
       cout << *beg << '\t';
       n_columns++;
   }
   cout << endl;

   while (getline(file, line)) {
     file_contents += line;
   }

   file.close();

   tokenizer<> tok(file_contents);


   int i = 0;
   for (tokenizer<>::iterator beg=tok.begin(); beg!=tok.end(); ++beg, ++i) {
       cout << *beg;
       if (i % n_columns) {
         cout << '\t';
       } else {
         cout << endl;
       }
   }

   return 0;
}

<强>生成文件

all: t

t: csv.cpp
    g++ -I /usr/include/boost csv.cpp -o t

答案 1 :(得分:0)

看起来你必须使用不同的逻辑解析每一行,所以你应该首先检查第一列并使用它应用适当的逻辑,下面是一些伪代码:

    std::fstream fs("test.txt");
    std::string line;

    //
    // Read line by line
    while (std::getline(fs, line)) {

        std::istringstream str(line);
        std::string rec_type;

        // Read record type (your first two lines looks like are of no type?)
        if ( !std::getline(str, rec_type, ',') )
            continue;

        // Decide type of record, and parse it accordingly
        if ( rec_type == "Transportation Cost") {
            std::string val;

            // Read comma delimited values
            if ( !std::getline(str, val, ',') )
                continue;
            int ival1 = std::stoi(val);

            if ( !std::getline(str, val, ',') )
                continue;
            int ival2 = std::stoi(val);
            // ...
        }

        if ( rec_type == "Tariffs") {
            std::string val;
            if ( !std::getline(str, val, ',') )
                continue;
            int ival = std::stoi(val);
            // ...
        }
    }

答案 2 :(得分:0)

一种方法是将每一行视为单独的记录和对象 让对象读取他们的数据。

例如:

std::string row_text;
std::getline(text_file, row_text);  // Read in first line and ignore.
while (std::getline(text_file, row_text))
{
  std::istringstream text_stream(row_text);
  std::string label;
  std::getline(text_stream, label, ','); // Parse the label.

  // Delegate based on label.
  // Note: can't use switch for strings.
  if (label == "Tariffs")
  {
      Input_Tariff_Data(text_stream);
  }
  else if (label == "ShippingType")
  {
      Input_Shipping_Type_Data(text_stream);
  }
  //...
} // End-while 

另一种方法是首先读取标签,然后委托给读取行的函数。

if-else

typedef void (*P_Input_Processor)(std::istringstream& text_stream); struct Table_Entry { char const * label; *P_Input_Processor input_processor; }; //... const Table_Entry delegation_table[] = { {"Tariffs", Input_Tariff_Data}, {"ShippingType", Input_Shipping_Type_Data}, }; const unsigned int entry_quantity = sizeof(delegation_table) / sizeof(delegation_table[0]); // ... std::string row_text; std::getline(input_file, row_text); // Read and ignore first line. while (std::getline(input_file, row_text)) { // Create a stream for parsing. std::istringstream text_stream(row_text); // Extract label text std::string label; std::getline(text_stream, label, ','); // Lookup label in table and execute associated function. for (unsigned int index = 0; index < entry_quantity; ++index) { if (label == delegation_table[index].name) { // Execute the associated input function // by derferencing the function pointer. delegation_table[index](text_stream); break; } } } 梯形图可以由使用函数指针的查找表替换。有时桌子更容易阅读。

std::map<std::string, P_Input_Processor>

查找表的替代方法是使用:
std::map<std::string, void (*P_Input_Processor)(std::istringstream&)>

print "event.Ascii = ", event.Ascii