2013-06-02 80 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_,所以它将在循环完成后保留所有数据。如果你把它放在一个单独的函数中,你可以返回它,或者通过引用作为参数传递它,或者将它声明为一个类的成员,或者如果你喜欢,可以在全局声明它。 –