2013-06-02 103 views
0

我成功編寫了將包含文本數據的.dat文件寫入一維數組的代碼。但是,當我試圖開發我的代碼將這些文件寫入二維數組時,我一直在指出問題。下面的代碼是什麼,我試圖修復:將文件寫入二維數組

while (getline(fin, line)) { 
    char* buf = _strdup(line.c_str()); 
    // parse the line into blank-delimited tokens 
    int n = 0; // a for-loop index 
    int s = 0; 
    int m = 0; 
    // array to store memory addresses of the tokens in buf 
    const char* token[MAX_TOKENS_PER_LINE][MAX_TOKENS_PER_LINE] = {}; 
    char *next_token; 
    // parse the line 
    token[0][0] = strtok_s(buf, DELIMITER, &next_token); // first token 
    //token[0] = strtok(buf, DELIMITER); // first token 
    if (token[0][0]) { 
    // zero if line is blank 
    for (n = 1; n < MAX_TOKENS_PER_LINE; n++) { 
     token[m][n] = strtok_s(0, DELIMITER, &next_token); 
     //token[n] = strtok(0, DELIMITER); 
     if (!token[m][n]) break; // no more tokens 
     m++; 
    } 
    } 
    // process (print) the tokens 
    for (int i = 0; i < n; i++) // n = #of tokens 
    for (int j = 0; j<m; j++) { 
     cout << "Token[" << i << "," << j << "] = " << token[i][j] << endl; 
     cout << endl; 
    } 
    fin.clear(); 
    fin.close(); 
    free(buf); 
} 

顯然,第一行後的第一個令牌token[0][0]將指向垃圾爲不同的數據將在buf。如何避免這個問題?

+1

在你的打印循環中,你可以使用'i'作爲第一個索引,'j'作爲第二個索引,'j'使用'm'。但是,當你閱讀時,你使用'm'作爲第一個索引,'n'作爲第二個索引。 –

+0

此外,你讀了一個循環,但關閉你從循環內讀取的文件? –

+0

你總是在標記循環中增加'm'和'n',這意味着你將設置'token [0] [0]',然後'token [1] [1]'等等。 –

回答

0

您需要令牌陣列中的「複製走」每個令牌,就像

 if (token[0][0]) // zero if line is blank 
     { token[0][0] = _strdup(token[0][0]); 
      for (n = 1; n < MAX_TOKENS_PER_LINE; n++) 
      { token[m][n] = strtok_s(0, DELIMITER, &next_token); 
       if (!token[m][n]) break; // no more tokens 
       token[m][n] = _strdup(token[m][n]); 
       m++; 
      } 
     } 

和自由的元素以後。

另外:你是在文件的最後釋放的buf指針,你需要釋放它的每一行 - 事實上,與上述邏輯,你並不需要調用_strdup()buf,它可以只是char* buf = line.c_str();

2

更好的解決方案可能是使用std::istringstreamstd::getline爲令牌化太:

std::vector<std::vector<std::string>> tokens; 

int current_line = 0; 
std::string line; 
while (std::getline(fin, line)) 
{ 
    // Create an empty vector for this line 
    tokens.push_back(std::vector<std::string>()); 

    std::istringstream is(line); 

    std::string token; 
    while (std::getline(is, token, DELIMITER)) 
     tokens[current_line].push_back(token); 

    current_line++; 
} 

在此之後,tokens將包含在文件中每行一個條目,每個條目將成爲( possib ly空)矢量的令牌。

+0

太棒了!但我需要知道我是否可以稍後參考每個元素的「標記」,如果可能,我該如何實現?或向量將在內存中的每一行之後被清除? – Hawk

+0

@hawk向量在循環中聲明_before_,所以它將在循環完成後保留所有數據。如果你把它放在一個單獨的函數中,你可以返回它,或者通過引用作爲參數傳遞它,或者將它聲明爲一個類的成員,或者如果你喜歡,可以在全局聲明它。 –