【问题标题】:C Copying a linked list with two pointersC复制带有两个指针的链表
【发布时间】:2018-12-30 12:29:15
【问题描述】:

这是一个学校项目,我需要完成一个函数来复制看起来像这样的员工链接列表

typedef struct TEmployee
{
    struct TEmployee * m_Next;
    struct TEmployee * m_Bak;
    char * m_Name;
} TEMPLOYEE;

这是我的复制功能

TEMPLOYEE * cloneList(TEMPLOYEE * src)
{
    TEMPLOYEE* current = src;
    TEMPLOYEE* newList = NULL;
    TEMPLOYEE* tail = NULL;

    while(current != NULL)
    {
        if(newList==NULL)
        {
            newList = (TEMPLOYEE*)malloc(sizeof(TEMPLOYEE));
            newList -> m_Name = current -> m_Name;
            newList -> m_Next = NULL;
            newList -> m_Bak = NULL;
            tail = newList;
        }
        else
        {
            tail -> m_Next = (TEMPLOYEE*)malloc(sizeof(TEMPLOYEE));
            tail = tail -> m_Next;
            tail -> m_Name = current -> m_Name;
            tail -> m_Next = NULL;
            tail -> m_Bak = current -> m_Bak;
        }
        current = current -> m_Next;
    }

    return newList;
}

这工作正常,但它不能正确复制 m_Bak,所以当我尝试这个断言时,m_Next 和 m_Bak 应该是相同的,但不是

assert ( b && ! strcmp ( b -> m_Name, "Maria" ) && b -> m_Bak == b -> m_Next );

感谢任何帮助。

【问题讨论】:

  • xxxx -> m_Name = current -> m_Name; 行不会克隆 C 中的字符串,您可以使用 memcpy() 整个结构进行克隆。我个人更喜欢使用 calloc 来自动 0-ing 一个新结构。
  • 使用strdup复制字符串
  • 至于样式:大写名称通常用于预处理器名称或structs 的名称(例如typedef struct TEMPLOYEE {...}tEmployee;)。以m_ 开头的名称通常在 C++ 中用于表示变量是类的属性。

标签: c pointers linked-list char assert


【解决方案1】:

这一行

tail -> m_Bak = current -> m_Bak;

错误,因为它使新列表指向当前列表。

你更需要:

    else
    {
        tail -> m_Next = (TEMPLOYEE*)malloc(sizeof(TEMPLOYEE));
        tail -> m_Next -> m_Bak = tail;  // New line
        tail = tail -> m_Next;
        tail -> m_Name = current -> m_Name;
        tail -> m_Next = NULL;
        // tail -> m_Bak = current -> m_Bak; Delete this line
    }

请注意,您的代码确实复制名称,因此两个列表将指向相同的名称对象。如果您想复制名称,请查看strdup

另请注意:

您不需要转换malloc 返回的值。但是,您应该检查 malloc 是否返回 NULL

【讨论】:

  • 谢谢,我已将名称更改为tail -> m_Name = malloc(strlen(current -> m_Name)); strcpy(tail -> m_Name, current -> m_Name); m_Bak 复制适用于第一个节点之后的每个节点,但第一个节点在原始列表中已经有 m_Bak 地址,此后不会被复制在if里面,我应该怎么复制呢?
  • @Lada1208 使用tail -> m_Name = malloc(1 + strlen(current -> m_Name));,因为您需要为字符串终止留出空间
【解决方案2】:

这是我的解决方案:

typedef struct TEmployee
{
    struct TEmployee * m_Next;
    struct TEmployee * m_Bak;
    char * m_Name;
} TEMPLOYEE;

void *Malloc(size_t size)
{
    void *ptr = NULL;
    if ((ptr = malloc(size)) == NULL)
    {
        perror("alloc");
        exit(1);
    }

    return ptr;
}

TEMPLOYEE *cloneList(TEMPLOYEE *src)
{
    TEMPLOYEE *newList = (TEMPLOYEE *)Malloc(sizeof(TEMPLOYEE));
    newList->m_Bak = NULL;

    TEMPLOYEE *copy = newList;
    TEMPLOYEE *current = src;

    while (current != NULL)
    {
        newList->m_Name = strdup(current->m_Name);  // need free
        newList->m_Next = NULL;

        if (current = current->m_Next)
        {
            newList->m_Next = (TEMPLOYEE *)Malloc(sizeof(TEMPLOYEE));
            newList->m_Next->m_Bak = newList;
            newList = newList->m_Next;
        }
    }

    return copy;
}

希望我能正确理解您的问题...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-20
    • 2017-04-15
    • 2013-08-07
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    相关资源
    最近更新 更多