【问题标题】:How to update the pointer to create a list如何更新指针以创建列表
【发布时间】:2021-12-26 06:06:05
【问题描述】:

我正在尝试学习 C,但在使用指针创建列表时遇到了一些问题。

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

typedef struct _tDateTimeNode
{
    struct _tDateTimeNode *next;
} tDateTimeNode;

typedef struct _ApiData
{
    tDateTimeNode *timeNodeList;
} tApiData;

void dateTimeNode_insert(tDateTimeNode **_list)
{
    bool found = false;
    tDateTimeNode *list = (*_list);
    while (list != NULL && !found)
    {
        printf("This code never runs!\n");
        list = list->next;
    }

    if (list == NULL)
    {
        printf("This if is always executed!\n");
        list = (tDateTimeNode *)malloc(sizeof(tDateTimeNode));
    }

    if (*_list == NULL)
    {
        printf("This if is also executed!\n");
        _list = &list;
    }
}

int main()
{
    tApiData data;
    data.timeNodeList = NULL;

    tDateTimeNode **timeNode = &(data.timeNodeList);
    dateTimeNode_insert(timeNode);
    dateTimeNode_insert(timeNode);
    dateTimeNode_insert(timeNode);
    dateTimeNode_insert(timeNode);
}

使用gcc -o t test.c &amp;&amp; ./t 编译问题后,我得到以下输出:

This if is always executed!
This if is also executed!
This if is always executed!
This if is also executed!
This if is always executed!
This if is also executed!
This if is always executed!
This if is also executed!

如你所见,最后两个 if 总是被执行。但是 while 永远不会运行。 while 块应该在函数第一次执行后运行,因为据说我添加了一个新元素。我想我没有正确更新_list 的值,但我已经没有办法尝试了。知道如何解决吗?

【问题讨论】:

  • _list = &amp;list; -> *_list = list;
  • 你应该打开编译器警告

标签: c linked-list


【解决方案1】:

你写这个的方式有很多问题

void dateTimeNode_insert(tDateTimeNode **_list)
{
    bool found = false;
    tDateTimeNode *list = (*_list);
    while (list != NULL && !found)
    {
        printf("This code never runs!\n");
        list = list->next;
    }

    if (list == NULL)
    {
        printf("This if is always executed!\n");
        list = (tDateTimeNode *)malloc(sizeof(tDateTimeNode));
    }

    if (*_list == NULL)
    {
        printf("This if is also executed!\n");
        _list = &list;
    }
}

请注意found 始终为假并且可以删除,因为!false 始终为真,永远不会改变

_listtDateTimeNode**所以应该在*_list中带入列表头的地址

当你写作时

   _list = &list;

对列表的唯一引用已经永远消失了。也许你打算写*_list = list;以便在插入第一个元素时保存列表的新头部

命名也很混乱:list_list

请注意,列表是一个容器。您不应将列表与数据混在一起。你今天的清单是DateTimeNode,但它仍然只是一个清单。在你的下一个程序中,可能是一本书,一首播放列表中的歌曲,所有经典的列表练习。如果代码更通用,则创建列表很简单。各种列表

示例:一个列表和一个DateTimeNode

我将使用您的代码发布一个示例,但使用我上面写的内容

想象一个控制队列的工单列表。每个进入的客户都会获得一张带有序列号和时间戳的票,格式为yyyy-mm-dd hh:mm:ss。客户在队列末尾进入。

这是一张可能的票

typedef struct
{
    char*    ts;   // time stamp
    unsigned USN;  // sequence number

}   Ticket;

可能的Node 获取这些票的列表

typedef struct _Node
{
    Ticket*       tk;
    struct _Node* next;

}   Node;

正如预期的那样,列表中的每个节点都指向一张票。列表只是一个容器。

列表本身可以是

typedef struct
{
    Node*    head;  // first node if any
    unsigned size;  // actual Node count

}   List;

这些方式更容易理解:列表有节点,每个节点指向一些数据。数据有编号,便于测试。并有时间戳。当然,计算机速度很快,时间戳分辨率是秒,所以我们需要数千个节点才能看到不同的时间戳......

最小的函数集

List* create();
List* destroy(List*);
int   insert(Ticket*, List*);
int   show(List*, const char*);

show() 接受消息的可选字符串,destroy() 返回 NULL 作为礼貌,因此我们可以在销毁列表的同一行中使列表指针无效。

一个测试

int main(void)
{
    Ticket ticket;
    List*  one = create();
    for (int i = 1; i <= 10; i += 1)
    {
        ticket.USN = i;
        ticket.ts  = get_ts();
        insert(&ticket, one);
    };
    show(one, "After 10 tickets inserted...\n");
    one = destroy(one);  // destroys list, invalidate pointer
    return 0;
}

代码创建一个包含 10 张票的列表,显示它们并删除该列表。

输出

After 10 tickets inserted...

   List has 10 elements:

    1  2021-11-15 14:12:06
    2  2021-11-15 14:12:06
    3  2021-11-15 14:12:06
    4  2021-11-15 14:12:06
    5  2021-11-15 14:12:06
    6  2021-11-15 14:12:06
    7  2021-11-15 14:12:06
    8  2021-11-15 14:12:06
    9  2021-11-15 14:12:06
   10  2021-11-15 14:12:06

示例代码

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

typedef struct
{
    char*    ts;   // time stamp
    unsigned USN;  // sequence number
} Ticket;

typedef struct _Node
{
    Ticket*       tk;
    struct _Node* next;

} Node;

typedef struct
{
    Node*    head;  // first node if any
    unsigned size;  // actual Node count
} List;

// List stuff
List* create();
List* destroy(List*);
int   insert(Ticket*, List*);
int   show(List*, const char*);

// helpers
char* get_ts();  // get time in format "yyyy-mm-dd hh:mm:ss"

int main(void)
{
    Ticket ticket;
    List*  one = create();
    for (int i = 1; i <= 10; i += 1)
    {
        ticket.USN = i;
        ticket.ts  = get_ts();
        insert(&ticket, one);
    };
    show(one, "After 10 tickets inserted...\n");
    one = destroy(one);  // destroys list, invalidate pointer
    return 0;
};  // main()



List* create()
{
    List* list = (List*)malloc(sizeof(List));
    if (list == NULL) return NULL;
    list->head = NULL;
    list->size = 0;
    return list;
}

List* destroy(List* list)
{
    if (list == NULL) return NULL;
    Node* tmp = list->head->next;
    Node* p   = list->head;
    for (unsigned i = 0; i < list->size - 1; i += 1)
    {  // delete ticket and node at p
        free(p->tk);
        free(p);
        p   = tmp;
        tmp = p->next;
    }
    // p now points to last
    free(p->tk);
    free(p);
    free(list);  // the List itself
    return NULL;
}

int insert(Ticket* tk, List* L)
{  // insert tk into list L, at the end
    if (L == NULL) return -1;
    if (tk == NULL) return -2;
    // get a new ticket
    Ticket* nt = (Ticket*)malloc(sizeof(Ticket));
    *nt        = *tk;
    // now creates a new Node for this ticket
    Node* nnd = (Node*)malloc(sizeof(Node));
    nnd->next = NULL;
    nnd->tk   = nt;

    // list is empty?
    if (L->size == 0)
    {
        L->head = nnd;
        L->size = 1;
        return 0;  // ok
    }

    // search List end
    Node* p = L->head;
    while (p->next != NULL) p = p->next;
    p->next = nnd;  // last now points to new
    L->size += 1;
    return 0;  // ok
}

int show(List* L, const char* msg)
{
    if (msg != NULL) printf("\n%s\n", msg);
    if (L == NULL)
    {
        printf("There is no list: nothing to display");
        return -1;
    }
    printf("   List has %d elements:\n\n", L->size);
    Node* p = L->head;
    for (unsigned i = 0; i < L->size; i += 1)
    {
        printf("%5u  %s\n", p->tk->USN, p->tk->ts);
        p = p->next;
    }
    printf("\n\n");
    return L->size;
}

char* get_ts()
{  // return string in format: "yyyy-mm-dd hh:mm:ss"
    time_t moment;
    time(&moment);  // get time
    // convert time to struct tm
    struct tm* t_info     = localtime(&moment);
    char*      time_stamp = (char*)malloc(20);
    // format time stamp and return to caller
    strftime(time_stamp, 20, "%Y-%m-%d %H:%M:%S", t_info);
    return time_stamp;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2015-03-03
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多