PAT乙级真题1028 || 人口普查(详解,C/C++示例,测试点分析)


【欢迎关注微信公众号:计算机黑科学大全,对话框回复:PAT乙级真题】获取全部真题详解及代码示例
个人博客地址:https://mzwang.top

人口普查

题目描述:

某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。

输入格式:

输入在第一行给出正整数 N,取值在(0,];随后 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

题目来源:PAT乙级1028
作者:CHEN, Yue
单位:浙江大学

问题解决:

解题思想

分别设置最年长人和最年轻人的姓名、生日,最年长人的生日初始化为最晚的年月日,最年轻人的生日初始化为最早的年月日(想一下为什么要这样初始化?);用scanf()函数读入每一个人的姓名及生日(注意:不能用gets()函数,思考一下为什么?它们遇到空格的处理?),此处,生日以字符串的形式读入,构造一个函数将字符串格式生日转换成数值形式,通过引用来返回数值型的year,month,day;接着,判断此时输入的生日是否合理(不是年龄超过200岁的情况或未出生的生日的情况),若不合理,用continue直接跳过本次循环,进入下一次输入,若合理,判断是否比目前最年长的人更年长或者比目前最年轻的人更年轻,并进行相应的更新。

坑点提醒

本题容易忽略的一个点就是:对有效生日个数为0个的特殊情况的处理。若有效生日个数为0个则不存在最年长或最年轻的人,相应的,只需输出有效生日个数即可(0),不需要输出最年长或最年轻的人的姓名。这也是PAT在线评测系统倒数第二个测试点测试的内容,若此处处理不当则此测试点将不会通过。

代码示例(C/C++)

小提示:请将以下代码保存为.cpp格式(C++程序)左右滑动代码以查看完整代码

#include 
#include 
using namespace std;
void Birth_Strtonum(int &year,int &month,int &day,char birthday[]);
int main()
{
    int n;
    scanf("%d",&n);
    char name[6],birthday[11];//读入姓名和生日
    char oldest[6],youngest[6];//最年长人和最年轻人的姓名
    int old_y = 2014,old_m = 9,old_d = 6;//最年长人的生日,初始化为最晚的年月日
    int young_y = 1814,young_m = 9,young_d = 6;//最年轻人的生日,初始化为最早的年月日
    int coun = 0;//有效生日的个数
    for(int i = 0; i < n; i++){
        getchar();//吸收掉缓冲区换行符
        scanf("%s%s",name,birthday);//读入名字,以字符串格式读入生日
        int year,month,day;
        year = month = day = 0;
        Birth_Strtonum(year,month,day,birthday);
        //下面条件是年龄超过200岁的情况
        if(year < 1814||(year == 1814&&month <9)
           ||(year == 1814&&month == 9&&day < 6)){
            continue;
        }
        //下面条件是未出生的生日的情况
        if(year > 2014||(year == 2014&&month >9)
           ||(year == 2014&&month == 9&&day > 6)){
            continue;
        }
        //更新最年长的人
        if(year < old_y||(year == old_y&&month < old_m)
           ||(year == old_y&&month == old_m&&day < old_d)){
            old_y = year;
            old_m = month;
            old_d = day;
            strcpy(oldest,name);
        }
        //更新最年轻的人
        if(year > young_y||(year == young_y&&month > young_m)
           ||(year == young_y&&month == young_m&&day > young_d)){
            young_y = year;
            young_m = month;
            young_d = day;
            strcpy(youngest,name);
        }
        coun++;//有效生日的个数
    }
    if(coun == 0){//若有效生日个数为0个则不存在最年长或最年轻的人
        printf("%d",coun);
    }
    else{
        printf("%d %s %s",coun,oldest,youngest);
    }
    return 0;
}
//字符串格式生日转换成数值形式,通过引用来返回数值型的year,month,day
void Birth_Strtonum(int &year,int &month,int &day,char birthday[])
{
    int j = 0;
    int k = 1000;
    while(j < 4){//年份转换成数值,注意每一个字符都要转换成数字
        year += (birthday[j] - '0') * k;
        k /= 10;
        j++;
    }
    j++;//跳过年与月的间隔符号'/'
    month = (birthday[j] - '0') * 10 + (birthday[j + 1] - '0');//月份转换成数值
    j += 3;//j跳到天的位置
    day = (birthday[j] - '0') * 10 + (birthday[j + 1] - '0');//天数转换成数值
}

你可能感兴趣的:(PAT乙级真题1028 || 人口普查(详解,C/C++示例,测试点分析))