2013-08-22 42 views
1

我有使用strtok()功能的小问题。 我解析两个文件。 Firts我加载文件1到buffer。该文件constains我需要加载的第二个文件的名称。这两个文件都是一行一行读取的。我的代码如下所示:C++的strtok - 多用更多的数据缓冲区使用

char second_file_name[128] = { "" }; 
char * line = strtok(buffer, "\n"); 
while(line != NULL) 
{ 
    if (line[0] = 'f') 
    { 
    sscanf(line, "%*s %s", &second_file_name); 
    LoadSecondFile(second_file_name); 
    } 
    // processing other lines, not relevant for question 
    line = strtok(NULL, "\n"); 
} 

虽然LoadSecondFile(...)功能非常相同的方式工作,即:

char * line = strtok(buffer, "\n"); 
while(line != NULL) 
{ 
    // process file data 
    line = strtok(NULL, "\n"); 
} 

我的问题是什么,调用LoadSecondFile(...)功能后,用于解析的strtok()指针第一个文件变得“搞砸了”。它不会给我第二个文件的名字后面的行,它不会给我什么 - 理解为“完全废话”。我是否知道这是由strtok()指针在程序中共享引起的,而不仅仅是在函数中?如果是这样,我怎么能“备份”用于解析第一个文件strtok()的指针,然后再使用它来解析第二个文件?

感谢您的任何建议。 干杯。

+2

偏离主题,但您应该启用编译器警告来捕捉错误,如if(line [0] ='f')'。 –

+0

嘿我在这里输入代码时,完全错过了这个错误,谢谢:) –

回答

7

strtok是一个邪恶的小功能,维护全局状态,所以(如你发现),你不能tokenise在同一时间两个字符串。在一些平台上,有更少的邪恶变体,名称如strtok_rstrtok_s;但既然你在编写C++而不是C,为什么不使用C++库呢?

ifstream first_file(first_file_name);  // no need to read into a buffer 
string line; 
while (getline(first_file, line)) { 
    if (!line.empty() && line[0] == 'f') { // NOT = 
     istringstream line_stream(line); 
     string second_file_name; 
     line_stream.ignore(' ');   // skip first word ("%*s") 
     line_stream >> second_file_name; // read second word ("%s") 
     LoadSecondFile(second_file_name); 
    } 
} 
3

您可以使用strtok_r它可以让你有不同的状态指针。

+1

我建议将“可以使用”到“_must_使用”。 – mah

+0

您可能会指出这是一个Unix扩展,可能在其他系统上可用或不可用。它仍然修改它正在解析的缓冲区。 –

+0

@mah:不,C++库也是一个选项。这是可移植的(不像'strtok_r'),并且还修复了缓冲区溢出漏洞。 –

3

这就是为什么它不断推荐到而不是使用strtok (更不用说线程的问题了)。有许多 更好的解决方案,使用C++标准库 的功能。其中没有一个修改他们正在处理的文本,并且其中没有一个使用隐藏的静态状态。

+0

那么,我的应用程序是单线程的,我不需要文本保持原样,我只需要阅读一次并处理它。你能指出任何有效的方法来逐行解析文件,而不使用'strtok()'吗? –

+1

'std :: find','std :: find_if','std :: find_first_of','std :: search' ...所有这些都比'strtok'或其任何“更安全”的替代品。 –