我正在进行字符串标记化,类似于下面的示例。但是,在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++;
}
答案 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::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);
答案 1 :(得分:0)
你知道,事情是:strtok 修改传递给它的字符串。 如果您尝试在字符串常量上使用它,这通常会出现段错误,因为内存实际上并不是您的改变。
我用来解决这个问题的方法是始终在字符串的重复上使用strtok。
char *srcStr = "Some constant text";
char *tmpStr = strdup(srcStr);
//...
//some operations involving strtok
//...
free(tmpStr);