strtok字符串并修改令牌值

时间:2012-11-06 01:30:04

标签: c++ strtok

我正在进行字符串标记化,类似于下面的示例。但是,在while循环中,我将把字母“a”改为“hellow”,例如。在分配到myVar [i]之前尝试更改pch时,我得到分段错误。我应该怎么做呢?

    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 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

你知道,事情是:strtok 修改传递给它的字符串。 如果您尝试在字符串常量上使用它,这通常会出现段错误,因为内存实际上并不是您的改变。

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

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