2012-10-23 176 views
0

可能重複:
Splitting a string in C++的strtok():將字符串轉換爲char *

char *strtok(char *s1, const char *s2) 

我怎麼能轉換string爲char *所要求的strtok?我做

for (string line; getline(sourceFile, line);) { 
    tokens = strtok(line.c_str(), " {};"); 
} 

sourceFileifstreamsourceFile.open(filepath.c_str());

我得到:類型 「爲const char *」 的

參數是與類型的參數不兼容 「的char *」

+2

因爲它是C++,這是怎麼回事? http://stackoverflow.com/questions/236129/splitting-a-string-in-c – chris

+2

你不想在C++字符串上使用'strtok()'; 'strtok()'破壞字符串,在標記結尾處插入NUL''\ 0''。使用什麼 - 任何 - 其他。 –

回答

0

如果你這樣做:

char fp[40]; // or some reasonable size 
strcpy(fp, filepath.c_str()); // fp is not a const char* like c_str() returns 

您應該能夠使用strtok()針對fp

但是,您可能需要考慮更多C++拆分字符串的方法。

+1

即使這樣,使'fp'成爲'std :: vector (filepath.size())'會更好。 – chris

+1

@chris:'std :: vector (filepath.size())' - 它應該是'size()+ 1',因爲你需要它爲'strtok()'終止NUL。 –

+0

@TonyD,哎呀,對吧。 – chris

2

正如其他人所說,你可能想使用strtok以外的東西。

但是,做你所要求的(你可能不應該):

for (string line; getline(sourceFile, line);) { 
    char* line_cstr = strdup(line.c_str()); 

    char* token = strtok(line_cstr, " {};"); 

    while ((token = strtok(NULL, " {};")) != NULL) { 
     //code 
    } 

    free(line_cstr); 

} 
+0

這裏使用strdup很不錯。 – Chimera

+1

這會以犧牲複製字符串爲代價,但我會建議使用boost :: tokenizer代替。 –

+0

@TimoGeusch我完全同意。當有更好的替代品可用時,無需使用這些混亂的C函數。 –

0

喬納森萊弗勒的評論解釋,strtok的實際修改緩衝區到位終止連續令牌。這對速度非常有用 - 可以將每個標記複製到其他一些存儲區域,同時還可以讓您以單獨的NUL終止序列方便地訪問它。在std::string實例中使用strtok是否合法是一個有趣的問題 - 當然,c_str()成員返回const char*,因爲您不打算覆蓋該緩衝區的某些部分。但是,只要你沒有一個空字符串(爲它給出未定義的行爲),你可以得到一個char*&line[0]的第一個元素。完成之後,您可以對字符串進行變異,但只能在偏移量[0]..[size()-1] ......不保證以NUL終止c_str()返回的緩衝區的方式,並且正是因爲&line[0]返回的緩衝區可能不適合使用通過strtok。你可以附加一個NUL(例如line += '\0' - NUL是合法的std::string內容),但它會使代碼有點難以維護,如果你打算將原始值用於任何東西。

如果您確實想使用strtok,似乎最好先將數據複製到單獨的可寫NUL終止緩衝區。例如:

char* p = strdup(line.c_str()); 
... use strtok on p ... 
free(p); 

你可以使用alloca(),智能指針,一個std::vector<char>,以儘量減少對內存泄漏的潛力。(我沒有看到任何特別的理由喜歡上述的C++ newdelete - 無論如何,你使用的是strtok,但是如果你有智能指針庫,期望它能適用它)。

所有這一切說,尋找另一種機制 - 如提升 - 這是一個更好的選擇。我猜這樣的替代品在鏈接克里斯張貼在您的問題下的評論中討論....