2011-02-07 3 views
0

может ли кто-нибудь сказать мне, почему функция замены не работает? говорят, что main называется replace (1,2, list). Он должен искать узлы, и если значение узла равно 1, оно должно сделать новый узел со значением 2, чтобы заменить его, а затем освободить память, выделенную для первого узла. Я не могу понять = (c - заменить функцию связанного списка

typedef struct iNode 
{ 
    int myInt; 
    struct iNode* next; 
} IntNode, *IntNodePtr; 

IntNodePtr insert(int i, IntNodePtr p) 
{ 
    IntNodePtr newp = malloc(sizeof(struct iNode)); 
    newp->myInt = i; 
    newp->next = p; 
    return newp; 
} 

IntNodePtr delete(int i, IntNodePtr p) 
{ 
    /* End of list check */ 
    if(p == NULL) 
     return NULL; 

    /* Check if current node is the one to delete */ 
    if(p->myInt == i) 
    { 
     IntNodePtr temp; 
     temp = p->next; 

     free(p); 
     return temp; 
    } 

    p->next = delete(i, p->next); 
    return p; 
} 

IntNodePtr replace(int i, int j, IntNodePtr p) 
{ 
    if(p == NULL) 
     return NULL; 

    if(p->myInt == i) 
     insert(j, p->next); 

    free(p); 

    p->next = replace(i, j, p->next); 
    return p; 
} 
+0

Обратите внимание, что вам всегда нужно передать самую первую ссылку в списке в функцию 'replace'. В противном случае вы закончите разбивку списка. Это касается 2 или 3 ответов, которые у вас есть до сих пор. Я знаю, что, вероятно, предполагается, но ... – JimR

ответ

0

Есть несколько проблем с replace() функции. (Это выглядело хорошо для меня в ваш последний вопрос).

  1. Вы называете insert() когда вы найдете узел, который имеет i, но вы ничего не делаете с новым узлом (то, что insert() возвращается). в основном новый узел вы вставляете это новый p, так что вы должны установить p к нему.

  2. Вы освободите p и сразу же попытаетесь установить поле nextp на значение. Место, указывающее p, недействительно, поэтому вы не должны этого делать. Вы должны использовать временную переменную, чтобы сохранить старый p, чтобы вы могли освободить его позже. Это должно быть сделано только в том случае, если вы фактически замените его, чтобы он был частью предыдущего условия.

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

/* if the current node contains the int I'm looking for... */ 
if(p->myInt == i) 
{ /* ... the current node needs to be replaced */ 
    /* save the current node to delete later (2) */ 
    IntNodePtr oldNode = p; 

    /* insert a new node making it the new current node (1) */ 
    p = insert(j, oldNode->next); 

    /* free the old node (2) */ 
    free(oldNode); 
} 
/* and so on */ 
+0

Вы не могли редактировать код и размещать его jeff? он был полностью смущен и расстроен этим материалом и все еще не понимал этого. Мне тоже понравилась моя старая функция, но функция должна быть неизменной, а моя старая была изменчивой. – mikecavs

+0

@mike: У вас почти было это. В основном она была похожа на функцию 'delete()'. Надеюсь, для вас это намного понятнее. –

+0

большое спасибо Джеффу, наконец, посмотрим, где я сейчас ошибся. иногда мне просто нужно посмотреть на правильный код, прежде чем я смогу понять, почему мой код был неправильным. – mikecavs

0

Как Марк отметил, ваш free(p) имеет неопределенное поведение. Таким образом, следующий оператор

p->next = replace(i, j, p->next); 

становится недействительным, поскольку вы пытаетесь присвоить p->next к значению указателя, но само расположение p->next памяти не определено.

Но почему вы заменили функцию рекурсивной? Простой цикл while будет достаточным.

IntNodePtr replace(int i, int j, IntNodePtr p) { 
    if(p == NULL) 
     return NULL; 
    IntNodePtr prevPtr = NULL; 
    while(p){ 
     if(p->myInt == i){ 
      IntNodePtr temp = insert(j, p->next); 
      if(prevPtr) 
       prevPtr->next = temp; 
      free(p); 
      break; 
     } 
     prevPtr = p; 
     p = p->next; 
    } 
} 

И вы неправильно используете вашу функцию вставки, а также, так как вы не подключаете предыдущий узел к вновь созданному узлу.

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