PAT 1028 人口普查

1028 人口普查 (20 分)

某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。

这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 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

第一次自己写的:前前后后用了太多的循环,耗时太长 

//写一个结构体,输入数据,然后循环计算从他生日到2014年9月6号活了多少天算是否符合,还可以计算出max和min

#include <stdio.h>

struct People{
    char name[10];
    int year;
    int month;
    int day;
}; 
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
//计算出每个人总共活了多少天(循环太多了,或消耗大量的时间)
int calculate(int year,int month,int day)
{
    int cot=0;
    for(;year<=2014;year++)
    {
        days[1]=(year%400==0) || (year%4==0 && year%100!=0)?29:28;
        for(;month<=sizeof(days)/sizeof(days[0]);month++)
        {
            for(;day<=days[month-1];day++)
            {
                cot++;
                if(year==2014 && month==9 && day==6)
                {
                    return cot;
                }
            }
            day=1;
        }
        month=1;
    }
    return cot;
}

int main(void)
{
    int N;
    scanf("%d",&N);
    getchar();
    struct People people[N];
    int i,cot=0,cot1=0,total;
    int year,month,day;
    int m=0,mi=0;
    total=calculate(1814,9,6);    //计算总的200年到现在的天数
    int max=0,min=1000000;
    for(i=0;i<N;i++)
    {
        scanf("%s",people[i].name);
        scanf("%d",&people[i].year);
        getchar();
        scanf("%d",&people[i].month );
        getchar();
        scanf("%d",&people[i].day );
        getchar();
        year=people[i].year;
        month=people[i].month;
        day=people[i].day;
            
        cot=calculate(year,month,day);
        if(cot<=total && cot>0){
            if(cot>max)
            {
                m=i;
                max=cot;    
            }
            if(cot<min)
            {
                mi=i;
                min=cot;        
            }
            cot1++;
        }
    }
    if(cot1==0)
    {
        printf("0\n");
    }
    else
    {
        printf("%d %s %s\n",cot1,people[m].name,people[mi].name);
    }
}

计算点3是在没有人符合条件的时候直接输出 

这是自己第二次写的:目前还有点问题,利用qsort函数排序出了问题 (待解决......)

问题在于:我使用typedef的时候把结构体名称和变量名写成了一样的(实际操作是可以,不冲突),但是在qsort函数中单个数据的内存大小在系统计算中计算的是所有结构体数组所占的内存大小

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct{
        char name[10];
        int year;
        int month;
        int day;
}people;
 
 
int compare(const void *a,const void *b){
        people A=*(people *)a;
        people B=*(people *)b;
        
        if(A.year!=B.year) return B.year>A.year;        
        else if(A.month!=B.month) return B.month>A.month;
        else return B.day>A.day;
}
 
int main(void){
        int n,i,k=0;        
        scanf("%d",&n);
        people people[n];
        int year,month,day;
        char name[10];        //临时存储名字 
        
        for(i=0;i<n;i++){
                getchar();
                scanf("%s %d/%d/%d",name,&year,&month,&day);
                //用于判断是否符合出生年月日条件,符合则将它放进people结构体中 
                if(((year<2014) || (year==2014 && month<9) || (year==2014 && month==9 &&day<=6))
                &&((year>1814)||(year==1814 && month>9)||(year==1814 && month==9 && day>=6))){
                        strcpy(people[k].name,name);        //k顺便统计符合年龄条件的人数 
                        people[k].year=year;
                        people[k].month=month;
                        people[k++].day=day;
                }
        }
 
        qsort(people,k,sizeof(people[0]),compare);        //将符合年龄条件的人排序 
 		
        if(k!=0)    printf("%d %s %s\n",k,people[k-1].name,people[0].name); 
        else printf("%d\n",k);
        
        return 0;
}

 这是别人的代码:很巧妙的使用了乘法将出生年月日转化成了数字,这样不仅方便比较大小,还不需要排序,只需要记录下,最大最小的名字即可,(不过需要注意scanf函数输入的数据类型)

#include <stdio.h>
#include <string.h>

int main(void){
	int n,count=0,i;
	scanf("%d",&n);
	int day,month,year;
	char name[6],maxname[6],minname[6];
	long long maxage=20140906,minage=18140906;
	for(i=0;i<n;i++){
		scanf("%s %d/%d/%d",name,&year,&month,&day);
		long long birth=year*10000+month*100+day;
		if(birth<18140906 || birth>20140906);
		else{
			count++;
			if(birth<maxage){
				strcpy(maxname,name);
				maxage=birth;
			}
			if(birth>minage){
				strcpy(minname,name);
				minage=birth;
			}
		} 
	}
	if(count){
		printf("%d %s %s\n",count,maxname,minname);
	}
	else{
		printf("0\n");
	}
	
	return 0;
}

2022.5.11         以后找最大值、最小值,开始初始化的时候最大值定义为范围的最小值,最小值定义为范围的最大值!!

#include <stdio.h>
#include <string.h>

int main(void){
	int n,i,cot=0;
	scanf("%d",&n);
	int birth,max_birth=20140906,min_birth=18140906;
	int year,month,day;
	char name[6],max_name[6],min_name[6];
	for(i=0;i<n;i++){
		scanf("%s %d/%d/%d",name,&year,&month,&day);
		birth=year*10000+month*100+day;
		if(birth>20140906 || birth<18140906)	continue;
		if(birth<max_birth){
			max_birth=birth;
			strcpy(max_name,name);
		}
		if(birth>min_birth){
			min_birth=birth;
			strcpy(min_name,name);
		}
		cot++;
	}
	if(cot)	printf("%d %s %s\n",cot,max_name,min_name);
	else printf("0\n");	
	return 0;
}

2022.6.26

注意:

①:取值范围要准确

②:注意当没有人符合条件的情况

#include <stdio.h>
#include <stdlib.h>

typedef struct People{
	char name[10];
	int year;
	int month;
	int day;
}people;

int compare(const void *a,const void *b){
	people A=*(people *)a;
	people B=*(people *)b;

	//出生年月日从大到小排序
	if(A.year!=B.year)	return B.year>A.year;
	else if(A.month!=B.month)	return B.month>A.month;
	else return B.day>A.day;
}

int main(void){
	int n,i,k=0;
	scanf("%d",&n);
	people t[n];

	for(i=0;i<n;i++){
		people s;
		getchar();
		scanf("%s %d/%d/%d",s.name,&s.year,&s.month,&s.day);
		if(((s.year<2014) || (s.year==2014 && s.month<9) || (s.year==2014 && s.month==9 && s.day<=6)) && ((s.year>1814) || (s.year==1814 && s.month>9) || (s.year==1814 && s.month==9 && s.day>=6))){
			t[k++]=s;	
		}	
	}
	qsort(t,k,sizeof(t[0]),compare);

	if(k!=0)	printf("%d %s %s\n",k,t[k-1].name,t[0].name);
	else printf("%d\n",k);

	return 0;
}

 好好学习,天天向上!

我要考研!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值