作者的话:若有朋友复制代码去PAT试着运行遇到问题的:
1.可能是格式问题,可以先把从本站复制的代码粘贴到记事本,再把记事本里的代码复制,然后粘贴到PAT的代码区,提交本题回答,应该就可以了;
2.可能是注释原因,PAT有时候检测到注释会编译错误,所以可以先把注释删了,再进行提交回答;
3.可能是作者当初根据题目写出来的代码仍存在一些疏漏,而恰好当时的测试机制没那么完善,没检测出问题。后面测试机制有所更新,故出现问题,若有相关需要的可以评论区留言或私信作者,我看到的话会去再查一下疏漏之处,然后更新文章。
一、题目描述
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200岁的老人,而今天是2014年9月6日,所以超过200岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入格式:
输入在第一行给出正整数 N,取值在(0,105];随后 N 行,每行给出1个人的姓名(由不超过5个英文字母组成的字符串)、以及按 yyyy/mm/dd(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。
输出格式:
在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。
输入样例:
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例:
3 Tom John
二、解题思路
读题:
//接收正整数N,表示后面N行会给出总共N个人的姓名和生日。
//接收姓名(<=5个字母)+生日(yyyy/mm/dd)
//输出有效生日的个数+最年长的人的姓名+最年轻的人的姓名(空格相隔)
//要求:设定今天是2014.9.6,超过两百岁的生日和未出生的生日都是无效生日
思路:
1.定义结构体Person,成员是存储姓名的字符串数组a和存储生的变量year,month,day;
2.定义需要的变量并接收n;
3.把n赋值给count(后面会检测每个输入的生日,若为无效生日,则count–,当检测完所有生日后,count的值就是有效生日的个数);
4.设置循环,循环进行n轮,每轮循环接收一行数据,并检测接收的数据是否为有效生日。把当轮循环及之前接收的有效生日中的最早生日(年纪最大)和最晚生日(年纪最小)找出来存在max,min中;
5.按要求格式进行输出。
三、具体实现
0.标准C源程序框架
#include <stdio.h>
#include <string.h>//要用到strcpy函数
int main()
{
return 0;
}
1.定义结构体Person,成员是存储姓名的字符串数组a和存储生日的变量year,month,day;
typedef struct Person
{
char a[6];//存储最多5个字母+'\0'
int year, month, day;//存储年月日
}Person;
2.定义需要的变量并接收n;
int n;//存储N
int i = 0;//循环变量
int count;//存储有效生日的个数
//初始化max,min,并控制初值在后面一定能被有效数据所覆盖
Person max = { "",3000,1,1 }, min = { "",0,1,1 }, temp;
scanf("%d", &n);
3.把n赋值给count(后面会检测每个输入的生日,若为无效生日,则count–,当检测完所有生日后,count的值就是有效生日的个数);
count = n;//开始默认所有数据都为有效生日
4.设置循环,循环进行n轮,每轮循环接收一行数据,并检测接收的数据是否为有效生日。把当轮循环及之前接收的有效生日中的最早生日(年纪最大)和最晚生日(年纪最小)找出来存在max,min中;
while (i < n)
{
scanf("%s", temp.a);//接收当前行的姓名和生日
scanf("%d/%d/%d", &temp.year, &temp.month, &temp.day);
if (temp.year < 1814//生于1814年以前的,已经超过200岁,属于无效生日
|| ((temp.year == 1814) && ((temp.month < 9) || ((temp.month == 9) && (temp.day < 6))))//1814年出生,出生的月份或日期早于200年前的今天的,也是无效生日
|| ((temp.year == 2014) && ((temp.month > 9) || ((temp.month == 9) && (temp.day > 6))))//同在今年,今天之后的日期
|| temp.year>2014)//今年之后的年份
{
count--;//前面条件表达式若为真,说明当前输入为无效生日
}
else//确定当前接收生日是有效生日时
{
if ((temp.year < max.year)//比当前最早出生年份更小的,是年龄更大的
|| ((temp.year == max.year) && (temp.month < max.month))//月份
|| ((temp.year == max.year) && (temp.month == max.month) && (temp.day < max.day)))//日期
{
strcpy(max.a, temp.a);
max.year = temp.year;
max.month = temp.month;
max.day = temp.day;
}//找到年龄更大的人,把其的数据赋值给max
if (temp.year > min.year//比当前最晚出生年份更大的,是年龄更小的
|| ((temp.year == min.year) && (temp.month > min.month))
|| ((temp.year == min.year) && (temp.month == min.month) && (temp.day > min.day)))
{
strcpy(min.a, temp.a);
min.year = temp.year;
min.month = temp.month;
min.day = temp.day;
}
}
i++;
}
5.按要求格式进行输出。
if (count)//当所有数据都为无效生日的时候,不存在最年长者和最年轻者,不需要输出他们的名字
printf("%d %s %s", count, max.a, min.a);
else
printf("%d", count);
四、测试数据
输入输出样例1:如题
输入样例2:(当所有数据都无效的时候,不需要输出最年长者和最年轻者的名字,只需要输出0,后面不能有任何符号)(测试点3)
1
Mike 0000/00/00
输出样例2:
0
五、全部代码
#include <stdio.h>
#include <string.h>//要用到strcpy函数
typedef struct Person
{
char a[6];//存储最多5个字母+'\0'
int year, month, day;//存储年月日
}Person;
int main()
{
int n;//存储N
int i = 0;//循环变量
int count;//存储有效生日的个数
//初始化max,min,并控制初值在后面一定能被有效数据所覆盖
Person max = { "",3000,1,1 }, min = { "",0,1,1 }, temp;
scanf("%d", &n);
count = n;//开始默认所有数据都为有效生日
while (i < n)
{
scanf("%s", temp.a);//接收当前行的姓名和生日
scanf("%d/%d/%d", &temp.year, &temp.month, &temp.day);
if (temp.year < 1814//生于1814年以前的,已经超过200岁,属于无效生日
|| ((temp.year == 1814) && ((temp.month < 9) || ((temp.month == 9) && (temp.day < 6))))//1814年出生,出生的月份或日期早于200年的今天的,也是无效生日
|| ((temp.year == 2014) && ((temp.month > 9) || ((temp.month == 9) && (temp.day > 6))))//今年今天之后的日期
|| temp.year>2014)//今年之后的年份
{
count--;//前面条件表达式若为真,说明当前输入为无效生日
}
else//确定当前接收生日是有效生日时
{
if ((temp.year < max.year)//比当前最早出生年份更小的,是年龄更大的
|| ((temp.year == max.year) && (temp.month < max.month))//月份
|| ((temp.year == max.year) && (temp.month == max.month) && (temp.day < max.day)))//日期
{
strcpy(max.a, temp.a);
max.year = temp.year;
max.month = temp.month;
max.day = temp.day;
}//找到年龄更大的人,把其的数据赋值给max
if (temp.year > min.year//比当前最晚出生年份更大的,是年龄更小的
|| ((temp.year == min.year) && (temp.month > min.month))
|| ((temp.year == min.year) && (temp.month == min.month) && (temp.day > min.day)))
{
strcpy(min.a, temp.a);
min.year = temp.year;
min.month = temp.month;
min.day = temp.day;
}
}
i++;
}
if (count)//当所有数据都为无效生日的时候,不存在最年长者和最年轻者,不需要输出他们的名字
printf("%d %s %s", count, max.a, min.a);
else
printf("%d", count);
return 0;
}
六、优化代码
//运行速度变化不大,但是我觉得代码可读性应该增强了,代码量也有相应减少。
#include <stdio.h>
#include <string.h>//要用到strcpy函数
typedef struct Person
{
char a[6];//存储最多5个字母+'\0'
int birth;//存储生日
}Person;
int main()
{
int n;//存储N
int i = 0;//循环变量
int count;//存储有效生日的个数
int year, month, day;
//初始化max,min,并控制初值在后面一定能被有效数据所覆盖
Person max = { "",30000101 }, min = { "",00000101 }, temp;
scanf("%d", &n);
count = n;//开始默认所有数据都为有效生日
while (i < n)
{
scanf("%s", temp.a);//接收当前行的姓名和生日
scanf("%d/%d/%d", &year, &month, &day);
temp.birth = year*10000+month*100+day;//把年月日三个数据整合成一个整数,以此更方便的比较生日早晚
if (temp.birth<18140906||temp.birth>20140906) count--;//前面条件表达式若为真,说明当前输入为无效生日
else//确定当前接收生日是有效生日时
{
if(temp.birth<max.birth)//出生日期比当前年龄最大者更小,即更早,则年龄比他更大
{
strcpy(max.a, temp.a);
max.birth = temp.birth;
}//找到年龄更大的人,把其的数据赋值给max
if (temp.birth > min.birth)//出生日期比当前年龄最小者更大,即更迟,则年龄比他更小
{
strcpy(min.a, temp.a);
min.birth = temp.birth;
}
}
i++;
}
if (count)//当所有数据都为无效生日的时候,不存在最年长者和最年轻者,不需要输出他们的名字
printf("%d %s %s", count, max.a, min.a);
else
printf("%d", count);
return 0;
}