Привет, я делаю токенизацию строк, как в примере ниже. однако в цикле while я буду менять букву ‘a’ на ‘hellow’, например. я получаю ошибку сегментации при попытке изменить pch перед присвоением myVar [i]. как мне это сделать?
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++;
}
Я вижу две ошибки внутри вашего 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);
Видишь ли, дело в том: strtok модифицирует строка передана ему.
Это часто приводит к ошибкам, если вы пытаетесь использовать его для строковой константы, так как память на самом деле не ваша для изменения.
Метод, который я использую, чтобы обойти это, всегда использовать strtok на дублировать строки.
char *srcStr = "Some constant text";
char *tmpStr = strdup(srcStr);
//...
//some operations involving strtok
//...
free(tmpStr);