【问题标题】:Passing Pointers in Functions for Linked List在链接列表的函数中传递指针
【发布时间】:2015-03-08 09:13:33
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
//why does this work with pointers thought they made a copy?
//am i freeing memory correctly and well?
//Something wrong with freeing
struct Node{

    struct Node* next;
    int data;

};
void newNode(struct Node* trans, int val)
{
    if(trans!=NULL)
    {
        while(trans->next!=NULL)
        {
            trans=trans->next;
        }
        //next is null create heap memory
        trans->next=malloc(sizeof(struct Node));
        //checking to see if memory is created
        if(trans->next==NULL)
        {
            printf("This has failed");
        }
        //put in data
        trans->next->data=val;      
        //next is null
        trans->next->next=NULL;
    }

}
void printList(struct Node* head)
{
    if(head!=NULL)
    {
        struct Node* current;
        current=head;
        while(current->next!=NULL)
        {
            //print that current nodes data
            printf("list is: %d\n",current->data);
            current=current->next;
        }
    printf("last element is: %d\n",current->data);

    }
    else
    {
        printf("list is empty!");
    }

}
int removeLastNode(struct Node* trans)
{

    //return -1 if its a empty list
    int val=-1;
    if(trans!=NULL)
    {
        /*have to access trans->next->next cause you are freeing trans->next->next and getting its val
        then you want to set tran->next to NULL!
        */
        while(trans->next->next!=NULL)
        {
            trans=trans->next;
        }
        //at end of the list?
        val=trans->next->data;
        //free the heap
        free(trans->next);
        //next points to null
        trans->next=NULL;

    }
    return val;
}
//LOOK AT ME!
void freeList(struct Node* root)
{
    struct Node* temp;
    struct Node* current;
    current=root;
    while(current->next!=NULL)
    {
        temp=current;
        //going to the next one
        current=current->next;
        //freeing previous
        free(temp);     
    }
    //Am I really freeing the last one?
    free(current);

    root->next=NULL;
    root=NULL;

}
void addingHundred(struct Node* trans)
{
    int i;
    for(i=0;i<100;i++)
    {
        newNode(trans,i);
    }
}

int main()
{
    struct Node* root;
    //create heap mem for root
    root=malloc(sizeof(struct Node));
    root->next=NULL;
    root->data=10;
    //traversal pointer
    struct Node* trans;
    //setting to point to root
    trans=root;
    //adding a new node..
    newNode(trans,8);
    printf("value of trans after function call: %p\n",trans);
    newNode(trans,12);
    //value does not change
    printf("value of trans after function call: %p\n",trans);
    addingHundred(trans);

    //printing the list
    printList(root);

    int storage;
    //removing last node
    storage=removeLastNode(trans);
    //returns the last nodes value
    printf("value removed: %d\n",storage);
    printList(root);
    freeList(root);
    printList(root);

    return 0;
}

我对上面编写的代码有几个问题。一般概念问题在main 中,我用这个结构创建了一个struct Node* tran,我调用了newNode 函数,它接收一个结构Node*。现在我输入tran 作为参数,我没有传递tran 的地址。在这种情况下,函数newNode 不会创建tran 值的副本,并且函数中的任何操作都将在函数调用后撤消?

我在 print 语句中注意到这一点,至少 tran 的值在 newNode 函数调用后不会改变。我想要了解的是我的链接列表如何扩展并被跟踪?在这种情况下是否将tran 的值作为参数传递,因为它最初指向根值的堆内存,然后简单地遍历堆中的内存,但实际上并没有改变内存的内容?

如果是这样,那么为了更改列表中节点的值,我必须将 &amp;trans 作为参数传递,但如果我只是遍历列表以在末尾添加一个节点,我可以传递 @987654334 @ 作为参数?

我的另一个问题是我不相信我的freeList(struct Node* a) 函数工作正常。当我释放root 然后打印它时,它会为我打印一个垃圾值,而它应该打印“列表为空”还是打印垃圾会导致它访问我不拥有的内存?

最后,这里有人批评我的代码是“最终用户应用程序代码”。我仍然是编码新手,我不确定上面的代码是否格式不正确,或者最终用户应用程序代码意味着什么。如果有人解释我如何避免编写“最终用户应用程序代码”,我将不胜感激。

【问题讨论】:

  • 这是个大问题。
  • 不解释不知道怎么问清楚。
  • 代码应始终检查 malloc(和系列)的返回值,以确保操作成功
  • 指针的副本仍然指向同一个地方。所以指针可以作为参数传递并且仍然可以正常工作。 IE。可以修改指针指向的地方。但是,它需要是指向指针的指针才能改变指针指向的位置
  • @user3629249 谢谢,这是我需要澄清的事情之一。为了确保遍历此处有效,因为我们没有修改指针最后指向的位置,而是使用它来临时转到列表的末尾?

标签: c function pointers struct linked-list


【解决方案1】:

您不是按值传递trans,而是传递一个指向Node 结构的指针,因此永远不会复制。

你说

我不传tran的地址

这绝对是错误的,你传递的实际上就是这样。

值不会改变,因为你没有修改指针,在每次调用 newNode 之后,trans 指针指向与调用前相同的地址,所以值没有变化应该遵守

当您调用newNode 时,新节点会附加到列表的尾部,因此如果您实际遍历列表,您会看到所有值,以下代码将打印这些值

struct Node *node;
for (node = root ; node != NULL ; node = node->next)
    printf("value %d @ %p\n", node->val, node);

你应该看到每个节点的地址,它的值

free 不是为了0 内存,而是你free 它,对于操作系统,这就像你放弃了该地址的内存所有权,如果有义务0内存,因此会对性能造成巨大影响。

如果你想根据你的代码列出empty,你应该在调用freeList()之后这样做

root = NULL;

我修复了你的代码


备注:您的freeList 函数末尾有一个free(current),它双重释放最后一个节点,所以我删除了它,还修复了一些样式内容,并创建了printList() 函数更具可读性

#include <stdio.h>
#include <stdlib.h>
//why does this work with pointers thought they made a copy?
//am i freeing memory correctly and well?
//Something wrong with freeing
struct Node{

    struct Node* next;
    int data;

};
void newNode(struct Node* trans, int val)
{
    if (trans != NULL)
    {
        while (trans->next != NULL)
            trans = trans->next;
        /* next is null create heap memory */
        trans->next=malloc(sizeof(struct Node));
        /* checking to see if memory is created */
        if(trans->next == NULL)
            printf("This has failed");
        /* put in data */
        trans->next->data = val;
        /* next is null */
        trans->next->next = NULL;
    }
}
void printList(struct Node* head)
{
    struct Node *node;

    if (head == NULL)
        printf("empty list\n");
    for (node = head ; node != NULL ; node = node->next)
        printf("list is: %d\n", node->data);
}

int removeLastNode(struct Node* trans)
{
    int val = -1;
    /* return -1 if its a empty list */
    struct Node *node;
    struct Node *last;
    if (trans == NULL)
        return -1;
    /*
    * have to access trans->next->next cause you are freeing trans->next->next and getting its val
    * then you want to set tran->next to NULL!
    */
    node = trans;
    last = node->next;
    while (last->next != NULL)
    {
        node = node->next;
        last = node->next;
    }
    trans = node;
    node  = node->next;

    /* at end of the list? */
    val = node->data;
    /* free the heap */
    free(node);
    /* next points to null */
    trans->next = NULL;

    return val;
}

//LOOK AT ME!
void freeList(struct Node* root)
{
    struct Node* temp;
    struct Node* current;

    current = root;
    while (current != NULL)
    {
        temp=current;
        /* going to the next one */
        current=current->next;
        /* freeing previous */
        free(temp);
    }
}
void addingHundred(struct Node* trans)
{
    int i;
    for (i=0 ; i < 100 ; i++)
        newNode(trans, i);
}

int main()
{
    struct Node* root;
    int          storage;

    //create heap mem for root
    root = malloc(sizeof(struct Node));

    root->next=NULL;
    root->data=10;

    //adding a new node..
    newNode(root, 8);
    newNode(root, 12);

    addingHundred(root);

    //printing the list
    printList(root);


    //removing last node
    storage = removeLastNode(root);

    //returns the last nodes value
    printf("value removed: %d\n", storage);
    printList(root);

    freeList(root);

    root = NULL;

    printList(root);

    return 0;
}

我在你的问题正文中为你的最后一条评论做了这个。我不明白,但你当然可以改进你的代码格式。不要害怕使用空格字符,编译器无论如何都会忽略它们(当然字符串文字除外)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 2011-03-19
    • 1970-01-01
    相关资源
    最近更新 更多