C中双向链表中的const结构正在被修改
我正在处理双向链表,并出现了一个我无法解决的问题。为了更好地说明它,在我说问题是什么之前,这是代码。
Dblist.h
# Ifndef CGI_DBLIST_H
# Define CGI_DBLIST_H
# Include "malloc.h"
/ * Structure represantative an element of the list. * /
typedef struct elem
{
int value;
struct elem * prev;
struct elem * next;
} Elem;
/ * Structure access to the list. * /
typedef struct
{
elem * first;
elem * last;
} dblist;
# ifdef __cplusplus
extern "C" {
# Endif
void Init (dblist * l); /* Initialize the list */
void pushback (dblist * s, int val); /* Add a value at end */
void PushFront (dblist * l, int val); /* Add a value at start */
int PopBack (dblist * l); /* Remove value at end */
int PopFront (dblist * l); /* Remove value at start */
void View (dblist l); /* Display whole list */
void ViewReverse (dblist l); /* Display all reversed */
void Clear (dblist * l); /* discard list */
dblist getInterval (dblist const * s);
#ifdef __cplusplus
}
#endif
#endif /* CGI_DBLIST_H */
Dblist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dblist.h"
#include "malloc.h"
void Init (dblist * l)
{
l-> first = NULL;
l-> last = NULL;
}
void pushback (dblist * s, int val)
{
elem * n = malloc (sizeof (elem));
if (! n) exit (EXIT_FAILURE);
n-> value = val;
n-> prev = l-> last;
n-> next = NULL;
if (s-> last) s-> last-> next = n;
else s-> first = n;
l-> last = n;
}
void PushFront(dblist *l, int val)
{
elem *n = malloc(sizeof(elem));
if(!n) exit(EXIT_FAILURE);
n->value = val;
n->next = l->first;
n->prev = NULL;
if(l->first) l->first->prev = n;
else l->last = n;
l->first = n;
}
int PopBack(dblist *l)
{
int val;
elem *tmp = l->last;
if(!tmp) return -1;
val = tmp->value;
l->last = tmp->prev;
if(l->last) l->last->next = NULL;
else l->first = NULL;
free(tmp);
return val;
}
int popFront(dblist* l)
{
int val;
elem *tmp = l->first;
if(!tmp) return -1;
val = tmp->value;
l->first = tmp->next;
//if(l->first)l->first->prev = NULL;
//else l->last = NULL;
//free(tmp);
return val;
}
dblist getInterval (dblist const * s)
{
dblist* intervals = NULL;
memmove(&intervals, &l, sizeof(l));
if(intervals->first)intervals->first->prev = NULL;
else intervals->last = NULL;
return *intervals;
}
void View (dblist l)
{
elem *pelem = l.first;
while (Pelem)
{
printf ("% d \ n", pelem-> value);
pelem = pelem-> next;
}
}
void ViewReverse (dblist l)
{
elem* test = l.last;
while (test)
{
printf("% d \ n", test-> value);
test = test-> prev;
}
}
void Clear (dblist * l)
{
elem *tmp;
elem *pelem = l->first;
while(pelem)
{
tmp = pelem;
pelem = pelem->next;
free(tmp);
}
l->first = NULL;
l->last = NULL;
}
main.c
#include <stdlib.h>
#include <stdio.h>
#include "dblist.h"
int main ()
{
dblist pdbListe * = malloc (sizeof (dblist));
dblist interval;
Init (pdbListe);
printf ("Pushin In The gains list\n");
PushFront (pdbListe, 10);
Pushback (pdbListe, 20);
Pushback (pdbListe, 40);
PushFront (pdbListe, 23);
PushFront (pdbListe, 70);
PushFront (pdbListe, 54);
printf ("Viewing the list:\n");
View (pdbListe *);
puts ("--------------");
printf ("poping front capital gains from The Stack:\n");
printf ("% d\n", PopFront (pdbListe));
printf ("% d\n", PopFront (pdbListe));
/ / Printf ("% d\n", PopBack (pdbListe));
puts ("--------------");
printf ("Viewing the list after pop front:\n");
View (pdbListe *);
puts ("--------------");
printf ("this is pdbListe:% p\n", pdbListe);
printf ("this is interval:% p\n", & interval);
interval = getInterval (pdbListe);
printf ("Viewing the interval\n");
ViewReverse (interval);
printf ("first element is:% d\n", interval.first-> value);
printf ("last element is:% d\n", interval.last-> value);
puts ("--------------");
printf ("Reverse Viewing the list after pop front:\n");
ViewReverse (pdbListe *); // ISSUE HERE: it should print 6 elements not 4
puts ("--------------");
printf ("this is pdbListe:% p\n", pdbListe);
printf ("this is interval:% p\n", & interval);
printf ("sizeof pdbListe% d\n", sizeof (pdbListe));
printf ("sizeof interval% d\n", sizeof (interval));
printf ("Pushing back a value in The List:\n");
Pushback (pdbListe, 30);
printf ("Viewing the list after push back:\n");
View (pdbListe *);
puts ("--------------");
printf ("In The Front popping list:\n");
printf ("% d\n", PopFront (pdbListe));
printf ("% d\n", PopFront (pdbListe));
puts ("--------------");
printf ("Viewing the list after pop front:\n");
View (pdbListe *);
puts ("--------------");
printf ("Clearing the list\n");
Clear (pdbListe);
printf ("Freeing the list\n");
free (pdbListe);
system ("PAUSE");
return 0;
}
不关心malloc.h,它是一个小实用程序使用来确保正确的内存 usgae
所以问题是间隔变量来自 getInterval(const dblist *)
,我希望它在以下任一情况下仅保存初始列表的一部分 popBack
或 popFront
已应用。
问题是,如果我对 getInterval
进行修改,它会影响 pdbListe
的值。例如,尝试像这样修改 getInterval
(尝试注释这些行,如下所示):
dblist getInterval(const dblist* l) {
dblist* intervals = NULL;
memmove(&intervals, &l, sizeof(l));
//if(intervals->first)intervals->first->prev = NULL;
//else intervals->last = NULL;
return *intervals;
}
从那里可以看到,不仅 getInterval
返回的结果(在本例中) main.c 中的间隔变量)以及 pdbListe
变量,本质上永远不应该修改它!
我可以做些什么来解决这个问题?我希望 pdbListe 保持原样,并且永远不会受到 getInterval 所做操作的影响。
I'm dealing with doubly linked lists and came an issue I'm not working around. To illustrate it better, here's is the code before I say what the issue is.
Dblist.h
# Ifndef CGI_DBLIST_H
# Define CGI_DBLIST_H
# Include "malloc.h"
/ * Structure represantative an element of the list. * /
typedef struct elem
{
int value;
struct elem * prev;
struct elem * next;
} Elem;
/ * Structure access to the list. * /
typedef struct
{
elem * first;
elem * last;
} dblist;
# ifdef __cplusplus
extern "C" {
# Endif
void Init (dblist * l); /* Initialize the list */
void pushback (dblist * s, int val); /* Add a value at end */
void PushFront (dblist * l, int val); /* Add a value at start */
int PopBack (dblist * l); /* Remove value at end */
int PopFront (dblist * l); /* Remove value at start */
void View (dblist l); /* Display whole list */
void ViewReverse (dblist l); /* Display all reversed */
void Clear (dblist * l); /* discard list */
dblist getInterval (dblist const * s);
#ifdef __cplusplus
}
#endif
#endif /* CGI_DBLIST_H */
Dblist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dblist.h"
#include "malloc.h"
void Init (dblist * l)
{
l-> first = NULL;
l-> last = NULL;
}
void pushback (dblist * s, int val)
{
elem * n = malloc (sizeof (elem));
if (! n) exit (EXIT_FAILURE);
n-> value = val;
n-> prev = l-> last;
n-> next = NULL;
if (s-> last) s-> last-> next = n;
else s-> first = n;
l-> last = n;
}
void PushFront(dblist *l, int val)
{
elem *n = malloc(sizeof(elem));
if(!n) exit(EXIT_FAILURE);
n->value = val;
n->next = l->first;
n->prev = NULL;
if(l->first) l->first->prev = n;
else l->last = n;
l->first = n;
}
int PopBack(dblist *l)
{
int val;
elem *tmp = l->last;
if(!tmp) return -1;
val = tmp->value;
l->last = tmp->prev;
if(l->last) l->last->next = NULL;
else l->first = NULL;
free(tmp);
return val;
}
int popFront(dblist* l)
{
int val;
elem *tmp = l->first;
if(!tmp) return -1;
val = tmp->value;
l->first = tmp->next;
//if(l->first)l->first->prev = NULL;
//else l->last = NULL;
//free(tmp);
return val;
}
dblist getInterval (dblist const * s)
{
dblist* intervals = NULL;
memmove(&intervals, &l, sizeof(l));
if(intervals->first)intervals->first->prev = NULL;
else intervals->last = NULL;
return *intervals;
}
void View (dblist l)
{
elem *pelem = l.first;
while (Pelem)
{
printf ("% d \ n", pelem-> value);
pelem = pelem-> next;
}
}
void ViewReverse (dblist l)
{
elem* test = l.last;
while (test)
{
printf("% d \ n", test-> value);
test = test-> prev;
}
}
void Clear (dblist * l)
{
elem *tmp;
elem *pelem = l->first;
while(pelem)
{
tmp = pelem;
pelem = pelem->next;
free(tmp);
}
l->first = NULL;
l->last = NULL;
}
main.c
#include <stdlib.h>
#include <stdio.h>
#include "dblist.h"
int main ()
{
dblist pdbListe * = malloc (sizeof (dblist));
dblist interval;
Init (pdbListe);
printf ("Pushin In The gains list\n");
PushFront (pdbListe, 10);
Pushback (pdbListe, 20);
Pushback (pdbListe, 40);
PushFront (pdbListe, 23);
PushFront (pdbListe, 70);
PushFront (pdbListe, 54);
printf ("Viewing the list:\n");
View (pdbListe *);
puts ("--------------");
printf ("poping front capital gains from The Stack:\n");
printf ("% d\n", PopFront (pdbListe));
printf ("% d\n", PopFront (pdbListe));
/ / Printf ("% d\n", PopBack (pdbListe));
puts ("--------------");
printf ("Viewing the list after pop front:\n");
View (pdbListe *);
puts ("--------------");
printf ("this is pdbListe:% p\n", pdbListe);
printf ("this is interval:% p\n", & interval);
interval = getInterval (pdbListe);
printf ("Viewing the interval\n");
ViewReverse (interval);
printf ("first element is:% d\n", interval.first-> value);
printf ("last element is:% d\n", interval.last-> value);
puts ("--------------");
printf ("Reverse Viewing the list after pop front:\n");
ViewReverse (pdbListe *); // ISSUE HERE: it should print 6 elements not 4
puts ("--------------");
printf ("this is pdbListe:% p\n", pdbListe);
printf ("this is interval:% p\n", & interval);
printf ("sizeof pdbListe% d\n", sizeof (pdbListe));
printf ("sizeof interval% d\n", sizeof (interval));
printf ("Pushing back a value in The List:\n");
Pushback (pdbListe, 30);
printf ("Viewing the list after push back:\n");
View (pdbListe *);
puts ("--------------");
printf ("In The Front popping list:\n");
printf ("% d\n", PopFront (pdbListe));
printf ("% d\n", PopFront (pdbListe));
puts ("--------------");
printf ("Viewing the list after pop front:\n");
View (pdbListe *);
puts ("--------------");
printf ("Clearing the list\n");
Clear (pdbListe);
printf ("Freeing the list\n");
free (pdbListe);
system ("PAUSE");
return 0;
}
Don't care about the malloc.h, it is small utility I'm using to ensure correct memory usgae
So the problem is the interval variable comes from getInterval(const dblist *)
, I want it to hold only a part of the initial list when either popBack
or popFront
has been applied.
The problem is that if I make modifications to getInterval
, it is influencing the values of pdbListe
. For example try to modify getInterval
like this (try to comment those lines as illustrated below):
dblist getInterval(const dblist* l) {
dblist* intervals = NULL;
memmove(&intervals, &l, sizeof(l));
//if(intervals->first)intervals->first->prev = NULL;
//else intervals->last = NULL;
return *intervals;
}
From there one can see that not only the result returned by getInterval
(in this case the interval variable in main.c) but also the pdbListe
variable which by essence should never be modified!
What can I do to work around this? I want pdbListe
to remain as such and never be affected by what getInterval
is doing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您希望 getRange 返回子列表,而原始列表保持不变,则需要修改终止列表(将端点放入列表)的方式。您将需要停止使用 NULL 作为结束标记,并使用与第一个/最后一个元素指针的比较。例如:
请注意
e != list->last
,而不是e != NULL
。这样,您可以通过构造具有新起点/终点的 dblist 来创建子列表。它不再需要对底层链接(下一个和上一个)进行任何修改。
If you want getRange to return a sublist, while the original list remains unmodified, then you need to modify how you terminate (put endpoints on) your list. You will need to stop using NULL as an end marker and use comparison to the first/last element pointers instead. For example:
Note the
e != list->last
, note != NULL
.That way, you can make a sublist by constructing a dblist with new start/end points. It no longer requires any modification to the underlying links (next and prev).