プログラムコード (lifeclock.c)
/*********** START *****************************/
#include < stdio.h >
/*日付の構造体 a=年,b=月,c=日*/
struct date {
int a;
int b;
int c;
};
/*このプログラムで使われている関数*/
struct date getdate(int );
int checkdate(struct date );
int leapyear(int ,int );
int countdays(struct date );
int totaldays(struct date ,struct date );
/******* main *************************************/
int main () {
char buff[100];
int n,total,untilnow,second,minute,hour,totalsecond;
double ratio,time;
struct date birth=getdate(1); /*まず誕生日を入力してもらう*/
if (checkdate(birth)==-1) return;
printf("How many years will you live?\n"); /*何歳まで生きるか入力してもらう*/
fgets(buff,sizeof(buff),stdin);
n=atoi(buff);
struct date now=getdate(2); /*現在の日付を入力してもらう*/
if (checkdate(now)==-1) return; /*ライブラリーの関数も使えますが、入力可能にしてみました*/
struct date death; /*ここで死亡の日付の構造体を作る*/
death.a=birth.a+n;
death.b=birth.b;
death.c=birth.c;
total= totaldays(birth,death); /*誕生日から死亡までの日数*/
untilnow= totaldays(birth,now); /*誕生日から現在までの日数*/
ratio = (double)untilnow/total; /*一生の何%が過ぎたかを計算する*/
time=86400*ratio; /*24時間にその比率をかけて、現在何秒過ぎたかを計算する*/
totalsecond = time; /*秒までしか計算したくないので、ここで自然数に変更する*/
second = totalsecond%60; /*秒の計算*/
minute = (totalsecond/60)%60; /*分の計算*/
hour = totalsecond/3600; /*時の計算*/
printf("If your life was compared to 24 hours, now would be %d hour %d minutes %d second\n", hour, minute, second);
return 0;
}
/******* getdate **********************/
/*日付をキーボードから入力する*/
struct date getdate (int i) {
struct date date;
char buff[100];
if (i==1) printf("What year were your born? (1900<=year<=2000)");
else printf("What year is now?\n");
fgets(buff,sizeof(buff),stdin);
date.a=atoi(buff);
if (i==1)printf("What month were your born?\n");
else printf("What month is now?\n");
fgets(buff,8,stdin);
date.b=atoi(buff);
if (i==1) printf("What day were your born?\n");
else printf("What day is today?\n");
fgets(buff,8,stdin);
date.c=atoi(buff);
return (date);
}
/******** checkdate ******************************/
/*記入された日付が有効であるか確認する。問題に「bとcは一般的な月日の範囲とします」と指示してあるので、この関数は省略しても良い*/
int checkdate(struct date date){
if (date.a<1900) { /*年*/
printf("invalid year,try again\n");
return(-1);
}
if (date.b<1 || date.b>12) { /*月*/
printf("invalid month,try again\n");
return(-1);
}
if (date.c<1 || date.c >31){ /*日*/
printf("invalid day,try again\n");
return(-1);
}
if (date.b==4 || date.b==6 || date.b==9 || date.b==11) {
if (date.c==31){
printf("invalid day,try again\n");
return(-1);
}
}
if (date.b==2) { /*2月の場合は閏年かどうかをleapyear関数で確認し、29日の有効を確認する*/
if (leapyear(date.a,date.a)==0) {
if (date.c>28) {
printf("invalid day,try again\n");
return(-1);
}
}
else {
if (date.c>29) {
printf("invalid day,try again\n");
return(-1);
}
}
}
}
/******* leapyear ************************************************/
/*ある年からある年までに閏年が何年あるかを調べる*/
int leapyear(int b,int l){
int count=0;
int i;
for (i=b;i<=l;i++){
if (i%100==0 && i%400!=0) i++;
if (i%4==0) {
count++;
}
}
return(count);
}
/********** countdays *********************************************/
/*ここで年の始まりからある日までの日数を数える*/
int countdays (struct date x) {
int year[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
int lyear[12] = {31,29,31,30,31,30,31,31,30,31,30,31};
int sum=0,i;
sum+=(x.c-1);
for (i=0;i<(x.b-1);i++){
if (leapyear(x.a,x.a)==1) sum+=lyear[i];
else sum+=year[i];
}
return (sum);
}
/**************** totaldays ***************************/
/*ここである日から違う日までの日数を3段階で数える*/
int totaldays(struct date birth,struct date death){
/*生まれてからその年が終わるまでの日を数える*/
int x1;
int y=countdays(birth);
if (leapyear(birth.a,birth.a)==1) x1=366-y;
if (leapyear(birth.a,birth.a)==0) x1=365-y;
/*死亡の年が始まってから死亡する日までの日を数える*/
int x2=countdays(death);
/*生まれた年の次の年から死亡した年の前の年までの日を数える*/
int n=(death.a-birth.a);
int leap=leapyear(birth.a+1,death.a-1);
int x3=(366*leap)+(365*(n-leap-1));
int total=x1+x2+x3;
return (total);
}
/******** END ***************************/
出力の例
i)
1990<=a<=2000,n=80のとき、今日は何時何分何秒ですか?
t11m022@s01612h009:~/sony$ ./lifeclock
What year were your born? (1900<=year<=2000)
1960
What month were your born?
10
What day were your born?
14
How many years will you live?
80
What year is now?
2012
What month is now?
2
What day is today?
9
If your life was compared to 24 hours, now would be 15 hour 23 minutes 46 second
ii)
1990<=a<=2000,n=200のとき、今日は何時何分何秒ですか?
t11m022@s01612h009:~/sony$ cc lifeclock.c
t11m022@s01612h009:~/sony$ ./a.out
What year were your born? (1900<=year<=2000)
1950
What month were your born?
4
What day were your born?
2
How many years will you live?
200
What year is now?
2012
What month is now?
2
What day is today?
9
If your life was compared to 24 hours, now would be 7 hour 25 minutes 22 second
アルゴリズムの説明・動作方法
「誕生日から今までの日数」を、「誕生日から死亡までの日数」と割って比率を出している。それから、その比率を24時間の秒数(86400秒)にかけて、今日は何時何分何秒という回答を出している。
日数を数えるのに3段階を使っている。
1-
countdaysでは、年の始めからある月日まで何日過ぎているかを数えている。
例えば、4月15日(0時)なら、1月~3月までの日数(配列の足し算)プラス4月の過ぎた14日。
2-
この同じ関数で、ある日付から年が終わるまでの日数を数えられる。
例えば、1年間の365マイナス今まで過ぎた日数。
ここでは閏年も考慮している。
3-
1と2に数えてない日数を計算する。
例えば、1950年~1970年なら閏年が5年間あるので
(366 x 5) + (365 x 15) で計算できる。
例えば、i)の計算は以下のようになる。
1960年10月14日 ~ 80年間 の一生を24時間にたとえて、
2012年2月9日は何時何分何秒になるか。
1-
1960年10月14日から1961年1月1日までの日数を計算する
1960は閏年なので、31+29+31+30+31+30+31+31+30+13 = 287
366 - 287 = 79日
2-
2012年1月1日から2012年2月9日までの日数を計算する
31+8 = 39日
3-
1961年から2011年までの日数を計算する
閏年が12年間
(366 x 12) + (365 x 40) = 18262日
全部を足したら18380日になる。これが「誕生日から今までの日数」
同じように「誕生日から死亡までの日数」を計算すると28855日になる。
18383/28855 = 0.6371 (63.71%)
これを86400秒にかけると、55043.88秒になる。
これが15時23分46(.88)秒になる。
この問題では秒以下の時間を省略している。
実行環境など
私はLinuxのUbuntuで実行をしましたが、基本的な機能しか使っていないので、C言語のコンパイラがあればどこでも実行できるはずです。
コードを.cファイルに保存して、コンパイルすらば実行できる。
Nenhum comentário:
Postar um comentário