2017-10-16 149 views
-2

基本上我想'拿'最后一个元素。从列表中删除它,但在此之前,它被存储在一个变量中,以便它仍然可以作为单独的变量访问,但不再是列表的一部分。如何将链表中的最后一个节点复制到变量中,然后删除C中列表中的原始数据?

编辑

这对于应该返回的最后一个节点作为一个变量,但是从列表中删除一个函数的代码:

struct node * take_last_node() 
{ 
    struct node * back = top; 
    struct node * cursor; 
    while (back->link != NULL) 
    { 
     cursor = back; 
     back = back->link; 
    } 
    cursor->link = NULL; //this is the problem 
    return back; 
} 

游标所在应该是倒数第二个节点在最后一个节点被删除之前,后面是最后一个将从列表中删除并作为变量返回的节点。如果没有注释行,则光标和背面指向正确的节点,但显然后面的节点不会被删除。所以我添加了该行,以便后面的节点从列表中删除,但仍保存在单独的变量中。假设我有一个从上到下的列表:4,3,2,1,NULL。在这个函数中添加了注释行后,最后一个节点会被删除,但是光标和后面的结构变量会向上移动,而这个函数返回2,而光标本身指向3,而我希望光标指向2最终列表看起来像这样:4,3,2,NULL和函数返回1.

这是完整的代码。这不是真实的,但它完美地创建我目前正在与真钞有问题:

#include <stdio.h> 
#include <stdlib.h> 

struct token 
{ 
    int type; 
    char * value; 
}; 

union data 
{ 
    int treenode; 
    struct token token; 
}; 

struct node 
{ 
    enum Node_Type {TREE_NODE, TOKEN} type; 
    union data data; 
    struct node * link; 
}; 

struct node * top = NULL; 
struct node * lookahead = NULL; 

struct node * peek(int placement_of_node_from_top) 
{ 
    int n = placement_of_node_from_top; 
    struct node * temp = top; 
    if (temp != NULL) 
    { 
     for (int i = 1; i <= n-1; ++i) 
     { 
      if (temp->link == NULL) 
       break; 
      temp = temp->link; 
     } 
    } 
    else 
    { 
     printf("[InternalError] Void stack.\n"); 
     exit(EXIT_FAILURE); 
    } 

    return temp; 
} 

void pop(int placement_of_node_from_top) 
{ 
    int n = placement_of_node_from_top; 
    for (int i = 0; i <= n-1; ++i) 
    { 
     top = top->link; 
     if (top == NULL) 
     { 
      printf("[InternalError] Void stack.\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 
} 

void push(union data data, enum Node_Type type) 
{ 
    struct node * temp = malloc(sizeof(struct node)); 
    temp->type = type; 
    temp->data = data; 
    temp->link = top; 
    top = temp; 
} 

struct node * retokenise() 
{ 
    struct node * back = top; 
    struct node * cursor = NULL; 
    while (back->link != NULL) 
    { 
     cursor = back; 
     back = back->link; 
    } 
    cursor->link = NULL; 
    return back; 
} 

int main() 
{ 
    union data data1, data2, data3, data4; 
    data1.token.type = 0; 
    data1.token.value = "Test"; 
    data2.token.type = 1; 
    data2.token.value = "String"; 
    data3.token.type = 2; 
    data3.token.value = "Hello"; 
    data4.token.type = 3; 
    data4.token.value = "World"; 

    push(data1, TOKEN); 
    push(data2, TOKEN); 
    push(data3, TOKEN); 
    push(data4, TOKEN); 

    printf("TAKE (%d: %s)\n", retokenise()->data.token.type, retokenise()->data.token.value); 

    while (peek(1) != NULL) 
    { 
     if (peek(1)->link == NULL) 
     { 
      printf("(%d: %s)\n", peek(1)->data.token.type, peek(1)->data.token.value); 
      break; 
     } 
     printf("(%d: %s)\n", peek(1)->data.token.type, peek(1)->data.token.value); 
     pop(1); 
    } 

    return 0; 
} 
+5

听起来对我来说是个好主意。你的代码在哪里? –

+1

@John Smith“从列表中删除它,但在此之前,它被存储在一个变量中” - 这是解决方案! –

+1

1.从列表中取消链接节点,更新**所有可能指向它的指针。 2.将现在孤立节点的值复制/移动到某个返回/输出目标。 3.删除节点。 4.归还(2)中收获的水果。而已。 – WhozCraig

回答

0

见下面的错误: -

printf("TAKE (%d: %s)\n", retokenise()->data.token.type, retokenise()->data.token.value); 

在上面printf你在呼唤retokenise()两次。在第一次调用中它将返回最后一个节点,并且您正在打印data.token.type的值,并在第二次调用中返回当前的最后一个节点,并且您正在打印data.token.value。这两个值来自两个不同的节点。在retokenise()这两个调用中都返回两个不同的节点,而不是同一个节点。请记住,每次调用都会删除节点并返回其地址指针。一个很大的错误是,你甚至没有释放内存,这会导致内存泄漏。像

更正它下面: -

struct node *p = retokenise(); 
printf("TAKE (%d: %s)\n", p->data.token.type, p->data.token.value); 
free(p); 

纠正你剩下的代码像上面所有返回不同的节点指针在每次调用,例如pop()的功能,但不叫free()功能你是不是在这里删除节点。小心翼翼地做。如果您需要更多帮助,请告诉我。

+0

我的代码几乎完全像你在我已更新的问题中编辑部分写的你的代码。问题也写在那里。 –

+0

@JohnSmith,你的代码对我来说很好。它返回列表的最后一个节点,当前最后一个节点由指针'cursor'指向。这里有什么错'cursor-> link = NULL;'?声明完全正确。你目前的问题是什么? –

+0

问题写在编辑部分。我有一个包含从上到下的列表:4,3,2,1,NULL。此函数在删除1时返回2,因此最终列表变为4,3,2,NULL,但这不完全是我想要的。它确实成功删除了1,但我还想要的是,在从列表中实际删除之前,将1保存到变量中。所以我想要的功能是让列表如下所示:4,3,2,NULL并返回1.不是2. –