我正在尝试创建一个方法,它将char *添加到LinkedList,确保linkedList始终按字母顺序排序。我已经获得了定义LinkedItem结构的代码:
// Define our list item as 'struct ListItem', and also
// typedef it under the same name.
typedef struct ListItem {
char *s;
struct ListItem *p_next;
} ListItem;
我还获得了一个方法,可以将项目添加到列表的开头:
// Adds a new item to the beginning of a list, returning the new
// item (ie the head of the new list *)
ListItem* add_item(ListItem *p_head, char *s) {
// Allocate some memory for the size of our structure.
ListItem *p_new_item = malloc(sizeof(ListItem));
p_new_item->p_next = p_head; // We are the new tail.
p_new_item->s = s; // Set data pointer.
return p_new_item;
}
现在这是我的代码,我会在以后解释更多:
ListItem* addSortedItem(ListItem *p_head, char *s){
if(p_head==NULL)//if the list is empty, we add to the beginning
return add_item(p_head,s);
ListItem* p_new_item = malloc(sizeof(ListItem));
ListItem *p_current_item = p_head; //makes a pointer to the head of the list
while (p_current_item) { // Loop while the current pointer is not NULL
printf("entering while loop with current=%s\n",p_current_item->s);
// now we want to look at the value contained and compare it to the value input
if(aThenB(s,p_current_item->s)!=TRUE){
// if A goes after B, we want to go on to look at the next element
p_current_item=p_current_item->p_next;
} else if (aThenB(s,p_current_item->s)==TRUE) {printf("entered elseif\n");
p_head=add_item(p_current_item,s);
return p_head;
} else {printf("WHY DID WE EVER REACH THE ELSE!?"); return p_head;}
}
}
现在,如果A和B的正确排序顺序是A,然后是B,则aThenB(StringA,StringB)返回TRUE,否则返回false - 相等也是一个选项,我根本没有让它工作得很好允许: - )
我的测试数据("sheep i"
,i为0-10)发生的事情是,我要么只返回一个元素,要么我随机跳过元素,具体取决于顺序输入。我可以包含更多代码,但它有点混乱。
我认为我的问题源于不完全理解指针及其工作原理 - 我想确保p_head始终指向头部,而p_current正在列表中流动。但是当p_current到达最后一个元素时,我也遇到了seg错误,所以我不确定我哪里出错了。
感谢您提供有关如何让我的代码正确返回的任何帮助: - )
编辑:在main方法的以下块中调用addSortedItem():
// The empty list is represented by a pointer to NULL.
ListItem *p_head = NULL;
ListItem *p_head2=NULL;
// Now add some items onto the beginning of the list.
int i;
for (i=0; i<NO_ITEMS; i++) {
// Allocate some memory for our string, and use snprintf to
// create a formatted string (see GNU API docs) much like printf
// but instead writing to memory rather than the screen.
char* s = malloc(MAX_DATA_CHARS);
snprintf(s, (size_t) MAX_DATA_CHARS, "sheep %d", i);
p_head = addSortedItem(p_head, s);
}
答案 0 :(得分:1)
在链接列表的中间或末尾添加新元素时出错。
在你的addStoredItem
函数中,你创建了一个从newItem到currentItem的指针,但你没有考虑从前一个元素到newItem的链接
初始链接列表,请致电addStoredItem
item1-->item2-->item4-->item5
链接列表afetr调用addStoredItem
以添加 item3
item1-->item2-->item4-->item5
^
|
item3
因为您可以看到从 item4 开始在子链接列表的头部添加了新项目,但是您没有从 item2 链接到项目3 强> 所以我们必须保留指向前一项的指针才能完成链接。
add_item()
功能允许在头部添加项目
如果您尝试在链接列表末尾添加项目
,则同样如此item1-->item2-->item4-->item5 NULL
^
|
item6
item6 已添加为单独的头部,并且没有从 item5 (上一个)到item6(新)的链接
因此您的addStoredItem()
功能可以像这样修复
ListItem* addSortedItem(ListItem *p_head, char *s){
if(p_head==NULL)//if the list is empty, we add to the beginning
return add_item(p_head,s);
struct ListItem* p_new_item = malloc(sizeof(ListItem));
ListItem *p_current_item = p_head; //makes a pointer to the head of the list
ListItem *p_prev_item = NULL; //FIXED
while (p_current_item) { // Loop while the current pointer is not NULL
printf("entering while loop with current=%s\n",p_current_item->s);
// now we want to look at the value contained and compare it to the value input
if(aThenB(s,p_current_item->s)!=TRUE){
// if A goes after B, we want to go on to look at the next element
p_prev_item = p_current_item; //FIXED
p_current_item=p_current_item->p_next;
} else if (aThenB(s,p_current_item->s)==TRUE) {printf("entered elseif\n");
break;
} else {printf("WHY DID WE EVER REACH THE ELSE!?"); return p_head;}
}
if (p_prev_item!=NULL) //FIXED
p_prev_item->p_next=add_item(p_current_item,s); //FIXED
else //FIXED
p_head=add_item(p_current_item,s);//FIXED
return p_head; //FIXED
}
固定线用//FIXED
答案 1 :(得分:0)
首先,您的p_head
为NULL
,因此当您输入addSortedItem
功能时,您可以创建列表并添加第一个字符串。没关系。
但是,在添加第二个项目(在您的情况下是“羊1”)后,您输入while (p_current_item)
循环。对aThenB
的调用会返回FALSE
,然后您转到下一个元素NULL
!实际上,此时p_head
看起来像这样:
p_head {
s = "sheep 0",
p_next = NULL
}
您的while
条件不正确,退出您的功能,没有添加任何内容
您可以在第一个if
添加条件,例如:
if (p_current_item->next == NULL)
p_current_item->next = addSortedItem(NULL, s);
else
p_current_item = p_current_item->next;
另外,说p_head=add_item(p_current_item,s);
是错误的。假设您的列表类似于:
"sheep 1" -> "sheep 2" -> "sheep 4" -> "sheep 5"
如果你添加“羊3”,你会得到这个:
"sheep 1" -> "sheep 2" -> "sheep 3" -> "sheep 4" -> "sheep 5"
^
|
p_head
您将无法再添加“羊0”。不要将addSortedItem
的返回值作为新p_head
答案 2 :(得分:0)
支持东西:
#define FALSE 0
#define TRUE 1
#define aThenB(a,b) (strcmp(a,b) <=0 ? TRUE : FALSE)
通过将函数的签名修改为,可以避免所有特殊情况 接受指向指针的指针。
void addSortedItem(ListItem **pp_head, char *s){
ListItem *p_new_item ;
for ( ;*pp_head; pp_head = &(*pp_head)->p_next) {
if (aThenB(s,(*pp_head)->s)==FALSE) break;
}
p_new_item = malloc(sizeof *p_new_item);
p_new_item->s = s;
p_new_item->p_next = *pp_head;
*pp_head = p_new_item;
}
来电者应该这样做:
ListItem *root = NULL;
addSortedItem( &root, "sheep#0");