Сбой связанного списка, c

#c #linked-list

#c #связанный список

Вопрос:

У меня проблема с моим связанным списком. Я почти уверен, что мои указатели отключены, или я неправильно передал указатель, поскольку я новичок в c. Структуры также являются новыми для меня, а c — это язык, к которому я привык, и различий больше, чем я знал. Я мог бы сделать эту программу на c в кратчайшие сроки, но в любом случае вот мой код.

 void add_process(struct process new_process, struct process *head, struct process *current){

    new_process.next = NULL;

    if(head == NULL){
        head = amp;new_process;
        current = head;
        head->next = NULL;
    }
    else if(new_process.timeNeeded < head->timeNeeded){
        temp = head->next;
        head = amp;new_process;
        new_process.next = temp;
    }
    else{
        current = head;
        while(new_process.timeNeeded > current->timeNeeded){
            temp = current;
            current = current->next;
        }
        temp->next = amp;new_process;
        new_process.next = current;
    }
}
 

Я считываю значения из файла в процесс, единственное, что я сейчас использую, это timeNeeded, который является int . И я пытаюсь упорядочить список по кратчайшему времени, необходимому в первую очередь.

 int main(){
    FILE *readfile;
    readfile = fopen("data.txt","r");


    head = NULL;
    current = NULL;

    while(fscanf(readfile, "%s %i %i %i", 
        amp;new_process.processName, amp;new_process.arrivalTime, 
            amp;new_process.timeNeeded, amp;new_process.priority) != EOF)  {

                add_process(new_process, head, current);
      }
    current = head;

    while(current->next != NULL){
        printf("%s %i %i %in", new_process.processName, new_process.arrivalTime, new_process.timeNeeded, new_process.priority);
        current = current->next;
    }

    return 0;
}
 

Программа вылетает при печати, что не является проблемой. Первая проблема заключается в том, что моя программа каждый раз вводит цикл if (head == NULL) и вставляет его туда. Так что head, вероятно, никогда не меняется, но я не уверен, как это исправить, я почти уверен, что это двойной указатель, но не положительный. И я также уверен, что есть и другие проблемы, поэтому, если вы могли бы указать мне правильное направление, и если я делаю что-то совершенно неправильное, дайте мне знать.

РЕДАКТИРОВАТЬ: Итак, после добавления указателя на head я получаю сообщение об ошибке в head-> next = NULL, в котором говорится: «выражение должно иметь тип указателя на класс». Пытался добавить * перед заголовком, но, похоже, это не помогло. Кто-нибудь знает, как это исправить?

Ответ №1:

Ваша функция add_process здесь:

 void add_process(struct process new_process, 
                 struct process *head, 
                 struct process *current)
 

Принимает любой указатель, который вы передаете в него по значению. Это означает, что после вашего вызова в цикле while здесь:

 while(fscanf(readfile, "%s %i %i %i", 
    amp;new_process.processName, amp;new_process.arrivalTime, 
    amp;new_process.timeNeeded, amp;new_process.priority) != EOF)  
{

        add_process(new_process, head, current);
}
 

head по-прежнему будет нулевым, потому что он никогда не менялся. Чтобы он фактически изменил указатель заголовка, а не какой-либо другой указатель, измените ваш add_process, чтобы использовать указатель двойного уровня:

 void add_process(struct process new_process, 
                 struct process **head, 
                 struct process *current)
 

Еще одна проблема с вашим приведенным выше кодом заключается в том, что new_process аргумент также принимается по значению. Итак, это временная копия любого процесса, который вы передали. После add_process возврата new_process выходит из области видимости. Теперь это означает, что в вашем связанном списке есть висячий указатель, указывающий на недопустимую память.

Чтобы исправить это, вы должны использовать malloc для динамического выделения памяти, а затем создать копию new_process . Затем ваш связанный список указывает на malloc процесс редактирования. Объекты, созданные в куче с помощью malloc, будут сохраняться до тех пор, пока они не будут освобождены.

Вот краткий пример, который даст вам представление:

 typedef struct process Process;
void add_process(Process new_process, Process **head, Process *current)
{
    Process *new_proc_copy = (Process *)malloc( sizeof(Process) );
    // now copy over the stuff from 
    // new_process over to this one
    memcpy((char *)new_proc_copy, (char *)new_proc, sizeof(Process));

    if(*head == NULL)
    {
        *head = new_process_copy;
        current = *head;
        (*head)->next = NULL;
    }
    else if(new_process.timeNeeded < head->timeNeeded)
    {
        // handle this case
    }
    else
    {
        // handle rest of your stuff
    }
}
 

Не забудьте освободить выделенную память, когда закончите. Это лучше всего сделать в вашей функции очистки процесса — эквиваленте деструктора в C , только вам нужно вызвать его вручную.

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

1. Большое спасибо, все это имеет смысл, надеюсь, я смогу снова запустить это.

2. @user1019430 Не забудьте проголосовать за ответы, которые вы сочли полезными.

3. Да, я пытался, но сначала мне нужно 15 повторений, я дам вам право голоса, когда получу его

Ответ №2:

Чтобы иметь возможность изменять значение, содержащееся в head , вы должны передать указатель head на свою add_process функцию.

Ответ №3:

Похоже, вы не выделяете место для new_process . Не могу использовать одну и ту же память каждый раз — нужно выделить немного.

Также помните, что C не изменяет параметры автоматически на по ссылке. Поэтому, если вы хотите что-то изменить, вам нужно передать указатель на эту вещь. Это включает в себя другие указатели — поэтому вам может понадобиться указатель на указатель.

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

1. Да, я хотел спросить об этом, как мне выделить новую память на c. Я считаю, что мне нужно использовать malloc, это правильно?

2. Да, malloc — лучший способ