如何在 C 中复制队列?
How can I make a copy of a queue in C?
我正在尝试将一个队列复制到另一个队列中,以便在销毁一个队列时不会销毁另一个队列。
我试过这样使用 memcpy
:
memcpy(queue1, queue2, sizeof(queue2));
但我收到以下错误:
expected ‘void * restrict’ but argument is of type 'Queue'
是否可以将一个队列复制到另一个队列?
编辑
这是队列的结构:
typedef char *Following;
typedef struct _NodeQ {
Following element;
struct _NodeQ * next;
} NodeQ;
typedef struct {
int error;
NodeQ * first;
NodeQ * last;
} Queue;
您的编译器警告您 memcpy
需要两个指针作为第一个参数。这将是正确的复制方式:
memcpy(&queue1, &queue2, sizeof(queue2));
以上行将用 queue2
的内容覆盖结构 queue1
,有效地将 quque2
复制到 queue1
。
memcpy
绝对不是这样,因为那样只会让你执行“浅拷贝”。如果您认为您的对象可以存储指向外部数据的指针,则该对象的浅拷贝将指向完全相同的外部数据,而不是复制所有内容(“深拷贝”)。
执行深拷贝的方法完全取决于实现。看起来您的队列正在使用一个简单的链表实现(请参阅每个 NodeQ
结构如何包含指向另一个 NodeQ
结构的指针,该结构具有指向另一个结构的指针,依此类推)。这在 C 中很常见。困难的部分是弄清楚如何复制队列中每个对象的“数据”部分(在本例中为 Following
类型变量)。我不知道您使用的是哪种定义 Queue
类型的库或框架,您应该参考一些文档来帮助您了解具体细节。谁知道呢,也许您会找到一种由图书馆支持的方式来复制您想要的方式。不过,我会尝试做你想做的,有一些假设。
从这一点开始推测
这只是一个猜测,但似乎 Following
可以表示一个字符串,因为它是一个字符指针。我在下面编写的代码使用了这个假设。请注意,虽然它未经测试并且有点仓促,但我只是想说明在您的场景中执行手动深层复制的样子。
Queue queue2;
NodeQ *e2, *e2prev = NULL, *e2first = NULL;
// Iterate through all elements of the first queue
for (NodeQ *e1 = queue1.first; e1; e1 = e1->next) {
// Allocate memory for the new element of queue 2
if (!(e2 = (NodeQ*)malloc(sizeof(NodeQ)))) {
printf("not enough memory\n");
}
// Remember the first element of queue for future use
if (!e2first)
e2first = e2;
// Note that strlen here could cause a segfault if my guess that "element" is a string is wrong
size_t buflen = strlen(e1->element) + 1; // +1 for null terminator
if (!(e2->element = (Following)malloc(sizeof(char) * buflen))) {
printf("not enough memory\n");
}
strcpy(e2->element, e1->element);
e2->next = NULL;
// Link new element with previous element
if (e2prev)
e2prev->next = e2;
e2prev = e2;
}
queue2.error = queue1.error;
queue2.first = e2first;
queue2.last = e2;
我正在尝试将一个队列复制到另一个队列中,以便在销毁一个队列时不会销毁另一个队列。
我试过这样使用 memcpy
:
memcpy(queue1, queue2, sizeof(queue2));
但我收到以下错误:
expected ‘void * restrict’ but argument is of type 'Queue'
是否可以将一个队列复制到另一个队列?
编辑
这是队列的结构:
typedef char *Following;
typedef struct _NodeQ {
Following element;
struct _NodeQ * next;
} NodeQ;
typedef struct {
int error;
NodeQ * first;
NodeQ * last;
} Queue;
您的编译器警告您 memcpy
需要两个指针作为第一个参数。这将是正确的复制方式:
memcpy(&queue1, &queue2, sizeof(queue2));
以上行将用 queue2
的内容覆盖结构 queue1
,有效地将 quque2
复制到 queue1
。
memcpy
绝对不是这样,因为那样只会让你执行“浅拷贝”。如果您认为您的对象可以存储指向外部数据的指针,则该对象的浅拷贝将指向完全相同的外部数据,而不是复制所有内容(“深拷贝”)。
执行深拷贝的方法完全取决于实现。看起来您的队列正在使用一个简单的链表实现(请参阅每个 NodeQ
结构如何包含指向另一个 NodeQ
结构的指针,该结构具有指向另一个结构的指针,依此类推)。这在 C 中很常见。困难的部分是弄清楚如何复制队列中每个对象的“数据”部分(在本例中为 Following
类型变量)。我不知道您使用的是哪种定义 Queue
类型的库或框架,您应该参考一些文档来帮助您了解具体细节。谁知道呢,也许您会找到一种由图书馆支持的方式来复制您想要的方式。不过,我会尝试做你想做的,有一些假设。
从这一点开始推测
这只是一个猜测,但似乎 Following
可以表示一个字符串,因为它是一个字符指针。我在下面编写的代码使用了这个假设。请注意,虽然它未经测试并且有点仓促,但我只是想说明在您的场景中执行手动深层复制的样子。
Queue queue2;
NodeQ *e2, *e2prev = NULL, *e2first = NULL;
// Iterate through all elements of the first queue
for (NodeQ *e1 = queue1.first; e1; e1 = e1->next) {
// Allocate memory for the new element of queue 2
if (!(e2 = (NodeQ*)malloc(sizeof(NodeQ)))) {
printf("not enough memory\n");
}
// Remember the first element of queue for future use
if (!e2first)
e2first = e2;
// Note that strlen here could cause a segfault if my guess that "element" is a string is wrong
size_t buflen = strlen(e1->element) + 1; // +1 for null terminator
if (!(e2->element = (Following)malloc(sizeof(char) * buflen))) {
printf("not enough memory\n");
}
strcpy(e2->element, e1->element);
e2->next = NULL;
// Link new element with previous element
if (e2prev)
e2prev->next = e2;
e2prev = e2;
}
queue2.error = queue1.error;
queue2.first = e2first;
queue2.last = e2;