双链表中的常量结构正在C中修改
我处理的是双链接列表,这是一个我没有解决的问题。为了更好地说明这一点,在我说明问题之前,下面是代码 Dblist.h双链表中的常量结构正在C中修改,c,data-structures,linked-list,constants,C,Data Structures,Linked List,Constants,我处理的是双链接列表,这是一个我没有解决的问题。为了更好地说明这一点,在我说明问题之前,下面是代码 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;
# 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;
}
#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;
}
从这里可以看到,不仅是getInterval
返回的结果(在本例中是main.c中的interval变量),而且是pdbListe
变量,本质上不应该修改它
我能做些什么来解决这个问题?我希望
pdbListe
保持原样,永远不受getInterval
正在做的事情的影响。如果希望getRange返回子列表,而原始列表保持不变,则需要修改终止列表(将端点放在列表上)的方式。您需要停止使用NULL作为结束标记,而是使用与第一个/最后一个元素指针的比较。例如:
void printList(dblist *list) {
for (elem *e = list->first; e != list->last; e = e->next) {
printf("%d ", e->value);
}
}
注意e!=列表->最后一个
,而不是e!=空
这样,您就可以通过构造一个具有新起点/终点的dblist来创建子列表。它不再需要对基础链接(next和prev)进行任何修改。对不起,正确的句子是:“从这里可以看到不仅是getRange返回的结果(在本例中是main.c中的range变量)但是pdbListe变量也在被修改,本质上永远不应该被修改!!有两件事:你的代码甚至没有被编译,因为有些函数使用了一个名为“s”的参数,然后试图使用一个名为“l”的未声明变量(当它们的意思是“s”)第二,你到底为什么要用memmove来复制一个指针?你的意思是复制“l”的东西吗“指向?可能代码没有编译,对此我深表歉意。”。事实上,为了使代码可读,需要进行大量的编辑,因此可能会出现错误,但我确信我没有改变逻辑。memcopy只是为了好玩!您只需使用assigment运算符(=),在稍微修改代码后,它将非常有用!谢谢兰德,谢谢你指出这一点。事实上,正如我所写的,当我放弃使用NULL作为列表端点的值时,行为发生了变化。这正是我在建议注释getRange()[现在是getInterval()]的某些部分时提到的。我注意到,当我在范围[interval]列表上运行ViewReverse()函数时,它会精确地打印出原始列表。如果我不能很好地理解你的建议,请给出getRange()[getInterval()]函数的新构造来启发我。Thanks@Randall:考虑到您的建议,我修改了getRange()[getInterval()]函数,如bellow,并得到了一些有趣的结果:当我应用ViewReverse()时,原始列表没有被修改,但新列表仍然包含一些元素(前面弹出的元素)[尚未与printList()一起使用]您显示的构造是因为我想非常确定新列表在范围的边界]函数内。它是这样的:如果(范围->第一个)范围->第一个->上一个=l->第一个->上一个;其他范围->最后一个=l->最后一个@兰德尔:事实上,你的回答解决了我的问题!但是,如果你能考虑到我的最后一个问题并加以研究,这将是一个更大的帮助。最佳重新考虑在ViewReverse中,您需要将“while(test)”更改为“while(test!=l.first)”,因为“while(test)”是空检查的简写。确定。我理解这一点,我做了修改(事实上,它工作得很好)。问题是为什么新的子列表包含弹出的元素,而我不再包含NULL作为结束标记?不应该!尝试使用while(test)运行ViewReverse,它会显示那些元素仍然存在。不应该!你知道怎么把它们脱掉吗?
void printList(dblist *list) {
for (elem *e = list->first; e != list->last; e = e->next) {
printf("%d ", e->value);
}
}