Ошибка сегментации при использовании 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("%sn", tokens[i++]);
  }
}

6 ответов


попробуйте это:

#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.
*/

  • нужно позвонить 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."; например.

куча вещей неправильно:

  1. hello указывает на строковый литерал, который должен рассматриваться как нечто неизменное. (Он мог жить в памяти только для чтения.) С strtok_r мутирует строку аргумента, вы не можете использовать hello с ним.

  2. вы называете 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;
}

strtok_r пытается записать нулевые символы в hello (что незаконно, потому что это строка const)


вы неправильно поняли использование 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;
}

Я думаю, что это может быть char *tokens[50]; потому что вы объявляете его указателем, когда он уже является указателем. Массив уже является указателем на объявление. Вы хотите сказать ... --1-->. Это должно сработать.