2016-04-21 438 views
-2

我一直在尝试阅读以下数据表并为HUB(行)和另一个对象(大陆)(列)创建对象。由于我不是C++经验丰富的用户,我一直面临一些困难。数据如下。 HUB和破折号后面的数字显示了枢纽的顺序。每个大陆下的其他数字是HUB与大陆之间的相应成本和关税。我希望能来清点例如下面,让这将是73 cout << hub(1)->cont(USA)->transport() << endl;从逗号分隔的数据文件中读取列C++

,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(); 
    } 
+2

可以通过'getline'从''头读取每一行。然后,您可以将每行字符串放入一个“istringstream”中,并通过'getline'读取每个数据,方法是将逗号指定为行分隔符。但这实在太开放了:有很多方法可以做到这一点,所以投票结果太宽泛。 –

回答

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

的Makefile

all: t 

t: csv.cpp 
    g++ -I /usr/include/boost csv.cpp -o t 
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); 
      // ... 
     } 
    } 
0

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

例如:

class Tariff 
{ 
    int values[3]; 
    public: 
    friend std::istream& operator>>(std::istream& input, Tariff& t); 
}; 

std::istream& operator>>(std::istream& input, Tariff& t) 
{ 
    // Read and ignore the label "Tariff" 
    std::string name; 
    std::getline(input, name, ','); // Read until ',' delimiter. 
    input >> t.value[0]; 
    // Note: the ',' is not a digit, so it causes an error state, 
    // which must be cleared. 
    input.clear(); 
    input >> t.value[1]; 
    input.clear(); 
    input >> t.value[2]; 
    input.clear(); 
} 

另一种方法是首先读取标签,则委托给该行中读出的功能。

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&)>

+0

** Downvoter **:请添加注释,解释您的downvote。 –

+0

..这看起来像一个有效的答复,为什么downvote它......这将肯定有助于改善答案,如果downvoter将强制评论,可能是因为可以看看这些类型的问题:( – Tejendra

相关问题