C语言 编写单链表所遇到的若干问题和易犯的错误

使用C语言实现单链表的创建,删除,添加。
所遇到问题:
1、 Node head;
head->next=NULL;
这个没有分配地址,直接使用 head->next,会导致程序崩溃
。同样的问题,在创建删除的函数是又同样遇到,例如while(p!=NULL&&p->id!=id),若是先判断p->id!=id,则会导致程序崩溃。为什么?其原因是当p指向NULL时,p->id!=id会导致程序崩溃。
解决方案:先判断是否为空,再判断p->id!=id。
2、free()仅仅是将指针所指地址回收,实质是指针所指的地址还在,只是其中内容不再保护,地址中的值会出现各种内容,为了规范和避免引起不必要的麻烦,则需要将指针置空。
3、二级指针,函数参数中使用二级指针,如 void deleteEmun(Node
* head,int id),一般的如果在自定义的函数中没有使用malloc()函数,即形参指针指向malloc所定义的节点,而不是指向实参所传的地址,这时候就需要使用二级指针。当然,如果是返回值是指针的函数,则不需要二级指针,返回值返回函数内定义好的指针即可。

typedef struct{
 int id;
 char name[5];
 double scores;
 struct Node *next;
}Node; 

int main(int argc, char *argv[])
{ 
 /**
  注意:指针若指向未分配的地址会导致崩溃 
  
  Node *head;
  head->next=NULL;
  这是典型错误,没有分配内存,head->next=NULL会导致运行崩溃 
  这个错误困扰我很久 
 */
 Node *head = (Node*)malloc(sizeof(Node));
 Node *p,*q,*rear;
 int id;
 
 head->next=NULL;
 printf("head->next=%d\n",head->next);
 head=create(head);
 
 p=head->next;
 printf("\n\np=%d  (p=head->next)\n",p);
 
 printf("\n-----------------头插法元素遍历----------------\n");//分割线
 printf("学号\t姓名\t成绩\t地址\t"); 
 while(p!=NULL){
  printfNode(p);
  p=p->next; 
  //rear=p;
//  printf("\nrear的地址是%d\n",rear);
 }
 
 printf("\n-----------------删除元素----------------\n"); 
 printf("\n输入需要删除元素的ID:\n");
 scanf("%d",&id);
 deleteEmun(&head,id);
 q=head->next;
 while(q!=NULL){
  printfNode(q);
  q=q->next; 
 
 }
 
 printf("\n----------------插入元素(头插法)-----------------\n");//分割线
 insert(head);
 
 printf("\n学号\t姓名\t成绩\t地址\t"); 
 p=head->next;
 while(p!=NULL){
  printfNode(p);
  p=p->next; 
 }
 printf("\n---------------------------------\n");//分割线
 
 return 0;
}



```c
Node* create(Node* head){
 printf("\n----------------初始化(头插法)-----------------\n");//分割线
 
 int i;
 for(i=0;i<10;i++){
  Node *p = (Node*)malloc(sizeof(Node));
  p->id=createRandomID(p);
  createRandomName(&p);
  printfNode(p);
  
  p->next=head->next;
  head->next=p;
 }
 return head;
 
}
/**
以节点的地址为随机数的种子。如果以时间为随机数的种子,那么在for循环中CPU运算速度快,则会导随机产生的ID和姓名都一样
*/
int createRandomID(Node* p){//在创建单链表时,随机生成节点中属性的ID
 int a ;
// time_t timer;
 srand((int)p);
 a = rand()%100;
 return a;
}

void createRandomName(Node** p){//在创建单链表时,随机生成节点中属性的名字
 int i;
// time_t timer;
 srand((int)(*p));
 (*p)->name[0]=rand()%26+66;
 for(i=1;i<5;i++){
  (*p)->name[i] = rand()%26+97;
 } 
}
Node* insert(Node* head){ 
 
 Node *p = (Node*)malloc(sizeof(Node));
 
 
 printf("请输入学生的学号  姓名  成绩 \n");
 scanf("%d%s%lf",&p->id,&p->name,&p->scores);
 
 p->next=head->next;
 head->next=p;
 return head;
 
} ``

void deleteEmun(Node** head,int id){
	printf("\n所要删除的元素的id:%d\n",id);
	Node *p = (*head)->next;
 	Node *pre=*head;   //这是指向p的前一个指针 
 	while(p!=NULL&&p->id!=id){
 	printf("\np:   %d\tp->next:    %d\n",p,p->next);
 	pre=p; 
  	p=p->next;
  	}
	 if(p!=NULL&&p->id==id){
  		pre->next=p->next;
 		 printf("\n未free(p)前p的地址:%d\n",p);
  		free(p);
 		 printf("free(p)后p的地址:%d\n",p);
  		p=NULL;
 		 printf("free(p)和p=NULL后p的地址:%d\n",p); 
 	}else{
  		printf("没有该ID"); 
 		 exit(0);
	 }
 }
 
void printfNode(Node* p){
 printf("\n%d\t%s\t%6.1lf\t%d\t",p->id,p->name,p->scores,p);
}


发布了9 篇原创文章 · 获赞 0 · 访问量 92

猜你喜欢

转载自blog.csdn.net/ren_x_guo/article/details/104713675
今日推荐