Проблема в C со строковым массивом, где элементы повторяются - PullRequest
0 голосов
/ 03 июня 2019

Я пытаюсь взять неизвестное количество строк консольного ввода, преобразовать каждую строку в строку, используя malloc, а затем добавить каждую строку в массив строк, динамически перераспределяя память каждый раз.Моя цель - создать массив, в котором каждый элемент представляет собой отдельную строку, введенную консолью (цикл while должен заканчиваться EOF).

Мой код ниже.

char * inputString = (char *)malloc(100);
char * aWord = (char *)malloc(1);
char ** listWords = (char **)malloc(1);
int wordCount = 0;

while (fgets(inputString, 100, stdin) != NULL)
{       
    wordCount++;
    *(inputString + (strlen(inputString) - 1)) = '\0';
    aWord = (char *)realloc(aWord, strlen(inputString) + 1);
    aWord = inputString;

    listWords = realloc(listWords, sizeof(char) * wordCount);
    *(listWords + (wordCount - 1)) = aWord;
}

for (int i = 0; i < wordCount; i++)
    printf("%s\n", listWords[i]);

Если ядолжны были вводить в консоли

abc\n
b\n
cad\n
^Z\n

Теоретически, я хотел бы, чтобы мой код выводил

abc\n
b\n
cad\n

Каждая строка ввода с консоли.Вместо этого он печатает

cad\n
cad\n
cad\n

Последняя введенная строка.Помощь очень ценится

Ответы [ 3 ]

1 голос
/ 03 июня 2019

Сначала это так:

aWord = (char *)realloc(aWord, strlen(inputString) + 1);
aWord = inputString;

Здесь вы выделяете место для aWord, но затем перезаписываете возвращенный адрес на адрес, содержащийся в inputString.Таким образом, каждая строка, которую вы читаете, в итоге перезаписывает предыдущую строку.Вы также должны использовать malloc вместо realloc, потому что вы хотите получить новый буфер вместо того, чтобы повторно использовать существующий.

Измените вызов realloc на malloc and instead of assigning one pointer to the other, use strcpy`, чтобы скопировать его.

aWord = malloc(strlen(inputString) + 1);
strcpy(aWord, inputString);

Затем в этой строке:

listWords = realloc(listWords, sizeof(char) * wordCount);

Вы выделяете достаточно памяти только для массива символов вместо массива указателей на символы.Это приводит к записи после конца выделенной памяти, вызывая неопределенное поведение .

Правильное распределение:

listWords = realloc(listWords, sizeof(char *) * wordCount);
1 голос
/ 03 июня 2019

Есть три вопроса.

Во-первых, realloc не выделяет дополнительно aWord, но увеличивает / уменьшает буфер текущего aWord, таким образом, вероятно, возвращая новый адрес при освобождении старого.Таким образом, aWord = (char *)realloc(aWord, strlen(inputString) + 1) адаптирует память к новому размеру, но вы потеряете содержимое, записанное в aWord ранее.Обратите внимание, что *(listWords + (wordCount - 1)) = aWord позволит вашему окончательному списку указывать на aWord.Используйте malloc вместо realloc.

Во-вторых, с aWord = inputString; вы позволяете aWord указывать на inputString вместо копирования его содержимого.Вместо этого используйте strcpy:

char *aWord = malloc(aWord, strlen(inputString) + 1);
strcpy (aWord,inputString);

В-третьих, вам необходимо зарезервировать место для указателей символов, а не только символов.

listWords = realloc(listWords, sizeof(char*) * wordCount);
1 голос
/ 03 июня 2019

Вы не можете скопировать строку, используя присвоение, вы должны использовать strcpy():

strcpy(aWord, inputString);

Также

*(listWords + (wordCount - 1)) = aWord;

можно упростить до:

listWords[wordCount-1] = aWord;
...