// C语言程序设计实验与习题指导
// 实验八 结构体、共用体、枚举类型
// P52 二
// 1)
编写程序:输入某个日期的年月日,计算并输出第二天的年月日,以及它在该年中是第几天。掌握结构体变量的定义与使用。要求:用结构体类型变量存放年月日:考虑闰年的情况。
#include
//包含头文件,主要是输入输出函数
struct date//定义日期类型结构体
{
int yy,mm,dd;//分别定义年-yy、月-mm、日-dd
};
void main() //空类型主函数
{
struct date day;//定义日期变量-day
int i,flag=0,days=0;
//定义循环变量-i,闰年标志-flg,某日在该年中第几天-days
int
month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//非闰年时每个月天数,为保持月份数与数组下标数一致,数组长度定义为13,第0个数组元素不用,用month[1]表示第一月天数,month[2]表示第二月天数...以此类推
do{
printf("Please input a
date(year month day):\n");//提示 请输入一个日期,包括年月日
scanf("%d%d%d",&day.yy,&day.mm,&day.dd);//输入某一日期的年、月、日
if(((day.yy%4==0)&&(day.yy%100!=0))||(day.yy%400==0))
//某年如果能被4整除并且不能被100整除或者能被400整除,则为闰年
flag=1;//闰年标记置为1,表示该年为闰年;否则保持为初始设置的0,表示该年不为闰年
else
flag=0;//否则闰年标记置为0
if(flag)//如果该年为闰年
month[2]=29;//第二月份天数为29天
}while(day.yy<0||day.mm<1||day.mm>12||day.dd<1||(day.mm!=2&&day.dd>month[day.mm])||(day.mm==2&&flag==0&&day.dd>28)||(day.mm==2&&flag==1&&day.dd>29));//要求输入的数据满足一定的条件,那就是年份大于0,月份在1~12之间,日期不超过该月最大天数且大于0
//计算第二天的日期
day.dd+=1;//首先将日子加一天
if(day.dd>month[day.mm])//如果增加后的日子大于该月最大天数
{
day.dd=1;//该月天数归一
day.mm+=1;//月份加一
}
if(day.mm>12)//如果月份大于12
{
day.mm=1;//月份归一
day.yy+=1;//年份加一
}
printf("\n\nThe next day is
%d-%d-%d.\n\n",day.yy,day.mm,day.dd);//输出第二天的日期
if(((day.yy%4==0)&&(day.yy%100!=0))||(day.yy%400==0))
//某年如果能被4整除并且不能被100整除或者能被400整除,则为闰年
flag=1;//闰年标记置为1,表示该年为闰年;否则保持为初始设置的0,表示该年不为闰年
else
flag=0;//否则闰年标记置为0
if(flag)//如果该年为闰年
month[2]=29;//第二月份天数为29天
for(i=1;i
days+=month[i];//依次加上该日期前所有月份天数
days+=day.dd;//再加上该日子
printf("The next day %d-%d-%d is the %d-th day
of the year.\n\n",day.yy,day.mm,day.dd,days);//输出该日期是该年中的第几天
}
//
2)编写程序:有10个学生,每个学生的数据包括学号、姓名、3门课的成绩,从键盘输入这10个学生的数据,要求输出三门课程的
// 总平均成绩,并按总分从高到低输出所有学生的各数据项(学号、姓名、3门课的成绩及平均分)。掌握结构体数组的定义、使用,
//
学会使用结构体数组作函数参数,复习函数的定义、调用及排序算法。要求;用input函数输入10个学生的数据;用average函数求
// 三门课程的总平均成绩;用sort函数按总分高低进行排序;所有的数据输出都在主函数中进行。
#include
#define SN 3 //学生数 10
#define CN 3 //课程数 3
//定义学生结构体
struct student
{
long Num;//学号
char Name[10];//姓名
double Score[CN];//CN门课的成绩
double AveSc;//CN门课的平均成绩
};
//输入10个学生的数据
void input(struct student *stu)
{
int i,j;
double sCN;
printf("请输入%d个学生的学号、姓名、%d门课的成绩:\n\n",SN,CN);
for(i=0;i
{
sCN=0.0;
scanf("%ld%s",&stu[i].Num,stu[i].Name);
for(j=0;j
{
scanf("%lf",&stu[i].Score[j]);
sCN+=stu[i].Score[j];
}
stu[i].AveSc=sCN/CN;
}
}
//求三门课程的总平均成绩
void average(struct student *stu,double *ave,double *ave3)
{
int i,j;
double sum[CN],s3=0.0;
for(i=0;i
{
sum[i]=0.0;
for(j=0;j
{
sum[i]+=stu[j].Score[i];
s3+=stu[j].Score[i];
}
ave[i]=sum[i]/SN;
}
*ave3=s3/(SN*CN); }
//按总分高低进行排序,与按平均分高低进行排序等价
void sort(struct student *stu)
{
int i,j,k;
struct student st;
for(i=0;i
{
k=i;
for(j=i+1;j
{
if(stu[j].AveSc>stu[k].AveSc)
k=j;
}
if(k!=i)
{
st=stu[i];
stu[i]=stu[k];
stu[k]=st;
}
}
}
void main()
{
int i,j,k;
double ave[CN],aveT;
struct student stu[SN];
input(stu);
average(stu,ave,&aveT);
sort(stu);
printf("学生的学号 姓名 三门课成绩 三门课平均成绩
如下:\n\n");
for(i=0;i
{
printf("%ld %s ",stu[i].Num,stu[i].Name);
for(j=0;j
{
printf("%.1f
",stu[i].Score[j]);
}
printf("%.3f
\n",stu[i].AveSc);
}
printf("三门课的总平均成绩为%.3f\n\n",aveT);
for(k=0;k
{
printf("第%d门课的平均成绩为%.3f\n",k+1,ave[k]);
}
}
// 3)编写程序:建立一个链表,每个结点包括课程名、学分数。输入一门课程的名称,在链表中查找是否有这门课,若未找到,则
// 从键盘输入该课程的学分数,将这门课插入到链表的尾部,然后输出修改后链表各结点的数据。学会链表的建立、查找、插入等
//
基本操作。要求:函数create输入6门课程及学分,建立链表;函数print输出链表的各结点;函数find查找某课程,若找到,返回
//
指向该结点的指针变量,否则返回NULL;函数insert将新结点插入到链表的最后,返回链表的头指针;主函数中先调用create函数
//
和print函数;然后输入要查找的课程名,调用find函数后,若找到,输出相关信息;否则输入学分数,调用insert函数,将该课程
// 插入到链表中;最后调用print函数,输出插入后的链表。
#include
#include
#define CN 6//课程数 6
struct course//课程结构体
{
char Cname[20];//课程名
double Credit;//学分数
struct course *next;//指向下一课程结点的指针
};
//函数create输入6门课程及学分,建立链表
struct course *create(int n)
{
int i;
char name[20];
double credit;
struct course *head=NULL,*pnew,*ptail;
for(i=1;i<=n;i++)
{
pnew=(struct course
*)malloc(sizeof(struct course));
printf("请输入一个课程名和学分数:\n");
scanf("%s%lf",name,&credit);
strcpy(pnew->Cname,name);
pnew->Credit=credit;
if(head==NULL)
head=ptail=pnew;
else
{
ptail->next=pnew;
ptail=pnew;
}
}
ptail->next=NULL;//尾结点
return head;
}
//函数print输出链表的各结点
void print(struct course *head)
{
struct course *p=head;
printf("课程名 学分:\n\n");
while(p!=NULL)
{
printf("%s %.1f
\n",p->Cname,p->Credit);
p=p->next;
}
}
//函数find查找某课程,若找到,返回指向该结点的指针变量,否则返回NULL
struct course *find(struct course *head,char *name,struct course
*ps)
{
struct course *p=head;
while(p!=NULL&&(strcmp(p->Cname,name)!=0))
{
p=p->next;
}
if(p!=NULL)
{
ps=p;
return ps;
}
else
return NULL;
}
//函数insert将新结点插入到链表的最后,返回链表的头指针
struct course *insert(struct course *head,struct course
*pnew)
{
struct course *p,*pb;
p=pb=head;
if(head==NULL)
head=pnew;
else
{
while(p!=NULL)
{
pb=p;
p=p->next;
}
pb->next=pnew;
pb=pnew;
pb->next=NULL;
}
return head;
}
//建立一个链表,每个结点包括课程名、学分数。输入一门课程的名称,在链表中查找是否有这门课,若未找到,则
// 从键盘输入该课程的学分数,将这门课插入到链表的尾部,然后输出修改后链表各结点的数据。
void main()
{
int i;
char cname[20];
double credit;
struct course *head,*ps,*pc;
head=create(CN);
ps=pc=(struct course *)malloc(sizeof(struct
course));
printf("请输入一门课的名称:\n");
scanf("%s",cname);
strcpy(pc->Cname,cname);
if(find(head,cname,ps)==NULL)
{
printf("请输入该门课的学分:\n");
scanf("%lf",&credit);
pc->Credit=credit;
pc->next=NULL;
}
head=insert(head,pc);
print(head);
}
// 4)
编写程序:建立一个链表,每个结点包括职工号、职工姓名、工资。从键盘输入工资salary,要求将链表中工资低于salary的结点
//
全部删除,并输出修改后的链表。学会链表的建立、删除等基本操作。要求:用函数create输入6名职工及信息,建立链表;用函数
//
print输出链表的各结点;用函数delete完成结点的删除;主函数中先调用create函数和print函数;然后输入工资salary,调用delete
// 函数删除结点;调用print函数,将删除后的链表输出。
#include
#include
#define WN 3//职工数 6
struct worker//职工结构体
{
long Wnum;//职工号
char Wname[20];//职工姓名
double Salary;//工资
struct worker *next;//指向下一职工结点的指针
};
//函数create输入6名职工及信息,建立链表
struct worker *create(int n)
{
int i;
long num;
char name[20];
double salary;
struct worker *head=NULL,*pnew,*ptail;
for(i=1;i<=n;i++)
{
pnew=(struct worker
*)malloc(sizeof(struct worker));
printf("请输入一个职工号、职工姓名和工资:\n");
scanf("%ld%s%lf",&num,name,&salary);
pnew->Wnum=num;
strcpy(pnew->Wname,name);
pnew->Salary=salary;
if(head==NULL)
head=ptail=pnew;
else
{
ptail->next=pnew;
ptail=pnew;
}
}
ptail->next=NULL;//尾结点
return head;
}
//函数print输出链表的各结点
void print(struct worker *head)
{
struct worker *p=head;
printf("职工号 职工姓名 工资:\n\n");
while(p!=NULL)
{
printf("%ld %s %.1f
\n",p->Wnum,p->Wname,p->Salary);
p=p->next;
}
}
//函数find查找某职工,若找到,返回指向该结点的指针变量,否则返回NULL
struct worker *find(struct worker *head,double salary,struct worker
*ps)
{
struct worker *p=head;
while(p!=NULL&&(p->Salary!=salary))
{
p=p->next;
}
if(p!=NULL)
{
ps=p;
return ps;
}
else
return NULL;
}
//函数insert将新结点插入到链表的最后,返回链表的头指针
struct worker *insert(struct worker *head,struct worker
*pnew)
{
struct worker *p,*pb;
p=pb=head;
if(head==NULL)
head=pnew;
else
{
while(p!=NULL)
{
pb=p;
p=p->next;
}
pb->next=pnew;
pb=pnew;
pb->next=NULL;
}
return head;
}
//用函数delete完成结点的删除
struct worker *deletew(struct worker *head,double salary)
{
struct worker *p=head,*pold=head;
//删除满足指定条件的链表头部的连续若干节点
p=head;
while(head!=NULL&&head->Salary
{
head=head->next;
printf("%.3f has been deleted!
\n\n",p->Salary);
free(p);
p=head;
}
if(head==NULL)
return head;
//删除满足指定条件的链表头部的连续若干节点
p=head->next;
pold=head;
while(p!=NULL)
{
if(p->Salary
{
pold->next=p->next;
printf("%.3f
has been deleted! \n\n",p->Salary);
free(p);
p=pold->next;
}
else
{
pold=p;
p=p->next;
} }
return head;
}
//建立一个链表,每个结点包括职工名、学分数。输入一门职工的名称,在链表中查找是否有这门课,若未找到,则
// 从键盘输入该职工的学分数,将这门课插入到链表的尾部,然后输出修改后链表各结点的数据。
void main()
{
int i;
long num;
char wname[20];
double salary;
struct worker *head,*ps,*pw;
head=create(WN);
ps=pw=(struct worker *)malloc(sizeof(struct
worker));
printf("请输入工资:\n");
scanf("%lf",&salary);
pw->Salary=salary;
head=deletew(head,salary);
if(find(head,salary,ps)==NULL)
{
printf("请输入该职工的工号和姓名:\n");
scanf("%ld",&num);
scanf("%s",wname);
pw->Wnum=num;
strcpy(pw->Wname,wname);
pw->next=NULL;
}
head=insert(head,pw);
print(head);
}