2016-04-21 439 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

相關問題