c语言链表问题

Atlas~ 2019-12-26 10:46:01
学生选课系统中,建立链表时调用一个函数判断是否重复输入课程编号,这个函数要怎么写? 下面的图是自己写的,输出总是重复的
...全文
118 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
源代码大师 2021-05-06
  • 打赏
  • 举报
回复
希望对你有帮助:https://blog.csdn.net/it_xiangqiang/category_10581430.html 希望对你有帮助:https://blog.csdn.net/it_xiangqiang/category_10768339.html
Atlas~ 2019-12-27
  • 打赏
  • 举报
回复
这个功能基本都不能实现,改来改去总是有问题
Atlas~ 2019-12-27
  • 打赏
  • 举报
回复
#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();
}


自信男孩 2019-12-27
  • 打赏
  • 举报
回复
直接贴代码吧,可以帮你调一下~
Atlas~ 2019-12-27
  • 打赏
  • 举报
回复
引用 6 楼 自信男孩的回复:
楼主的代码里多处用到course的head,但是都是定义的局部变量head,还是没有初始化的head,直接用head->next这样会导致段错误的。

没办法我只能定义全局变量ghead,让其他函数里用ghead。这样改不好,函数之间的耦合很大。
部分函数我用了传参数(head)进去。

供参考吧。建议楼主对于代码架构多做一些努力~
谢谢你的帮助,我会努力的
Atlas~ 2019-12-27
  • 打赏
  • 举报
回复
我不知道要怎样给head初始化,我的思维不是很好,编程时感觉很乱,学起来也很吃力
自信男孩 2019-12-27
  • 打赏
  • 举报
回复
楼主的代码里多处用到course的head,但是都是定义的局部变量head,还是没有初始化的head,直接用head->next这样会导致段错误的。

没办法我只能定义全局变量ghead,让其他函数里用ghead。这样改不好,函数之间的耦合很大。
部分函数我用了传参数(head)进去。

供参考吧。建议楼主对于代码架构多做一些努力~
自信男孩 2019-12-27
  • 打赏
  • 举报
回复
#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("课程编号 课程名称 课程性质 总学
Atlas~ 2019-12-26
  • 打赏
  • 举报
回复
我知道了,应该是p->num==num

69,377

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧