Перераспределение не работает в цикле while


Мне нужна помощь с моим заданием на C. Задача состоит в том, чтобы написать программу, которая принимает строковый ввод неизвестной длины. Также мне нужно разделять слова, поэтому я использую char**. Программа перестает принимать ввод, когда появляется специальное слово. Вы можете увидеть мой код ниже:

char **words=NULL;
 maxWords=1;
numberOfWords=0;
words=calloc(maxWords,sizeof(char **));
input=malloc(max*sizeof(char  *));

words[numberOfWords]=calloc(max,sizeof(char*));


while(stopValue){
    while((c=getchar())!='n' && c!=' ' && c!=EOF){
        input[i++]=c;

        if(i==currentSize){
            currentSize=i+max;
            input=realloc(input,currentSize);
            words[numberOfWords]=realloc(words[numberOfWords],currentSize);
        }
    }
    input[i]='';
    if(strcmp(input,terminator)==0){
        break;
    }
    strcpy( words[numberOfWords],input);

    numberOfWords++;
    maxWords++;

    words=realloc(words,maxWords);
    words[numberOfWords]=calloc(max,sizeof(char*));
    currentSize=max;
    i=0;
    input=realloc(input,max);
 }

Это хорошо работает, когда у меня есть только 2-3 слова ввода. Но он терпит неудачу, когда их становится больше. Я думаю, что проблема заключается в words=realloc(words,maxWords); этой строке, но я не знаю, что именно.

Какая-нибудь помощь, пожалуйста?

1 2

1 ответ:

Вторым аргументом для calloc() должен быть размер того, на что указывает указатель, то есть указываемый тип, а не размер самого типа указателя.

Например, предположим, что вы хотите выделить место для 10 int, присвоив результат int *p, любой из следующих вариантов будет правильным синтаксисом и покажет определенное поведение:

int *a = malloc(10 * sizeof(int));
int *b = calloc(10, sizeof(int));
int *c = realloc(NULL, 10*sizeof(int))
int *d = malloc(10 * sizeof *d);
int *e = calloc(10, sizeof *e);
int *f = realloc(NULL, 10 * sizeof *f);

Указатель на указатель действует не иначе. Если вы хотите выделить последовательность указателей на символ, то синтаксис идентичен применяется:

char **a = malloc(10 * sizeof(char*));
char **b = calloc(10, sizeof(char*));
char **c = realloc(NULL, 10*sizeof(char*))
char **d = malloc(10 * sizeof *d);
char **e = calloc(10, sizeof *e);
char **f = realloc(NULL, 10 * sizeof *f);
Обратите внимание, что не только синтаксис, но и фактический код последних трех в обоих приведенных выше списках идентичен , за исключением самого типа указателя (первый-указатель на int, второй-указатель на char). Этот синтаксис использует преимущество того, как оператор sizeof (это не функция или макрос; это оператор) может использоваться против переменной , а не типа .

Это говорит, что words в вашем коде является указатель на указатель на символ. Я должен быть выделен с использованием аналогичного синтаксиса для правильного определения размера. Любое из следующих действий будет работать правильно:

char **words = calloc(maxwords, sizeof(char*)); // right, uses specific type
char **words = calloc(maxwords, sizeof *words); // right, gets size from var type

Оба делают одно и то же: выделяют буфер, правильно выровненный и размерный, чтобы вместить maxwords Количество char*, именно то, что вы хотели бы для хранения указателей на строки.

Эта проблема повторяется снова, когда вы делаете это:

words[numberOfWords] = calloc(max, sizeof(char*)); // wrong

Опять же, words является char**, поэтому words[anything] является char* и, как таковой, должен быть назначен распределение, основанное на размере указываемого типа: char. Это будет сделано любым из следующих способов:

words[numberOfWords] = calloc(max, sizeof(char));   // right, or...
words[numberOfWords] = calloc(max, sizeof **words); // right

Хорошо все это сказано, ваше подозрение, что это неправильно:

words = realloc(words, maxWords);
Это хорошо обосновано. Функция realloc принимает в качестве второго параметра число байтов . Вы передаете count of pointers, но не включаете размер каждого указателя в число запрошенных байтов. Используя синтаксис, описанный ранее, это можно сделать как:
words = realloc(words, maxWords * sizeof *words);

Или

words = realloc(words, maxWords * sizeof(char*));

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

Желаю удачи.