2012-11-06 107 views
0

嗨即时做字符串标记化类似于下面的例子。然而,在while循环中,例如,我将改变字母'a'为'hellow'。在分配myVar [i]之前尝试更改pch时,出现分段错误。我该如何去做呢?strtok字符串和修改令牌值

map <int, char*> myVar; 
    char str[] ="- This, a sample string."; 
    char * pch; 
    printf ("Splitting string \"%s\" into tokens:\n",str); 
    pch = strtok (str," ,.-"); 
    int i = 0; 

    while (pch != NULL) 
    { 
     printf ("%s\n",pch); 

     //modify token value 
     stringstream strStream; 
     strStream << "hello_world"; 

     char newStr[7] = {0}; 
     memcpy(newStr, strStream, 7); 

     myVar[i] = (char*)newStr; 
     pch = strtok (NULL, " ,.-"); 
     i++; 
    } 
+2

你的意思是 “改变PCH”? – Gian

+4

您发布的代码不是您遇到问题的代码(对令牌没有任何更改)。发布*不*工作的代码。 –

+0

嘿抱歉,我已经编辑了上面的代码。 – nuttynibbles

回答

2

我看到你的while环内的两个错误:

1)要传递的stringstream本身,而不是数据它包含,以memcpy()。您正在依靠stringstream::operator void*()转换运算符。你不应该尊重那个指针,因为它并不指向实际的数据。这只是一个标志,表明stringstream是否有效。要将stringstream数据传递给memcpy(),您必须首先调用其str()方法以获取包含数据的std::string,然后调用其c_str()方法将该数据传递给memcpy()。 2)当您将值插入std::map时,您每次插入一个本地char[]变量。该char[]之后立即超出范围,使std::map包含指向堆栈中随机位置的指针。根据您所显示的代码,char[]缓冲区每次都可能重复使用相同的堆栈空间。

由于您使用C++,你真的应该使用更多的C++ - 面向的东西,比如std::stringstd::cout

试试这个:

std::map <int, std::string> myVar; 
std::string str = "- This, a sample string."; 
std::cout << "Splitting string \"" << str << "\" into tokens:" << std::endl; 
size_t start = 0; 
int i = 0; 

do 
{ 
    std::string token; 

    size_t pos = str.find_first_of(" ,.-", start); 
    if (pos != std::string::npos) 
    { 
     token = str.substr(start, pos-start); 
     start = pos + 1; 
    } 
    else 
    { 
     token = str.substr(start); 
     start = std::string::npos; 
    } 

    std::cout << token << std::endl; 

    //modify token value 
    myVar[i] = "hello_world"; 

    ++i; 
} 
while (start != std::string::npos); 
+0

是不是修改std :: string.c_str()的返回值的no-no? (正如strtok所做的那样) – enhzflep

+0

这是一个禁止修改由c_str()返回的值的方法。它清楚地写在文档中。引用http://www.cplusplus.com/reference/string/string/c_str/:“返回的数组指向一个内部位置,该位置具有此字符序列所需的存储空间及其终止空字符,但值这个数组不应该在程序中修改,只有在下一次调用字符串对象的非常量成员函数时才保证不变。“对于C++方式的建议+1,错误-1。结果0. – enhzflep

+0

那么,我说是应该替换'strtok()',毕竟。这将消除“修改c_str()”问题... –

0

你看,事情是:strtok的修改传递给它的字符串。 如果您尝试在字符串常量上使用它,通常会出现段错误,因为内存不是真的需要更改。

我用来解决这个问题的方法是始终在字符串的重复上使用strtok。

char *srcStr = "Some constant text"; 
char *tmpStr = strdup(srcStr); 
//... 
//some operations involving strtok 
//... 
free(tmpStr);