Добавление в структуру связанного списка с помощью цикла while не сохраняет данные (IN C) - PullRequest
0 голосов
/ 22 ноября 2018

Это один из моих первых вопросов, поэтому я надеюсь, что сформулирую его хорошо.Я проверил некоторые другие подобные вопросы на StackOverflow, но не получил от них реальных ответов.У меня есть следующая структура:

struct process {
int priority;
char* path;
char* parameters;
struct process *next;
};

Я читаю каждую строку из файла и добавляю строковые токены, которые я получаю в своем списке связанных структур, используя цикл while.Вот метод добавления:

struct process * add(int prio,char* pat, char* par,  struct process *head) {
  struct process *new_node;
  new_node = ( struct process *) malloc(sizeof( struct process));
  new_node->priority = prio;
  new_node->path = pat;
  new_node->parameters = par;
  new_node->next= head;
  head = new_node;
  return head;
}

Таким образом, основной алгоритм получает строки из файла, используя fgets в цикле while:

while (fgets(line, sizeof(line), file))

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

Это мой цикл while и главный алгоритм:

        FILE *file = fopen(filename , "r");
    char line[124];
    // can be put outside and passed as argument.
    struct process *head = ( struct process *)malloc(sizeof(struct process));
    new_node->priority = prio;
    new_node->path = pat;
    new_node->parameters = par;
    new_node->next= head;
    char* priority,*path,*parameters;

    while (fgets(line, sizeof(line), file)) {
         priority=strtok(line," ");             
         // The fix here is the following :
         char *path_token = strtok(NULL, " ");
         path = malloc(strlen(path_token) + 1); 
         strcpy(path, path_token);
         char *par_token = strtok(NULL, "\n");
         parameters = malloc(strlen(par_token) + 1);
         strcpy(parameters, par_token);
         // End of edit Thanks to the answers bellow
         char* junk;
         int p = strtol(priority,&junk,10);
         printf("prio : %d  ",p);
         head = add(p, path, parameters,head);
         printf("\n");
         pront(head);
         printf("\n");
    }
    \\ free the mallocs

Здесь мы заметили, что я использую метод pront () для печати моегосвязанный список на каждом шагу.Я также делаю это после цикла while.Вот код для pront ():

void pront(struct process *head) {
struct process *current_node = head;
while ( current_node != NULL) {
    printf("%d , %s , %s ", current_node->priority, current_node->path, current_node->parameters);
    printf("\n");
    current_node = current_node->next;
}

}

метод выдает бессмыслицу:

prio : 2  
2 , ./printchars , a 12 b 

prio : 15  
15 , ./printchars , c 23 d 
2 ,  ,  

prio : 7  
7 , ./printchars , e 34 f 
15 , /printchars ,  34 f 
2 , ./printchars , e 34 f 

предполагается вывести:

7 , ./printchars , e 34 f 
15 , ./printchars , c 23 d 
2 , ./printchars , a 12 b 

Я уверен, что проблема связана с циклом while, поскольку при использовании метода добавления вне цикла и последующей печати я получаю действительные результаты.Но как только он попадет в цикл, связанный список Head не будет правильно хранить значения!Спасибо за помощь

РЕДАКТИРОВАТЬ: проблема исправлена, и проблема заключалась в том, что я ужасно неправильно использовал strtok и указатели на char без malloc.Урок выучен !

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Ваш связанный список не хранит значения вообще.

Проблема не в цикле, а strtok - вы используете его неправильно: он не выделяет памятьчтобы сохранить токены, которые он анализирует, но вместо этого использует один внутренний статический буфер.

Итак, чтобы сохранить значения, вы должны выделить память для ваших строк (path и parameters) и использовать strcpyскопировать строки в выделенную память.Не забудьте free поля каждого элемента перед освобождением элементов списка!

Пример:

char *path_token = strtok(NULL, " ");
path = malloc(strlen(path_token) + 1); /* remember to allocate space for \0 terminator! */
strcpy(path, path_token));
0 голосов
/ 22 ноября 2018

Проблема с кодом ниже.

new_node->priority = prio;
new_node->path = pat;
new_node->parameters = par;

Ваша структура имеет символьный указатель для path и parameters

То, что вы делаете здесь, это просто назначаете указатель вСтруктура указателя в функции, передано.Позже, когда pat или par изменяет значение или имеет какое-либо значение мусора, элемент структуры также будет иметь значение мусора.

Что вам нужно сделать, это выделить память для каждого элемента и strcpydata

Кроме того, как указывает @Ruks -

struct process *head = ( struct process *)malloc(sizeof(struct process)); 
head = NULL;

неверно.Вы теряете указатель, возвращаемый malloc.Если вы хотите убедиться, что связанный список изначально пуст, вам следует инициализировать все элементы head.

head-> priority = 0; 
head-> path = NULL;
head-> parameters = NULL;
head-> next = NULL;
...