Ошибка сегментации при использовании strtok - PullRequest
1 голос
/ 16 января 2020

Я получаю ошибку сегментации при использовании char *s в основном. Если я использую char s[100] или что-то подобное, все в порядке. Это почему? SIGSEGV появляется, когда я вызываю find_short(char *s) функцию онлайн с инструкцией char *token = strtok(s, delim);. Это мой код:

#include <sys/types.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>

int find_short(char *s)
{
    int min = INT_MAX;
    const char delim[2] = " ";
    char *token = strtok(s, delim);
    while(token != NULL) {
        int len = (int)strlen(token);
        if (min > len)
            min = len;
        token = strtok(NULL, delim);
    }
    return min;
}
int main()
{
    char *s = "lel qwew dasdqew";
    printf("%d",find_short(s));
    return 0;
}

Ответы [ 2 ]

4 голосов
/ 16 января 2020

Строка:

char *s = "lel qwew dasdqew";

создает указатель на строку константа в памяти.
Поскольку эта строка является константой, вы не можете изменить ее содержимое.
Функция strtok попытается изменить содержимое, вставив \0 в местоположения разделителя токенов, и потерпит неудачу, поскольку строку нельзя изменить.


Изменение строки на:
char s[] = "lel qwew dasdqew";

Теперь делает s массивом локальных данных, которые вы можете изменять. strtok теперь будет работать, потому что он может изменить массив.

2 голосов
/ 16 января 2020

Основная ваша ошибка в том, что вы выбрали неправильную функцию для выполнения задачи. 1018 * хотя они не имеют постоянных типов массивов символов, они неизменны. Любая попытка изменить строковый литерал приводит к неопределенному поведению. И функция strtok изменяет переданную ей строку, вставляя завершающий ноль между подстроками.

Вместо функции strtok следует использовать строковые функции strspn и strcspn. Они не меняют переданный аргумент. Таким образом, используя эти функции, вы можете обрабатывать и строковые литералы.

Вот демонстрационная программа.

#include <stdio.h>
#include <string.h>

size_t find_short( const char *s )
{
    const char *delim= " \t";

    size_t shortest = 0;

    while ( *s )
    {
        s += strspn( s, delim );

        const char *p = s;

        s += strcspn( s, delim );

        size_t n = s - p;

        if ( shortest  == 0 || ( n && n  < shortest ) ) shortest = n;
    }

    return shortest;
}

int main(void) 
{
    const char *s = "lel qwew dasdqew";

    printf( "%zu", find_short( s ) );

    return 0;
}

Ее вывод

3
...