我在链接列表中将字符串插入正确位置(插入排序)时遇到问题。当我在链接列表中添加一些位置并通过键入“0”结束程序时,程序只显示第一个位置。 我也怀疑“(strcmp(tmp-> ch,new-> ch)> 0)”它正在按照我的想法工作?(将新元素与电流进行比较(我的意思是它应该是'> '或'<'))。 我会非常感谢任何建议;)。我的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_L 30
typedef struct elem{
char ch[MAX_L];
struct elem *next;
struct elem *prev;
} list_elem;
void add_to_list (list_elem *first, char ch[MAX_L])
{
list_elem *new=(list_elem*)malloc(sizeof(list_elem));
strcpy(new->ch, ch);
list_elem *tmp=first;
do
{
if(tmp->next==NULL)
{
tmp->next=new;
new->prev=tmp;
new->next=NULL;
}
if (strcmp(tmp->ch,new->ch)>0) //guess here should be inserted new element
{
new->prev=tmp->prev;
new->next=tmp;
tmp->prev=new;
}
else
tmp=tmp->next;
}while (tmp->next!=NULL);
}
void print_list(list_elem *first)
{
first=first->next;
if(first->ch==NULL)
printf("lista jest pusta!!\n");
while(first->next!=NULL){
printf("%s\n",first->ch);
first=first->next;}
printf("%s\n",first->ch);
}
int main()
{
list_elem *first=(list_elem*)calloc(1,sizeof(list_elem));
first->next=NULL;
first->prev=NULL;
char a;
char ch[MAX_L];
printf("write ' 0 ' to end program.\n");
printf("write smth to add it to list: \n");
while(ch[0]!='0'){
scanf("%s",&ch);
add_to_list(first,ch);}
print_list(first);
return 0;
}
答案 0 :(得分:2)
list_elem *first=(list_elem*)calloc(1,sizeof(list_elem));
您如何知道calloc
是否成功?
检查first
是否为NULL
,然后才能访问first->next
。
while(ch[0]!='0')
直到这一点ch
数组包含垃圾。那么如何将ch[0]
与'0'
进行比较?
scanf("%s",&ch);
%s
期望char *
类型的参数,而&ch
的类型为char (*)[30]
。
如果用户输入长度为&gt;的字符串,您可能还想避免意外的缓冲区溢出。 sizeof(ch)
。指定最大字段宽度以解决此问题。
first=first->next;
中 print_list()
在这里你跳过了第一个元素。
if(first->ch==NULL)
你真的想在这做什么?很可能你想检查字符串first->ch
是否为空。如果是,那么不检查它的方式。而是检查first->ch[0] == '\0'
while(ch[0]!='0')
为了检查用户是否输入了0
或其他字符串,这是不正确的方法。这将拒绝从0
开始的字符串(例如&#34; 0bar&#34;)
正确的方法是:
while((ch[0]!='0') || (strlen(ch) > 1))
在列表
中插入new
节点后,跳出循环
if (strcmp(tmp->ch,new->ch)>0)
{
new->prev=tmp->prev;
new->next=tmp;
tmp->prev=new;
}
在插入new
节点后,if
表达式strcmp(tmp->ch,new->ch)>0
将在所有后续循环迭代中保持true
,因为我们无法更改tmp
和new
。所以这将导致无限循环。
唯一的例外是tmp
是最后一个节点。
解决方案:
在new
节点插入列表后立即退出循环。
只需将break;
写为上面strcmp
if
答案 1 :(得分:0)
在tmp
之前插入时,您似乎没有将tmp->prev->next
设置为new
为清楚起见:
if (strcmp(tmp->ch,new->ch)>0) //guess here should be inserted new element
{
new->prev=tmp->prev;
new->next=tmp;
tmp->prev=new;
}
应该是:
if (strcmp(tmp->ch,new->ch)>0) //guess here should be inserted new element
{
tmp->prev->next=new;
new->prev=tmp->prev;
new->next=tmp;
tmp->prev=new;
}
附注:使用new
作为变量名称通常不赞成,因为它不能立即识别为变量,因为大多数程序员都有Java / C#/ C ++等经验new
是关键字。
附注2:不要施展malloc
。直到最近我读到this堆栈线程时才这样做。这是一个非常好的阅读。
答案 2 :(得分:0)
add_to_list
循环中存在问题:
do {
if(tmp->next==NULL)
{
tmp->next=new;
new->prev=tmp;
new->next=NULL;
break; // you must exit here, you don't want to go the "if" below...
}
if (strcmp(tmp->ch,new->ch)>0)
{
if( tmp->prev != NULL )
{
tmp->prev->next = new; // link from previous to the new element
}
new->prev=tmp->prev;
new->next=tmp;
tmp->prev=new;
break; // you should exit here, work is done
}
else {
tmp=tmp->next;
}
} while (1); // try again
这里也有一个问题:
scanf("%s",&ch); // should be scanf("%s",ch);
对于你的问题:
我也怀疑“(strcmp(tmp-&gt; ch,new-&gt; ch)&gt; 0)”它正在工作 我在想什么?
如果你错了,你会按相反的顺序排序,所以它很容易修复。