Ошибка сегментации при использовании strtok_r
Может кто-нибудь объяснить, почему я получаю ошибку сегментации в следующем примере?
#include <stdio.h>
#include <string.h>
int main(void) {
char *hello = "Hello World, Let me live.";
char *tokens[50];
strtok_r(hello, " ,", tokens);
int i = 0;
while(i < 5) {
printf("%s\n", tokens[i++]);
}
}
Ответы
Ответ 1
Попробуйте следующее:
#include <stdio.h>
#include <string.h>
int main(void) {
char hello[] = "Hello World, Let me live."; // make this a char array not a pointer to literal.
char *rest; // to point to the rest of the string after token extraction.
char *token; // to point to the actual token returned.
char *ptr = hello; // make q point to start of hello.
// loop till strtok_r returns NULL.
while(token = strtok_r(ptr, " ,", &rest)) {
printf("%s\n", token); // print the token returned.
ptr = rest; // rest contains the left over part..assign it to ptr...and start tokenizing again.
}
}
/*
Output:
Hello
World
Let
me
live.
*/
Ответ 2
- Вам нужно вызвать
strtok_r
в цикле. В первый раз, когда вы даете ему строку, подлежащую маркировке, вы даете ей NULL
в качестве первого параметра.
-
strtok_r
принимает значение char **
в качестве третьего параметра. tokens
- массив из 50 char *
значений. Когда вы передаете tokens
в strtok_r()
, то передается значение char **
, указывающее на первый элемент этого массива. Это нормально, но вы теряете 49 значений, которые не используются вообще. Вы должны иметь char *last;
и использовать &last
в качестве третьего параметра для strtok_r()
.
-
strtok_r()
изменяет свой первый аргумент, поэтому вы не можете передать ему то, что не может быть изменено. Строковые литералы в C доступны только для чтения, поэтому вам нужно что-то, что можно изменить: char hello[] = "Hello World, Let me live.";
например.
Ответ 3
Неверная ошибка:
-
hello
указывает на строковый литерал, который должен считаться неизменным. (Он может жить в постоянной памяти.) Поскольку strtok_r
мутирует строку аргумента, вы не можете использовать hello
с ней.
-
Вы вызываете strtok_r
только один раз и не инициализируете массив tokens
, чтобы указать на что-либо.
Попробуйте следующее:
#include <stdio.h>
#include <string.h>
int main(void) {
char hello[] = "Hello World, Let me live.";
char *p = hello;
char *tokens[50];
int i = 0;
while (i < 50) {
tokens[i] = strtok_r(p, " ,", &p);
if (tokens[i] == NULL) {
break;
}
i++;
}
i = 0;
while (i < 5) {
printf("%s\n", tokens[i++]);
}
return 0;
}
Ответ 4
strtok_r пытается записать нулевые символы в hello (это незаконно, потому что это строка const)
Ответ 5
Вы неправильно поняли использование strtok_r. Пожалуйста, проверьте пример и документацию
И попробуйте и посмотрите следующее:
#include <stdio.h>
#include <string.h>
int main(void)
{
char hello[] = "Hello World, let me live.";
char *tmp;
char *token = NULL;
for(token = strtok_r(hello, ", ", &tmp);
token != NULL;
token = strtok_r(NULL, ", ", &tmp))
{
printf("%s\n", token);
}
return 0;
}
Ответ 6
Я думаю, что это может быть char *tokens[50];
, потому что вы объявляете его указателем, когда он уже является указателем. Массив уже является указателем на объявление. Вы хотите сказать char tokens[50];
. Это должно сделать трюк.