0

嗨,我正在做类似于下面的示例的字符串标记化。但是,例如,在 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++;
     }
4

2 回答 2

2

while我在你的循环中看到了两个错误:

1)您将其stringstream本身而不是它包含的数据传递给memcpy(). 您依赖于stringstream::operator void*()转换运算符。您不应该尊重该指针,因为它不指向实际数据。它只是一个标志,表明它是否stringstream有效。要将stringstream数据传递给memcpy(),您必须首先调用它的str()方法来获取std::string包含数据的 a,然后调用它的c_str()方法将该数据传递给memcpy()

2)当您将值插入到您的中时,您每次std::map都插入一个局部变量。之后立即超出范围,将char[]包含指向随机位置的指针留在堆栈上。鉴于您显示的代码,缓冲区可能每次都重用相同的堆栈空间。char[]std::mapchar[]

由于您使用的是 C++,因此您确实应该使用更多面向 C++ 的东西,例如std::string,std::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);
于 2012-11-06T02:31:55.950 回答
0

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

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

char *srcStr = "Some constant text";
char *tmpStr = strdup(srcStr);
//...
//some operations involving strtok
//...
free(tmpStr);
于 2012-11-06T01:51:32.443 回答