Это стало довольно длинным ответом.Не принимайте это на свой счет, но вы сделали немало ошибок новичка.В университете я встречался со многими людьми, которым помогал изучать язык Си и программирование в целом, поэтому я привык замечать подобные вещи.
Важные проблемы, которые я мог найти
Вы назначаете указатель на переменную стека на words
Это очень плохо, потому что это значение будет перезаписано, как только выполнение выйдет из функции, которая создаетЭто. Решение: скопируйте содержимое этой переменной в переменную кучи.
Ваша функция append
неисправна
Она добавляетдобавлен элемент на второе место вместо последнего.Обратите внимание, что вам не нужен возврат в конце.Также нет смысла требовать двойной указатель в качестве входных данных для метода append
.Кроме того, после присвоения head
tmp
бесполезно проверять tmp и NULL
, поскольку оно не будет NULL
, если head
не NULL
.Также я рекомендую проверить новый узел по NULL
.Если это NULL
, это избавит вас от итерации по всей коллекции.
Функция create_list
неоптимальна
Fist,Различие между первым и другим делом бесполезно.Введение другого указателя (называемого current
в моем коде) избавит от необходимости проверять, является ли он первым или нет.Далее, вы всегда вызываете функцию append
на head
, поэтому вам всегда нужно перебирать всю коллекцию.Это также можно оптимизировать, введя переменную current
.(Которому при запуске должно быть присвоено значение head
.)
Функция print_list
ошибочна
Не печатаетсячто угодно, если есть только один узел.Это также избыточно проверяет указатели на ноль.(В начале цикла это тоже проверяется.) Оператор return в конце этой функции void
также не нужен.
Вы должны освободить память, когда выне используйте его
@Baltasarq написал в своем ответе хорошую функцию clear
, вы должны использовать ее.:)
Несерьезные ошибки, но вы должны знать о них
Не следует использовать void*
вместо char*
ЕслиВы знаете, что data
член структуры NODE
будет хранить символы, почему вы используете void*
?Это плохая практика!(Если, конечно, у вас нет веских причин.)
Использование слова new
в качестве имени переменной делает ваш код несовместимым с C ++.Таким образом, я рекомендую против этого.
Примите лучший стиль кодирования, пожалуйста - это сделает ваш код намного проще для чтения
Несоответствие: если в print_list
вы не выделяете новую переменную для прохода по коллекции (как вы делаете с переменной tmp
в append
), то ошибочно называть параметр head
.(Я переименовал его в node
в моем коде.)
Вот фиксированный код
(Обратите внимание, что могут быть небольшие синтаксические ошибки, потому что янабрал код в браузере, не проверяя его.)
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
void *data;
struct node *next;
} NODE;
NODE *new_node(void *data)
{
NODE *newNode = (NODE*)malloc(sizeof(NODE));
if (newNode)
{
newNode->data = data;
newNode->next = NULL;
return newNode;
}
return NULL;
}
void append(NODE *head, NODE *node)
{
if (head && node)
{
NODE *tmp = head;
while (tmp->next)
tmp = tmp->next;
tmp->next = node; /* add as last node */
}
}
void print_list(NODE *node, void (print_fn) (void*))
{
while (node)
{
if (print_fn)
print_fn(node->data);
else
printf("Word: %s\n", (char *)node->data);
node = node->next;
}
}
NODE *create_list()
{
FILE *dict_file = fopen("trial.txt", "r");
if (dict_file)
{
NODE *head = NULL;
NODE *current = head;
char word[20];
memset(word, '\0', 20);
while (fgets(word, sizeof(word), dict_file))
{
// Creating a variable on the heap
char *data = calloc(sizeof(word) + 1, sizeof(char));
// Copying the contents of words to it
strcpy(data, word);
append(current, new_node((void*)data));
if (current->next)
current = current->next
}
fclose(dict_file);
return head;
}
else
{
printf("ERROR: File not found");
}
return NULL;
}
int main(int argc, char *argv[])
{
NODE *head = create_list();
if (!head)
{
printf("ERROR: Either malloc() failed or data not found\n");
}
else
{
print_list(head, NULL);
}
return 0;
}