2016-01-26 2 views
-1
Exception thrown at 0x00A12849 in DLL.exe: 0xC0000005: Access violation reading ocation 0xDDDDDDDD. 

Ошибка возникает при синтаксическом анализе, и я не знаю, почему. Я написал тот же самый код, что и в книге, они только написали функцию del, а не функцию синтаксического анализа. PLS скажите, почему эта ошибка возникает в этом коде и как этого избежать в будущем. также помогают написать правильную функцию синтаксического анализа. спасибо всем заранееОшибка при анализе через связанный список

#include<iostream> 

using namespace std; 

struct list 
{ 
    int data; 
    list *next; 
    list *prev; 


}; 

list* createNode() 
{ 
    list *node = new list; 
    node->next = NULL; 
    node->prev = NULL; 
    return node; 
} 


void insert(list**head,int data,int position) 
{ 
    int k = 1; 
    list *current, *temp, *node = createNode(); 

    current = NULL; 
    temp = *head; 

    node->data = data; 

    if (position==1) 
    { 
     node->next = *head; 
     *head = node; 
     if (*head) 
     { 
      (*head)->prev = node; 
     } 

    } 
    else 
    { 
     while (temp->next!= NULL&&k < (position-1)) 
     { 
      temp = temp->next; 
      k++; 
     } 
     node->next = temp->next; 
     node->prev = temp->prev; 
     if (temp->next) 
      temp->next->prev = node; 
     temp->next= node; 
    } 
} 
void del(list**head, int position) 
{ 
    int k = 1; 
    list *current, *temp; 
    current = NULL; 
    temp = *head; 
    if (position == 1) 
    { 
     *head = (*head)->next; 

     if (*head != NULL) 
      (*head)->prev = NULL; 
     delete temp; 
     return; 
    } 


    while (k < position&&temp->next != NULL) 
    { 
     temp = temp->next; 
     k++; 
    } 
    current = temp->prev; 
    current->next = temp->next; 
    if (temp->next) 
     temp->next->prev = current; 
    delete temp; 
    return; 

} 
void parse(list * temp) 
{ 



    while (temp != NULL) 
    { 



     cout << "->" << temp->data; 
     temp = temp->next; 
    } 
} 

void main() 
{ 

    struct list *head = NULL; 

start:     

    int choice; 


    cin >> choice; 
    switch (choice) 
    { 
     case 1: int data, position; 
       cout << "\ndata:"; cin >> data; cout << "\nposition:"; 
       cin>>position; 
       insert(&head, data, position); 
       goto start; 
     case 2:parse(head); 
      goto start; 
     case 3: cout << "\nposition:"; cin >> position; 
       del(&head, position); 
       goto start; 
     default: break; 
    } 
    exit(0); 
} 
+1

Почему вы используете 'goto' вместо цикла? –

+0

@JoachimPileborg Этот код имел бы общую проблему, требующую «разбить» цикл изнутри «switch», поэтому требуется некоторая форма нечистого управления потоком. Выбор 'goto start' является более уродливым, чем каждый из нескольких других способов. Но это не так просто, как просто использовать цикл. – JSF

ответ

1

Эти шаги в неправильной последовательности и сделать Узлом свой пред:

*head = node; 
    if (*head) 
    { 
     (*head)->prev = node; 
    } 

Тогда вы также установить пред неправильно здесь:

node->prev = temp->prev; 

Следующий код не обязательно является ошибочным сам по себе, но это безосновательно опасное использование prev, которое не подходит к ошибкам, которые делают prev ошибочно, но также не удается в некоторых случаях плохого ввода (неверная позиция).

while (k < position&&temp->next != NULL) 
{ 
    temp = temp->next; 
    k++; 
} 
current = temp->prev; 

Вы сказали, что del функция была в книге. Может быть, у вас нет выбора, но вы, видимо, используете довольно плохую книгу. Эта функция (и ваша функция insert) написаны в стиле новичков, что не является хорошим способом научиться программировать. Начинающие проблемы подходят для обучения, но некоторые аспекты типичных начинающих решений следует избегать с самого начала. Одним из наиболее важных навыков программирования является поиск сходства, которое позволяет объединить связанные операции в более общие операции. Разбивание особых случаев (например, первое положение в этих функциях) является естественной ошибкой начинающего, которую вы должны убирать, а не копировать из книги.

Вы уже используете дополнительный уровень косвенности **, что позволяет объединение дел, так что вы должны в полной мере воспользоваться этим, а не уронить преимущество при первой же возможности:

void insert(list**head,int data,int position) 
{ 
    list *p = NULL; 
    while ((position--)>0 && *head) 
    { 
     p = *head; 
     head = &(p->next); 
    } 
    list *node = createNode(); 
    node->prev = p; 
    node->next = *head; 
    node->data = data; 
    *head = node; 
} 

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

+0

(* head) -> prev - это предыдущий указатель узла, на который указывает головка. -__- –

+0

@ DragonSurfer Нет, не после этого '* head = node'. –

+0

Что вы хотите '(* head) -> prev' быть? В других частях кода показана конструкция, в которой '(* head) -> prev' должно быть' NULL', но эта строка вызывает '(* head) -> prev' to' (* head) ' – JSF

Смежные вопросы