Страницы

Поиск по вопросам

понедельник, 10 февраля 2020 г.

Очистка памяти динамического массива строк

#c #динамические_массивы


Доброго времени суток. Есть такая задача. Вводится строка, программа должна разбить
ее на лексемы, сохранить их в массив data, выполнить какие-то операции и потом успешно
завершится. С алгоритмом проблем нет, но вот очистка памяти не работает. Если что,
точно известно: количество слов точно не может быть более 25, длина слова - не более
20 символов. 

int main()
{
    char* string = (char*)malloc(sizeof(char) * 500);
    fgets(string, 500, stdin);

    char** data = (char**)malloc(sizeof(char*) * 25);
    for (int i = 0; i < 25; i++)
    {
        data[i] = (char*)malloc(sizeof(char) * 20);
    }

    int length = 0;
    data[length] = strtok(string, " ");
    length++;

    while (data[length - 1] != NULL)
    {
        data[length] = strtok(NULL, " ");
        length++;
    }

    //Do Something

    for (int i = 0; i < length; i++)
    {
        free(data[i]);
    }
    free(data);
    free(string);
    return 0;
}

    


Ответы

Ответ 1



Как только вы делаете вот этот финт: data[length] = т.е. присваиваете указателю новое значение, старое, указывающее на выделенную память, теряется. Получается утечка памяти. А затем вы пытаетесь удалять то, что не выделяли. Или просто используйте массив указателей, или, если выделяете память для хранения слов - копируйте слова в выделенную память. Update Вариант 1: int main() { ... char** data = (char**)malloc(sizeof(char*) * 25); for (int i = 0; i < 25; i++) data[i] = NULL; int length = 0; for(char * с = strtok(string, " ");c;c = strtok(NULL, " ")) { data[length++] = c; } //Do Something free(data); free(string); } Вариант 2: int main() { ... char** data = (char**)malloc(sizeof(char*) * 25); for (int i = 0; i < 25; i++) data[i] = (char*)malloc(sizeof(char) * 20); int length = 0; for(char * с = strtok(string, " ");c;c = strtok(NULL, " ")) { strcpy(data[length++],c); } //Do Something for (int i = 0; i < 25; i++) { free(data[i]); } free(data); free(string); } Я бы все же добавил проверки на количество слов и длину... Мало ли кто что обещает...

Ответ 2



Для копирования выдаваемого strtok() слова в динамическую память проще всего использовать функцию strdup #ifndef _GNU_SOURCE #define _GNU_SOURCE // for getline() with gcc -std=c11, c99 etc... #endif #include #include #include char ** get_25words (char *s, size_t *nw) { char **w = (__typeof__(w))malloc(sizeof(char *) * 25); // type cast for c++ for (*nw = 0; *nw < 25; (*nw)++, s = 0) { char *t = strtok(s, " "); if (t) w[*nw] = strdup(t); else break; } return w; } int main (int ac, char *av[]) { char *s = 0; size_t sz; while (getline(&s, &sz, stdin) > 0) { size_t nw; char **w = get_25words(s, &nw); printf("found %zu words\n", nw); for (size_t i = 0; i < nw; i++) { printf("%s\n", w[i]); free(w[i]); } free(w); } free(s); } А читать строки неопределенной длины очень удобно функцией getline

Комментариев нет:

Отправить комментарий