本文是谭浩强老师c++程序设计(第三版)第七章的习题总结,主要涉及结构体的内容。
1. 定义一个结构体变量(包括年、月、日),编写程序,要求输入年月日,程序能够计算并输出改日是本年中的第几天。注意闰年问题。
#include <iostream>
using namespace std;
struct date
{
int year;
int month;
int day;
};
int main()
{
int days;
date Date;
cout << "input year, month,day: ";
cin >> Date.year >>Date.month >>Date.day;
switch(Date.month)
{
case 1: days = Date.day; break;
case 2: days = Date.day + 31; break;
case 3: days=Date.day+59; break;
case 4: days=Date.day+90; break;
case 5: days=Date.day+120; break;
case 6: days=Date.day+151; break;
case 7: days=Date.day+181; break;
case 8: days=Date.day+212; break;
case 9: days=Date.day+243; break;
case 10: days=Date.day+273; break;
case 11: days=Date.day+304; break;
case 12: days=Date.day+334; break;
}
if(Date.year %4 == 0 && Date.year % 100 !=0 ||Date.year % 400 == 0 && Date.month >=3)
days = days + 1;
cout<<Date.month<<"/"<<Date.day<<" is the "<<days <<"th day in "<<Date.year<<"."<<endl;
return 0;
}
本题需要注意两个问题:
(1)结构体声明时,struct后边的是结构体类型,而不是结构体名称,即此题中data是类型,而Date是名称,引用时只能引用名称Date而不能引用类型date;
(2)关于闰年的计算:闰年需要满足能被4整除且不能被100整除(此处典型的平年是1900年),或者该年份能被400整除,后者容易被忽略,这样将会排除2000年这种闰年年份,因此上述二者缺一不可。
2. 编写一个函数days,实现上面的计算。由主函数将年月日传递给days,计算出该日在本年中是第几天并将结果传回主函数输出
#include <iostream>
using namespace std;
struct date
{
int year;
int month;
int day;
};
int main()
{
int days(date);
date Date;
int d;
cout << "input year,month,day: ";
cin >> Date.year>>Date.month>>Date.day;
d = days(Date);
cout<<Date.month<<"/"<<Date.day<<" is the "<<d <<"th day in "<<Date.year<<"."<<endl;
return 0;
}
int days(date Date)
{
int d;
switch(Date.month)
{
case 1: d = Date.day; break;
case 2: d = Date.day + 31; break;
case 3: d=Date.day+59; break;
case 4: d=Date.day+90; break;
case 5: d=Date.day+120; break;
case 6: d=Date.day+151; break;
case 7: d=Date.day+181; break;
case 8: d=Date.day+212; break;
case 9: d=Date.day+243; break;
case 10: d=Date.day+273; break;
case 11: d=Date.day+304; break;
case 12: d=Date.day+334; break;
}
if(Date.year %4 == 0 && Date.year % 100 !=0 ||Date.year % 400 == 0 && Date.month >=3)
d = d + 1;
return d;
}
3. 编写一个函数print,打印一个学生的成绩数组,该数组中有五个学生的数据,每个学生的数据包括num(学号)、name(姓名)、score[3]](3门课的成绩)、用主函数输入这些数据,用print函数输出这些记录。
#include <iostream>
#include <iomanip>
using namespace std;
const int n=5;
struct student
{
char num[6];
char name[8];
int score[4];
}stu[n];
int main()
{
void print(student stu[5]);
int i,j;
for (i=0;i<n;i++)
{
cout<<"input scores of student "<<i+1<<":"<<endl;
cout<<"NO.: ";
cin>>stu[i].num;
cout<<"name: ";
cin>>stu[i].name;
for (j=0;j<3;j++)
{
cout<<"score "<<j+1<<":";
cin>>stu[i].score[j];
}
cout<<endl;
}
print(stu);
return 0;
}
void print(student stu[5])
{
int i,j;
cout<<" NO. name score1 score2 score3"<<endl;
for (i=0;i<n;i++)
{
cout<<stu[i].num<<" "<<setw(10)<<stu[i].name<<" ";
for (j=0;j<3;j++)
cout<<setw(3)<<stu[i].score[j]<<" ";
cout<<endl;
}
}
4. 在第3题的基础上,编写一个函数input,用来输入5个学生的数据记录。
#include <iostream>
#include <iomanip>
using namespace std;
const int n=5;
struct student
{
char num[6];
char name[8];
int score[4];
}stu[n];
int main()
{
void print(student stu[5]);
void input(student stu[5]);
input(stu);
print(stu);
return 0;
}
void input(student stu[5])
{
int i,j;
for (i=0;i<n;i++)
{
cout<<"input scores of student "<<i+1<<":"<<endl;
cout<<"no.: ";
cin>>stu[i].num;
cout<<"name: ";
cin>>stu[i].name;
for (j=0;j<3;j++)
{
cout<<"score "<<j+1<<":";
cin>>stu[i].score[j];
}
cout<<endl;
}
}
void print(student stu[5])
{
int i,j;
cout<<" no. name score1 score2 score3"<<endl;
for (i=0;i<n;i++)
{
cout<<stu[i].num<<" "<<setw(10)<<stu[i].name<<" ";
for (j=0;j<3;j++)
cout<<setw(3)<<stu[i].score[j]<<" ";
cout<<endl;
}
}
5. 有10个学生,每个学生的数据包括学号,姓名、3门课程的成绩,从键盘输入10个学生数据,要求输出3门课程总平均成绩,以及最高分的学生数据(包括学号、姓名、3门课程成绩、平均分数)
#include <iostream>
#include <iomanip>
using namespace std;
const int n=2;
struct student
{
char num[6];
char name[8];
int score[4];
float avr;
}stu[n];
int main()
{
int i,j,max,maxi,sum;
float average;
for (i=0;i<n;i++)
{cout<<"input scores of student "<<i+1<<endl;;
cout<<"NO.:";
cin>>stu[i].num;
cout<<"name:";
cin>>stu[i].name;
for (j=0;j<3;j++)
{cout<<"score "<<j+1<<":";
cin>>stu[i].score[j];
}
cout<<endl;
}
average=0;
max=0;
maxi=0;
for (i=0;i<n;i++)
{sum=0;
for (j=0;j<3;j++)
sum+=stu[i].score[j];
stu[i].avr=sum/3.0;
average+=stu[i].avr;
if (sum>max)
{max=sum;
maxi=i;
}
}
average/=n;
cout<<" NO. name score1 score2 score3 average"<<endl;
for (i=0;i<n;i++)
{cout<<setw(8)<<stu[i].num<<" "<<setw(10)<<stu[i].name<<" ";
for (j=0;j<3;j++)
cout<<setw(3)<<stu[i].score[j]<<" ";
cout<<stu[i].avr<<endl;
}
cout<<"average="<<average<<endl;
cout<<"The highest score is :"<<stu[maxi].name<<", score total:"<<max<<endl;
return 0;
}
6. 编写一个函数creat,用来建立一个动态链表。所谓建立动态链表是指在程序执行过程中从无到有地建立一个链表,即一个一个地开辟结点和输入各结点,并建立起前后相连的关系。各结点的数据由键盘输入。
#include <iostream>
using namespace std;
#define NULL 0
struct student
{
int num;
float score;
struct student *next;
};
student *creat(void) //定义函数。返回指针值的函数,此函数带回一个指向链表头的指针
{
student *head;
student *p1,*p2;
int n=0;
p1=p2=new student; //开辟一个新单元,并使p1,p2指向它
cin>>p1->num>>p1->score;
head=NULL;
while(p1->num!=0)
{n=n+1;
if(n==1) head=p1;
else p2->next=p1;//此时的p2是上一次的p1,因此后边指向新的p1
p2=p1;//p2是暂存前一个p1的指针
p1=new student;//开辟新的p1
cin>>p1->num>>p1->score;
}
p2->next=NULL;
return(head);
}
7. 编写一个函数print,将第6题建立的链表中各结点的数据依次输出。
#include <iostream>
using namespace std;
#define NULL 0
struct student
{long num;
float score;
student *next;
};
int n;
void print(student *head)
{
student *p;
cout<<"Now,These "<<n<<" records are:"<<endl;
p=head;
if(p!=NULL)
{
do
{
cout << p->num << ' '<<p->score <<endl;
p=p->next;
}while(p!=NULL);
}
}
8. 编写一个函数del,用来删除动态链表中一个指定的结点(由实参指定某一学号,表示要删除该学生结点)。
#include <iostream>
using namespace std;
#define NULL 0
struct student
{
long num;
float score;
student *next;
};
int n;
student *del(student *head,long num)
{
student *p1,*p2;
if (head==NULL) //是空表
{cout<<"list null!"<<endl; return(head);}
p1 = head;
while(num!=p1->num && p1->next!=NULL) //p1指向的不是所要找的结点且后面还有结点
{
p2 = p1;//暂存p1
p1 = p1->next;//往后找
}
if(num == p1->num)//找到要删除的结点了
{
if(p1==head) head=p1->next; //若p1指向的是首结点,把第二个结点地址赋予head
else p2->next = p1->next; //否则将下一结点地址赋给前一结点地址
cout<<"delete:"<<num<<endl;
n=n-1;
}
else cout<<"cannot find "<<num; //找不到该结点
return(head);
}
9. 编写一个函数insert,用来向动态链表插入一个结点。
#include <iostream>
using namespace std;
#define NULL 0
struct student
{
long num;
float score;
student *next;
};
int n;
student *insert(student *head,student *stud)
{
student *p0,*p1,*p2;
p1=head; //使p1指向第一个结点
p0=stud; //指向要插入的结点
if(head==NULL) //原来的链表是空表
{head=p0;p0->next=NULL;} //使p0指向的结点作为头结点
else
{
while((p0->num > p1->num) && (p1->next!=NULL))
{p2=p1; //使p2指向刚才p1指向的结点
p1=p1->next;} //p1后移一个结点
if(p0->num<=p1->num)
{if(head==p1) head=p0; //插到原来第一个结点之前
else p2->next=p0; //插到p2指向的结点之后
p0->next=p1;}
else
{p1->next=p0; p0->next=NULL;}
} //插到最后的结点之后
n=n+1; //结点数加1
return(head);
}
10. 将以上4个函数组成一个程序,由主程序先后调出这些函数,实现链表的建立、输出、删除和插入,在主程序中指定需要删除和插入的结点。
#include <iostream>
using namespace std;
#define NULL 0
struct student
{long num;
float score;
student *next;
};
int n;
int main()
{ student *creat(void);
student *del(student *,long);
student *insert(student *,student *);
void print(student *);
student *head,*stu;
long del_num;
cout<<"input records:"<<endl;
head=creat(); //返回头指针
print(head); //输出全部结点
cout<<endl<<"input the deleted number:";
cin>>del_num; //输入要删除的学号
while(del_num!=0)
{head=del(head,del_num); //删除后链表的头地址
print(head); //输出全部结点
cout<<"input the deleted number:";
cin>>del_num;
}
cout<<endl<<"input the inserted record:"; //输入要插入的结点
stu=new student; //开辟一个新结点
cin>>stu->num>>stu->score;
while(stu->num!=0)
{head=insert(head,stu); //返回地址
print(head); //输出全部结点
cout<<endl<<"input the inserted record:"; //输入要插入的结点
stu=new student;
cin>>stu->num>>stu->score;
}
return 0;
}
11. 医院有A、B、C、D、E、F、G七位医生,每人在一周内要值一次夜班。排班的要求是:
(1)A医生比C医生晚一天值班;
(2)D医生比E医生晚二天值班;
(3)B医生比G医生早三天值班;
(4)F医生的值班日在B和C医生的中间,且是星期四;
请编写程序,输出每位医生的值班日。值班日以Sunday,Monday,Tuesday,Wednesday,Thurday,Friday,Saturday 分别表示星期日到星期六(提示:用枚举变量)
#include<iostream>
using namespace std;
int main()
{
enum weekday{sun,mon,tus,wed,thu,fri,sat}; //声明枚举类型
enum weekday day; //定义枚举变量
int a,b,c,d,e,f,g,loop; //定义整形变量
char ch='A'; //定义字符变量
f=thu; //按照题意,F医生是星期四值班
for(a=sun;a<=sat;a++) //需要逐个检查A医生星期几符合条件
if(a!=f) //A医生值班日子不应该与F医生相同
for(b=sun;b<=sat;b++) //逐个检查B医生星期几符合条件
if((a!=b)&&(f>b)) //B医生值班日子不应该与A医生相同,且F在B之后
for(c=sun;c<=sat;c++) //逐个检查C医生星期几符合条件
if((c!=a)&&(c!=b)&&(c!=f)&&(a==c+1)&&(f<c)) //C医生值班日子不应该与A,B,F医生相同,且A比C晚一天
for(d=sun;d<=sat;d++) //逐个检查D医生星期几符合条件
if((d!=a)&&(d!=b)&&(d!=c)&&(d!=f)&&(c==d+3)) //D医生值班日子不应该与A,B,C,F医生相同,且C与D之后3天
for(e=sun;e<=sat;e++) //逐个检查E医生星期几符合条件
if((e!=a)&&(e!=b)&&(e!=c)&&(e!=d)&&(e!=f)&&(d==e+2)) //E值班不应该与A,B,C,D,E,F相同,且E与D前2天
for(g=sun;g<=sat;g++) //逐个检查G医生条件
if((g!=a)&&(g!=b)&&(g!=c)&&(g!=d)&&(g!=e)&&(g!=f)&&(g==b+2)) //G值班不应该与A,B,C,D,E,F相同,且G与B后2天
//符合以上条件才能执行以下工作
for(loop=0;loop<7;loop++)
{ cout<<"Doctor"<<char(ch+loop)<<":";
switch(loop+1)
{
case 1:day=weekday(a);break;
case 2:day=weekday(b);break;
case 3:day=weekday(c);break;
case 4:day=weekday(d);break;
case 5:day=weekday(e);break;
case 6:day=weekday(f);break;
case 7:day=weekday(g);break;
}
switch(day)
{
case sun:cout<<"Sunday"<<endl;break;
case mon:cout<<"Monday"<<endl;break;
case tus:cout<<"Thusday"<<endl;break;
case wed:cout<<"Wednesday"<<endl;break;
case thu:cout<<"Thurday"<<endl;break;
case fri:cout<<"Friday"<<endl;break;
case sat:cout<<"Saturday"<<endl;break;
}
}
return 0;
}