c-如何更新指针以创建列表



我正在学习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 && ./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块应该在函数的第一次执行之后运行,因为据说我添加了一个新元素。我认为我没有正确更新_list的值,但我已经没有可用的选项了。知道怎么解决吗?

您编写此的方式存在许多问题

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%sn", msg);
if (L == NULL)
{
printf("There is no list: nothing to display");
return -1;
}
printf("   List has %d elements:nn", L->size);
Node* p = L->head;
for (unsigned i = 0; i < L->size; i += 1)
{
printf("%5u  %sn", p->tk->USN, p->tk->ts);
p = p->next;
}
printf("nn");
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;
}

最新更新