一、PTA实验作业
题目1.结构体数组中查找指定编号人员
1. 本题PTA提交列表
2. 设计思路
struct student{
char num[10];
int year,month,day ;
};//该结构体表示人员的编号,出生年、月、日
定义i为循环变量,定义结构变量p
for i=0 to N-1
if std[i]中编号等于num
把std[i]赋值给p;跳出循环;
end for
返回p ;
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明
①初步代码及输出答案。
②不管怎么改,进入不了if语句。发现题目头中给出#include<string.h>
,考虑到应该使用函数来实现。
③尝试用比较函数strcmp来判断编号是否相等,改完后发现答案正确。
题目2.时间换算
1. 本题PTA提交列表
2. 设计思路
struct time{
int hour,minute,second;
};//该结构体表示时、分、秒
定义n表示过了n秒,定义结构变量times
输入起始时间和n
//计算新的时间
秒数=秒数+n;
分钟=分钟+秒数/60;
小时=小时+分钟/60;
//调整新时间的格式
秒数=秒数%60;
分钟=分钟%60;
小时=小时%24;
输出过n秒后的新时间
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明
①本题初步代码及输出结果。
②计算新时间时没有加上原来的时间,导致结果错误。改正后正确。
题目3.通讯录的录入与显示
1. 本题PTA提交列表
2. 设计思路
struct information{
char name[10];//姓名
int year,month,day;//出生年、月、日
char sex[2];//性别
char telephone[20],mobilephone[20];//telephone固定电话,mobilephone移动电话
};
定义变量n表示通讯录条数,i为循环变量,k为查询次数,number为查询编号;
输入n;
定义结构数组num[n];
for i=0 to n-1
输入姓名 生日 性别 固话 手机
end for
输入查询次数k;
for i=0 to k-1
输入查询编号number;
if 查询的编号有效
输出姓名 固话 手机 性别 生日
else
输出Not Found
end for
3.代码截图
4.本题调试过程碰到问题及PTA提交列表情况说明
①初步代码及结果,多种错误。
②调试发现性别,电话错误。
③把性别改为数组存放后部分正确。
④调试发现,判断编号有效后,输出不应该是第 i 条通讯录信息,应该是要查询的第number条信息。
⑤修改后代码及结果如下。
⑥不应该改变循环变量的值,直接在输出中改成输出第number 组。并且在输出中要用到%02d
控制出生日期格式。
二、截图本周题目集的PTA最后排名。
PTA排名
PTA提交列表
三、阅读代码
题目1:计算两个时间段的差值
#include <stdio.h>
struct TIME
{
int seconds;
int minutes;
int hours;
};
void differenceBetweenTimePeriod(struct TIME t1, struct TIME t2, struct TIME *diff);
int main()
{
struct TIME startTime, stopTime, diff;
printf("输入开始时间: \n");
printf("输入小时、分钟、秒:");
scanf("%d %d %d", &startTime.hours, &startTime.minutes, &startTime.seconds);
printf("输入停止时间: \n");
printf("输入小时、分钟、秒: ");
scanf("%d %d %d", &stopTime.hours, &stopTime.minutes, &stopTime.seconds);
differenceBetweenTimePeriod(startTime, stopTime, &diff); // 计算差值
printf("\n差值: %d:%d:%d - ", startTime.hours, startTime.minutes, startTime.seconds);
printf("%d:%d:%d ", stopTime.hours, stopTime.minutes, stopTime.seconds);
printf("= %d:%d:%d\n", diff.hours, diff.minutes, diff.seconds);
return 0;
}
void differenceBetweenTimePeriod(struct TIME start, struct TIME stop, struct TIME *diff)
{
if(stop.seconds > start.seconds){
--start.minutes;
start.seconds += 60;
}
diff->seconds = start.seconds - stop.seconds;
if(stop.minutes > start.minutes){
--start.hours;
start.minutes += 60;
}
diff->minutes = start.minutes - stop.minutes;
diff->hours = start.hours - stop.hours;
}
题目2:愿天下有情人都是失散多年的兄妹
输入格式:
输入第一行给出一个正整数N(2 <= N <= 104),随后N行,每行按以下格式给出一个人的信息: 本人ID 性别 父亲ID 母亲ID
其中ID是5位数字,每人不同;性别M代表男性、F代表女性。如果某人的父亲或母亲已经不可考,则相应的ID位置上标记为-1。
接下来给出一个正整数K,随后K行,每行给出一对有情人的ID,其间以空格分隔。
注意:题目保证两个人是同辈,每人只有一个性别,并且血缘关系网中没有乱伦或隔辈成婚的情况。
输出格式:
对每一对有情人,判断他们的关系是否可以通婚:如果两人是同性,输出“Never Mind”;如果是异性并且关系出了五服,输出“Yes”;如果异性关系未出五服,输出“No”。
分析:先标记第一个人的所有祖先,然后便利第二个人的祖先,如有相同,返回是第几代祖先,否则返回-1。
#include<stdio.h>
struct p{
int fa,ma;
int sex;
int flag;
}dir[100005];
int sum,flag,sum1;
void biaoji(int x)//标记第一个人祖先
{
if(dir[x].fa!=-1) {
dir[dir[x].fa].flag=1;
biaoji(dir[x].fa);
}
if(dir[x].ma!=-1) {
dir[dir[x].ma].flag=1;
biaoji(dir[x].ma);
}
}
void bianli(int x,int sum)//遍历第二个人祖先,如果被标记,令sum1为标记的几代祖先,否则继续遍历
{
//printf("%05d\n",x);
if(dir[x].flag==1&&flag==0){
flag=1;
//printf("*");
sum1=sum;
}
else {
if(dir[x].fa!=-1){
bianli(dir[x].fa,sum+1);
}
if(dir[x].ma!=-1){
bianli(dir[x].ma,sum+1);
}
}
}
int main()
{
int n;
scanf("%d",&n);
int fa,ma,di;
char sex;
for(int i=0;i<100005;i++){
dir[i].fa=-1;
dir[i].ma=-1;
}
for(int i=0;i<n;i++){
scanf("%d %c %d %d",&di,&sex,&fa,&ma);
dir[di].fa=fa;
dir[di].ma=ma;
if(sex=='M') dir[di].sex=1;
if(sex=='F') dir[di].sex=2;
dir[fa].sex=1;//标记父母性别,男性为1,女性为2
dir[ma].sex=2;
}
// for(int i=1;i<=24;i++)
// printf("%d:%d\n",i,dir[i].sex);
int m;
scanf("%d",&m);
int di1,di2;
while(m--){
scanf("%d %d",&di1,&di2);
for(int i=0;i<100005;i++)
dir[i].flag=0;//标记初始化
if(dir[di1].sex==dir[di2].sex) printf("Never Mind\n");
else{
sum=0;
flag=0;
sum1=-1;
biaoji(di1);//首先把第一个人的祖先全部标记
bianli(di2,sum);
if(sum1>=5||sum1==-1)
printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
四、本周学习总结
1.总结本周学习内容。
1.结构体、共用体、枚举这种构造数据类型特点。
1.1结构体
struct 结构名{
类型名 结构成员名1;
类型名 结构成员名2;
…
类型名 结构成员名n;
}变量列表;
- 如果要声明变量结构,可以在结构定义时,在结束的分号之前加上这些变量的名字,也可以在定义结构之后使用
struct 结构名 变量列表;
语句声明结构变量。 - struct是定义结构类型的关键字,结构名是一个合法的C标识符,结构的定义以分号结束。
- 嵌套定义的结构变量中,每个成员按从左到右,从外到内的方式引用。
- 结构成员成员运算符的优先级属最高级别,所以一般情况下都是优先执行,即和一般运算符混合运算时,结构成员运算符优先。
- 只有相同结构类型的变量之间才可以直接赋值。不能在结构体内部直接给成员赋值。
例:s2=s1;
等效于
s2.num=s1.sum;
strcpy(s2.name,s1.name);//数组
s2.math=s1.math;
s2.english=s1.english;
s2.computer=s1.computer;
s2.average=s1.average;
1.2共用体(联合体)
union 联合名{
成员声明
成员声明
…
}变量列表;
- 如果要声明联合变量,可以在联合定义时,在结束的分号之前加上这些变量的名字,也可以在定义联合之后使用
union 联合名 变量列表;
语句声明联合变量。 - 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后,原有成员就失去作用。即当给一个成员重复赋值时或对多个成员赋值时,只承认最后一次的赋值。
- 共用体变量的地址和它的各成员的地址都是同一地址。
- 不能对共用体变量名赋值,也不能企图引用变量名来得到一个值。
- 共用体类型可以出现在结构体类型的定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型的定义中,数组也可以作为共用体的成员。
- 共用体变量的初始化:
union data a=b; //把共用体变量初始化为另一个共用体
union data a={123}; //初始化共用体为第一个成员
union data a={.ch='a'}; //指定初始化项目
1.3枚举
enum 枚举名{枚举值1,枚举值2,…}变量列表;
- 如果要声明一个枚举变量(假定该枚举类型已经在前面定义过),可以采用
enum 枚举名 变量列表
的方式。 - 每一个枚举值应该是一个合法的标识符,或是一个标识符后跟上等号,再加上一个常量表达式。
- 编译程序将从0开始逐个给枚举值赋值。如果某个枚举值标识符后面跟有等号和常量表达式,那么编译程序就将该常量表达式的值作为该枚举的值。该枚举值后面的枚举值从这个枚举值开始逐个加1,重新编号。注意:枚举值都不能超过它的基础类型范围,否则会报错。
例:b的值为2,d的值为2.
public enum Number{a=1,b,c=1,d} ;
- 编译程序将枚举值当作常量。
- 每个枚举成员的常数值必须在该枚举的基础类型的范围之内。
例:产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型 uint 的范围内。
public enum TimeofDay:uint
{
Morning=-3,
Afternoon=-2,
Evening=-1
} ;
1.4其他
- 结构体和联合体可以含有多种数据类型,枚举只能含有一种基本数据类型,而且为整型。
- 结构体和联合体所占的空间不同,结构体按照对其方式每个数据类型都是独立的数据空间,整个结构体所占的空间基本上可以等于或者大于每个独立数据空间的和。而联合体所有数据类型都共享最大的那个数据类型的空间,所占的空间为最大的那个数据类型所占的空间。
2.递归函数原理
- 递归方法的两个要点:
递归出口:递归结束条件,到何时不再递归调用下去。
递归调用式子:递归的表达式。如fact(n)=n*fact(n-1)
- 尾部递归:指递归函数在调用自身后直接传回其值,而不对其再加运算,无需返回调用。尾部递归与循环是等价的。
- 优点:解决复杂问题,代码更直观。
2.罗列本周一些错题。
- 预习的时候对一些知识点还不熟悉。①函数调用时不知道填什么就随便填了float。②返回的应该是地址。