user-0 提问: c语言链表问题

回复:
user: user-1
content: 希望对你有帮助：https://blog.csdn.net/it_xiangqiang/category_10581430.html 希望对你有帮助：https://blog.csdn.net/it_xiangqiang/category_10768339.html

user: user-0
content: 这个功能基本都不能实现，改来改去总是有问题

user: user-0
content: #include<stdio.h> #include<string.h> #include<stdlib.h>         //包含动态内存分配的函数 #include<windows.h>        //包含清屏函数  void menu();               //声明菜单函数 void course_information(); //声明课程信息录入函数 void student_information();//声明学生选课信息录入函数 void lcourse();            //声明课程信息浏览函数 void courseNo();           //声明按课程编号查询函数 void credit();             //声明按学分查询函数 void * malloc(unsigned int size);  void free(void *p); int is_exist(struct course *p,int num);            //声明判断是否存在的函数   void main()                //主函数 {   menu();                  //调用menu函数 }  void menu()                //定义菜单函数 { 	int n,a=1; 	while(a) 	{ 	  system("cls"); 	  printf("\n"); 	  printf("********************学生选修课程系统********************"); 	  printf("\n\n\n"); 	  printf("1.课程信息录入\n"); 	  printf("2.学生选课信息录入\n"); 	  printf("3.课程信息浏览\n"); 	  printf("4.按课程编号查询\n"); 	  printf("5.按学分查询\n"); 	  printf("0.退出系统\n"); 	  printf("请输入数字[0-6]:[ ]\b\b"); 	  scanf("%d",&n); 	  if(n<0||n>6)  a=1; 	  else a=0; 	}     switch(n) 	{ 		case 1: course_information();break; 		case 2: student_information();break; 		case 3: lcourse();break; 		case 4: courseNo();break; 		case 5: credit();break; 		case 0:	exit(0);  //退出 	} }   struct course        //声明课程结构体 {   int num;           //课程编号   char name[20];     //课程名称   char chara[10];    //课程性质   int ttime;         //总学时   int stime;         //授课学识   int ptime;         //实验学时   float credit;      //学分   int term;          //开课学期   struct course *next;//指向结构体变量的指针 };  struct student {   int number;         //学生学号   int c[20];          //课程编号    float total;        //总学分 };   struct course *creatcourse()    //建立课程单链表的函数 {     struct course *head,*tail,*p;  //定义指向结构体变量的指针变量     int num,ttime,stime,ptime,term,n;  	float credit;     char name[20],chara[10];       int size=sizeof(struct course);//将返回的结构体变量的大小赋值给size     head=tail=NULL;  //先使head的值为0，这是链表为空时的情况，head不指向任何结点，即链表无结点     printf("请输入课程编号:");  //数据域成员的输入     scanf("%d",&num);       getchar();     printf("请输入课程名:");       scanf("%s",name);       getchar();       printf("请输入课程性质:");       scanf("%s",chara);       getchar();       printf("请输入总学时:");       scanf("%d",&ttime);       printf("请输入授课学时:");       scanf("%d",&stime);     getchar();     printf("请输入实验学时:");       scanf("%d",&ptime);       getchar();     printf("请输入学分:");       scanf("%f",&credit);       getchar();     printf("请输入开课学期:");       scanf("%d",&term);       getchar();      while(1){  //循环，不断加入新结点         p=(struct course *)malloc(size);  //为新结点开辟动态储存区，把起始地址赋值给p，p所指向的结点就是链表中的第一个结点         p->num=num;              //将输入的数据赋值给p指向的结构体变量         strcpy(p->name,name);           strcpy(p->chara,chara);           p->ttime=ttime;           p->stime=stime;           p->ptime=ptime;           p->credit=credit;           p->term=term;           p->next=NULL;  //指向下一个结点的指针变量为空         if(head==NULL)  //判断新结点是否为头节点             head=p;  //使head指向新开辟的结点，即将第一个结点作为表头         else               tail->next=p;  //尾节点指向新创立的节点         tail=p;  //指向尾节点的指针也指向该节点         do{           printf("请输入课程编号:");           scanf("%d",&num);           n=is_exist(head,num);  //判断课程编号是否存在         if(n==1)               break;           else               printf("您输入的编号已存在,请重新输入!\n");       }while(1);          if(num==0)   //直到新结点的数据成员num为0时跳出循环             break;           else           {   			printf("请输入课程名:");   			scanf("%s",name);   			getchar();   			printf("请输入课程性质:");   			scanf("%s",chara);   			getchar();   			printf("请输入总学时:");   			scanf("%d",&ttime);             getchar(); 			printf("请输入授课学时:");   			scanf("%d",&stime);  			getchar(); 		 			printf("请输入实验学时:");   			scanf("%d",&ptime);  			getchar();  			printf("请输入学分:");   			scanf("%f",&credit);   			getchar();  			printf("请输入开课学期:");   			scanf("%d",&term);              getchar();          }       }       return head;   }    //单链表的插入   struct course *addcourse()   {       struct course *head;     struct course *ptr,*p1,*p2,*p;       char name[20],chara[10];     int size=sizeof(struct course);       int num,ttime,stime,ptime,term,n;  	float credit;     do{           printf("请输入课程编号:");           scanf("%d",&num);           n=is_exist(head,num);           if(n==1)               break;           else               printf("您输入的编号已存在,请重新输入!\n");       }while(1);       printf("请输入课程名:");   	scanf("%s",name);   	getchar();   	printf("请输入课程性质:");   	scanf("%s",chara);   	getchar();   	printf("请输入总学时:");   	scanf("%d",&ttime);     getchar(); 	printf("请输入授课学时:");   	scanf("%d",&stime);  	getchar(); 		 	printf("请输入实验学时:");   	scanf("%d",&ptime);  	getchar();  	printf("请输入学分:");   	scanf("%f",&credit);   	getchar();  	printf("请输入开课学期:");   	scanf("%d",&term);      getchar();      p=(struct course *)malloc(size);       p->num=num;       strcpy(p->name,name);       strcpy(p->chara,chara);       p->ttime=ttime;       p->stime=stime;       p->ptime=ptime;       p->credit=credit;       p->term=term;      p2=head;       ptr=p;       while((ptr->num > p2->num)&&(p2->next!=NULL)){           p1=p2;           p2=p2->next;       }       if(ptr->num <= p2->num){           if(head==p2)  //表头插入             head=ptr;           else{         //表中插入             p1->next=ptr;               p->next=p2;           }       }       else{  //表尾插入         p2->next=ptr;           p->next=NULL;       }       return head;   }   //单链表的删除 struct course *deletecourse() {   struct course *head,*p,*pdel;   int size=sizeof(struct course);     int num;    printf("请输入要删除的课程编号:");   scanf("%d",&num);   if(head==NULL)   {     printf("链表为空，不需要做删除操作!\n"); 	return head;   }   if(head->num==num)  //如果删除的节点为表头节点   {     p=head;//p指向表头结点 	head=head->next;//把下一节点作为新的表头节点 	printf("编号为%d的课程已被删掉!\n",p->num); 	free(p); 	return head;   }   for(p=head;p->next!=NULL;p=p->next)//利用循环查找   {     if(p->next->num==num)//当当前节点的下一节点等于给定的值时，则下一节点就是要删除的节点 	{ 	  pdel=p->next;//pdel指向要删除的节点 	  p->next=pdel->next;//p指向要删除的节点的下一节点 	  printf("编号为%d的课程已被删掉!/n",pdel->num); 	  free(pdel);//删除结构指针pdel指向的节点 	  return head; 	}   }   printf("链表中没有为该编号的课程!\n");   return head; }    //单链表的查找  按课程编号 struct course *searchcourse1() {   struct course *head;   struct course *p=head->next;   int num;   printf("请输入要查询的课程编号:");   scanf("%d",&num);   getchar();   while(p!=NULL&&p->num!=num) 	  p=p->next;   if(p==NULL)   {     printf("找不到符合条件的课程"); 	return NULL;   }   if(p->num==num)   {   	 printf("找到符合条件的课程\n"); 	 printf("课程名为:%s\n",p->name);        printf("课程性质为:%s\n",p->chara);   	 printf("总学时为:%d\n",p->ttime);   	 printf("授课学时为:%d\n",p->stime);        printf("实验学时为:%d\n",p->ptime);        printf("学分为:%f",p->credit);        printf("开课学期为:%d\n",p->term);    }   return p; }   //按学分查找 struct course *searchcourse2() {   struct course *head;   struct course *p=head->next;   int credit;   printf("请输入要查询的课程学分:\n");   scanf("%d",&credit);   if(p==NULL)   {     printf("找不到符合条件的课程"); 	return NULL;   }   for(;p->credit==credit&&p!=NULL;p=p->next)   {   	 printf("找到符合条件的课程\n"); 	 printf("课程编号为:%d\n",p->num); 	 printf("课程名为:%s\n",p->name);        printf("课程性质为:%s\n",p->chara);   	 printf("总学时为:%d\n",p->ttime);   	 printf("授课学时为:%d\n",p->stime);        printf("实验学时为:%d\n",p->ptime);        printf("开课学期为:%d\n",p->term);    }   return p; }     int is_exist(struct course *head,int num)//判断是否重复输入 {   int n=1;   struct course *p;   for(p=head;p;p=p->next)   {       if(p->num==num)       {           n=0;           break;       }   }   return n; }     void course_information() {   struct course *pt;   int b;   char password[5]="1234";   char s[6];   do   { 	  printf("请输入管理员密码:"); 	  scanf("%s",s); 	  if(!strcmp(s,password)) 	  { 		break; 	  } 	  else 	  { 		printf("密码出错!\n"); 	  }   }while(1);   printf("\n\n");   printf("*********************课程信息录入********************\n");   printf("1录入课程            2添加课程              3删除课程\n");   scanf("%d",&b);   getchar();   switch(b)   {   case 1:pt=creatcourse();break;   case 2:pt=addcourse();break;   case 3:pt=deletecourse();break;   }   printf("操作完成!返回菜单\n");   menu(); }   void student_information() {   struct course *p,*head;   int number,num,i=0;   int c[20];   float total=0;   printf("********************学生选课信息录入********************\n");   printf("**********学号:[ ]\b\b");   scanf("%d",&number);   getchar();   while(total<60)   { 	  printf("输入要选择的课程编号\n"); 	  scanf("%d",&num); 	  getchar(); 	  while(num!=0) 	  { 		for(p=head;p;p=p->next) 			if(p->num==num) 			{ 			  total=total+p->credit; 			  c[i]=num;//将选择的课程编号存放在数组中 			  i++; 			} 			scanf("%d",&num); 	  }     }   if(total<60)   {     printf("选修总学分为%d未达到60，选修失败!\n",total); 	system("pause");   }   else   { 	printf("选课成功!\n");   }   system("pause"); }   void lcourse() {   struct course *p,*head;   p=head;   if(p==NULL)   {     printf("无课程信息\n"); 	return;   }   printf("***************************欢迎浏览************************\n");   printf("\n\n");   printf("课程编号     课程名称      课程性质     总学时     授课学时     实验学时     学分     开课学期\n");   for(;p;p=p->next)	   {     printf("%5d%10s%10s%10d%10d%10d%10d%10f%5d\n",p->num,p->name,p->chara,p->ttime,p->stime,p->ptime,p->credit,p->term);//输出链表   }   system("pause"); }  void courseNo() {   struct course *pt;   pt=searchcourse1();   printf("操作完成!返回菜单\n");   menu(); }  void credit() {   struct course *pt;   pt=searchcourse2(); }

user: user-2
content: 直接贴代码吧，可以帮你调一下～

user: user-0
content: 引用 6 楼 自信男孩的回复:楼主的代码里多处用到course的head，但是都是定义的局部变量head，还是没有初始化的head，直接用head->next这样会导致段错误的。  没办法我只能定义全局变量ghead，让其他函数里用ghead。这样改不好，函数之间的耦合很大。 部分函数我用了传参数(head)进去。  供参考吧。建议楼主对于代码架构多做一些努力～ 谢谢你的帮助，我会努力的

user: user-0
content: 我不知道要怎样给head初始化，我的思维不是很好，编程时感觉很乱，学起来也很吃力

user: user-2
content: 楼主的代码里多处用到course的head，但是都是定义的局部变量head，还是没有初始化的head，直接用head->next这样会导致段错误的。  没办法我只能定义全局变量ghead，让其他函数里用ghead。这样改不好，函数之间的耦合很大。 部分函数我用了传参数(head)进去。  供参考吧。建议楼主对于代码架构多做一些努力～

user: user-2
content: #include<stdio.h> #include<string.h> #include<stdlib.h>         //包含动态内存分配的函数 //#include<windows.h>        //包含清屏函数  void menu();               //声明菜单函数 void course_information(); //声明课程信息录入函数 void student_information();//声明学生选课信息录入函数 void lcourse();            //声明课程信息浏览函数 void courseNo();           //声明按课程编号查询函数 void credit();             //声明按学分查询函数 //void * malloc(unsigned int size); void free(void *p); int is_exist(struct course *p,int num);            //声明判断是否存在的函数  struct course *ghead;  //void main()                //主函数 int main()                //主函数 {     menu();                  //调用menu函数 }  void menu()                //定义菜单函数 {     int n,a=1;     while(a)     {         system("cls");         printf("\n");         printf("********************学生选修课程系统********************");         printf("\n\n\n");         printf("1.课程信息录入\n");         printf("2.学生选课信息录入\n");         printf("3.课程信息浏览\n");         printf("4.按课程编号查询\n");         printf("5.按学分查询\n");         printf("0.退出系统\n");         printf("请输入数字[0-6]:[ ]\b\b");         scanf("%d",&n);         if(n<0 || n>6)             a=1;         else             a=0;     }     switch(n)     {         case 1: course_information();break;         case 2: student_information();break;         case 3: lcourse();break;         case 4: courseNo();break;         case 5: credit();break;         case 0: exit(0);  //退出     } }   struct course        //声明课程结构体 {     int num;           //课程编号     char name[20];     //课程名称     char chara[10];    //课程性质     int ttime;         //总学时     int stime;         //授课学识     int ptime;         //实验学时     float credit;      //学分     int term;          //开课学期     struct course *next;//指向结构体变量的指针 };  struct student {     int number;         //学生学号     int c[20];          //课程编号     float total;        //总学分 };   struct course *creatcourse()    //建立课程单链表的函数 {     //struct course *head,*tail,*p;  //定义指向结构体变量的指针变量     struct course *tail,*p;  //定义指向结构体变量的指针变量     int num,ttime,stime,ptime,term,n;     float credit;     char name[20],chara[10];     int size=sizeof(struct course);//将返回的结构体变量的大小赋值给size     //head=tail=NULL;  //先使head的值为0，这是链表为空时的情况，head不指向任何结点，即链表无结点     printf("请输入课程编号:");  //数据域成员的输入     scanf("%d",&num);     getchar();     printf("请输入课程名:");     scanf("%s",name);     getchar();     printf("请输入课程性质:");     scanf("%s",chara);     getchar();     printf("请输入总学时:");     scanf("%d",&ttime);     printf("请输入授课学时:");     scanf("%d",&stime);     getchar();     printf("请输入实验学时:");     scanf("%d",&ptime);     getchar();     printf("请输入学分:");     scanf("%f",&credit);     getchar();     printf("请输入开课学期:");     scanf("%d",&term);     getchar();     while(1){  //循环，不断加入新结点         p=(struct course *)malloc(size);  //为新结点开辟动态储存区，把起始地址赋值给p，p所指向的结点就是链表中的第一个结点         p->num=num;              //将输入的数据赋值给p指向的结构体变量         strcpy(p->name,name);         strcpy(p->chara,chara);         p->ttime=ttime;         p->stime=stime;         p->ptime=ptime;         p->credit=credit;         p->term=term;         p->next=NULL;  //指向下一个结点的指针变量为空         if(ghead==NULL)  //判断新结点是否为头节点             ghead=p;  //使head指向新开辟的结点，即将第一个结点作为表头         else             tail->next=p;  //尾节点指向新创立的节点         tail=p;  //指向尾节点的指针也指向该节点         do {             printf("请输入课程编号:");             scanf("%d",&num);             n = is_exist(ghead,num);  //判断课程编号是否存在             if(n == 1)                 break;             else                 printf("您输入的编号已存在,请重新输入!\n");         } while(1);         if(num==0)   //直到新结点的数据成员num为0时跳出循环             break;         else         {             printf("请输入课程名:");             scanf("%s",name);             getchar();             printf("请输入课程性质:");             scanf("%s",chara);             getchar();             printf("请输入总学时:");             scanf("%d",&ttime);             getchar();             printf("请输入授课学时:");             scanf("%d",&stime);             getchar();             printf("请输入实验学时:");             scanf("%d",&ptime);             getchar();             printf("请输入学分:");             scanf("%f",&credit);             getchar();             printf("请输入开课学期:");             scanf("%d",&term);             getchar();         }     }     return ghead; }  //单链表的插入 struct course *addcourse(struct course *head) {      struct course *ptr,*p1,*p2,*p;     char name[20],chara[10];     int size=sizeof(struct course);     int num,ttime,stime,ptime,term,n;     float credit;     do{         printf("请输入课程编号:");         scanf("%d",&num);         n = is_exist(head,num);         if(n==1)             break;         else             printf("您输入的编号已存在,请重新输入!\n");     }while(1);     printf("请输入课程名:");     scanf("%s",name);     getchar();     printf("请输入课程性质:");     scanf("%s",chara);     getchar();     printf("请输入总学时:");     scanf("%d",&ttime);     getchar();     printf("请输入授课学时:");     scanf("%d",&stime);     getchar();     printf("请输入实验学时:");     scanf("%d",&ptime);     getchar();     printf("请输入学分:");     scanf("%f",&credit);     getchar();     printf("请输入开课学期:");     scanf("%d",&term);     getchar();     p=(struct course *)malloc(size);     p->num=num;     strcpy(p->name,name);     strcpy(p->chara,chara);     p->ttime=ttime;     p->stime=stime;     p->ptime=ptime;     p->credit=credit;     p->term=term;     p2=head;     ptr=p;     while((ptr->num > p2->num)&&(p2->next!=NULL)){         p1=p2;         p2=p2->next;     }     if(ptr->num <= p2->num){         if(head==p2)  //表头插入             head=ptr;         else{         //表中插入             p1->next=ptr;             p->next=p2;         }     }     else{  //表尾插入         p2->next=ptr;         p->next=NULL;     }      return head; }   //单链表的删除 struct course *deletecourse(struct course *head) {     //struct course *head,*p,*pdel;     struct course *p,*pdel;     //int size=sizeof(struct course);     int num;     printf("请输入要删除的课程编号:");     scanf("%d",&num);     if(head==NULL)     {         printf("链表为空，不需要做删除操作!\n");         return head;     }     if(head->num==num)  //如果删除的节点为表头节点     {         p=head;//p指向表头结点         head=head->next;//把下一节点作为新的表头节点         printf("编号为%d的课程已被删掉!\n",p->num);         free(p);         return head;     }     for(p=head;p->next!=NULL;p=p->next)//利用循环查找     {         if(p->next->num==num)//当当前节点的下一节点等于给定的值时，则下一节点就是要删除的节点         {             pdel=p->next;//pdel指向要删除的节点             p->next=pdel->next;//p指向要删除的节点的下一节点             printf("编号为%d的课程已被删掉!/n",pdel->num);             free(pdel);//删除结构指针pdel指向的节点             return head;         }     }     printf("链表中没有为该编号的课程!\n");     return head; }    //单链表的查找  按课程编号 struct course *searchcourse1() {     //struct course *head;     //struct course *p=head->next;     struct course *p = ghead->next;     int num;     printf("请输入要查询的课程编号:");     scanf("%d",&num);     getchar();     while(p!=NULL&&p->num!=num)         p=p->next;     if(p==NULL)     {         printf("找不到符合条件的课程");         return NULL;     }     if(p->num==num)     {         printf("找到符合条件的课程\n");         printf("课程名为:%s\n",p->name);         printf("课程性质为:%s\n",p->chara);         printf("总学时为:%d\n",p->ttime);         printf("授课学时为:%d\n",p->stime);         printf("实验学时为:%d\n",p->ptime);         printf("学分为:%f",p->credit);         printf("开课学期为:%d\n",p->term);     }     return p; }   //按学分查找 struct course *searchcourse2() {     //struct course *head;     struct course *p = ghead->next;     int credit;     printf("请输入要查询的课程学分:\n");     scanf("%d",&credit);     if(p==NULL)     {         printf("找不到符合条件的课程");         return NULL;     }     for(;p->credit==credit&&p!=NULL;p=p->next)     {         printf("找到符合条件的课程\n");         printf("课程编号为:%d\n",p->num);         printf("课程名为:%s\n",p->name);         printf("课程性质为:%s\n",p->chara);         printf("总学时为:%d\n",p->ttime);         printf("授课学时为:%d\n",p->stime);         printf("实验学时为:%d\n",p->ptime);         printf("开课学期为:%d\n",p->term);     }     return p; }     int is_exist(struct course *head,int num)//判断是否重复输入 {     int n=1;     struct course *p;      for(p=head;p;p=p->next)     {         if(p->num==num)         {             n=0;             break;         }     }      return n; }     void course_information() {     struct course *pt = ghead;     int b;     char password[5]="1234";     char s[6];     do     {         printf("请输入管理员密码:");         scanf("%s",s);         if(!strcmp(s,password))         {             break;         }         else         {             printf("密码出错!\n");         }     }while(1);     printf("\n\n");     printf("*********************课程信息录入********************\n");     printf("1录入课程            2添加课程              3删除课程\n");     scanf("%d",&b);     getchar();     switch(b)     {         case 1:pt=creatcourse();break;         case 2:pt=addcourse(pt);break;         case 3:pt=deletecourse(pt);break;     }     printf("操作完成!返回菜单\n");     menu(); }   void student_information() {     struct course *p;//,*head;     int number,num,i=0;     int c[20];     float total=0;      printf("********************学生选课信息录入********************\n");     printf("**********学号:[ ]\b\b");     scanf("%d",&number);     getchar();     while(total<60)     {         printf("输入要选择的课程编号\n");         scanf("%d",&num);         getchar();         while(num!=0)         {             for(p=ghead;p;p=p->next)                 if(p->num==num)                 {                     total=total+p->credit;                     c[i]=num;//将选择的课程编号存放在数组中                     i++;                 }             scanf("%d",&num);         }     }     if(total<60)     {         //printf("选修总学分为%d未达到60，选修失败!\n", total);         printf("选修总学分为%f未达到60，选修失败!\n", total);         system("pause");     }     else     {         printf("选课成功!\n");     }     system("pause"); }   void lcourse() {     struct course *p;//,*head;     //p = head;     p = ghead;     if(p==NULL)     {         printf("无课程信息\n");         return;     }     printf("***************************欢迎浏览************************\n");     printf("\n\n");     printf("课程编号     课程名称      课程性质     总学

user: user-0
content: 我知道了，应该是p->num==num