Segfault при доступе к элементам динамического 2d массива - PullRequest
0 голосов
/ 13 марта 2019

Моя цель - создать функцию, которая преобразует строку в массив «слов», полученных в результате разбиения исходной строки разделителем.Все слова должны заканчиваться нулем.Например: strtoarr ("** hello *** world *", "*") должен привести к {"hello", "world"}.Вот моя функция.

char    **strtoarr(char const *s, char c)
{
    char    **arr;
    size_t  i;
    size_t  j;
    size_t  k;

    arr = malloc(sizeof(**arr) * (strlen(s) + 2));
    if (arr == 0)
        return (NULL);
    i = 0;
    k = 0;
    while (s[i] != '\0')
    {
        j = 0;
        while (s[i] != c)
        {
            arr[k][j] = s[i];
            if (s[i + 1] == c || s[i + 1] == '\0')
            {
                j++;
                arr[k][j] = '\0';
                k++;
            }
            i++;
            j++;
        }
        j = 0;
        while (s[i] == c)
            i++;
    }
    arr[k] = 0;
    return (arr);
}

Работает только с пустыми строками и segfaults со всем остальным.Я считаю, что проблема здесь.

arr[k][j] = s[i];

Но я не понимаю, в чем проблема.Заранее спасибо

Ответы [ 2 ]

2 голосов
/ 13 марта 2019

Существует ряд проблем с вашим кодом, но наиболее важным является динамическое распределение.Ваш код не выделяет память для сохранения массива строк (он же массив массива char).

Эта строка:

arr = malloc(sizeof(**arr) * (strlen(s) + 2));

выделяет память для сохранения числа символов (т. Е. strlen(s) + 2 символов) но это не то, что вы хотите.Особенно, если arr является указателем на указатель на символ.

Простой подход, который вы можете использовать, - это выделить массив указателей на символы, а затем для каждого из этих указателей выделить массив символов.

Это будет:

char** arr = malloc(sizeof(*arr) * NUMBER_OF_WORDS_IN_INPUT);

arr[0] = malloc(NUMBER_OF_CHARACTERS_IN_WORD0 + 1);
arr[1] = malloc(NUMBER_OF_CHARACTERS_IN_WORD1 + 1);
...
arr[NUMBER_OF_WORDS_IN_INPUT - 1] = malloc(NUMBER_OF_CHARACTERS_IN_LAST_WORD + 1);

Затем вы можете сохранить символы в arr, используя синтаксис

arr[i][j] = SOME_CHARACTER;

без сегфоулатов .(Разумно требуется, чтобы i и j находились в пределах выделения).

0 голосов
/ 13 марта 2019

Внутренний цикл while должен завершиться, если s[i] равно NULL: while (s[i] != c && s[i] != '\0')

Вы проверяете s[i + 1] в своем операторе if, но продолжаете цикл.

Также вы выделяете больше байтов, чем необходимо, вы можете иметь буфер с тем же размером входной строки, и когда найден разделитель или NULL, вы выделяете новую строку в вашем массиве нужного размера и копируете буфер в него.

...