Подтвердить что ты не робот

Ошибка сегментации при использовании 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++]);
  }
}
4b9b3361

Ответ 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];. Это должно сделать трюк.