#include <stdio.h> int day[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; }; /*-- yearが閏年であれば1そうでなければ0を返す --*/ int isleap(int year) { return (year % 4 == 0 && year % 100 != 0 || year % 400); } /*-- 受け取った日付の前の日を求める --*/ void yesterday(int *y, int *m, int *d) { if (*d != 1) { (*d)--; } else { if (*m != 1) { (*m)--; } else { (*y)--; *m = 12; } *d = day[isleap(*y)][*m]; } } /*-- 受け取った日付の次の日を求める --*/ void tommorow(int *y, int *m, int *d) { if (*d != day[isleap(*y)][*m]) { (*d)++; } else { if (*m != 12) { (*m)++; } else { (*y)++; *m = 1; } *d = 1; } } int main(void) { int y, m, d; int ay, am, ad; int by, bm, bd; printf("年:"); scanf("%d", &y); printf("月:"); scanf("%d", &m); printf("日:"); scanf("%d", &d); ay = by = y; am = bm = m; ad = bd = d; yesterday(&ay, &am, &ad); tomorrow(&by, &bm, &bd); printf("前の日:%d年%d月%d日\n", ay, am, ad); printf("次の日:%d年%d月%d日\n", by, bm, bd); return 0; } <質問> ・*d = day[isleap(*y)][*m]; たとえば、日付が2000年3月31日だとして、isleap関数に引数として2000が渡されますよね? そして、閏年かどうかの判断がされて、この場合閏年なので1が返されます。 *d = day[1][3]?となりますよね? そして、day関数に[1][3]が渡されますよね? int day[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; }; この場合、[1][3]といったら、29なのに31になってません? あと、day関数でreturnで数値を返していないのはどうしてでしょうか?
ポインタ
ポインタ
以下はポインタを使って西暦y年m月d日の≪前の日≫あるいは≪次の日≫の日付を求めてプログラムです。
Re:ポインタ
> *d = day[1][3]?となりますよね?
> そして、day関数に[1][3]が渡されますよね?
dayという名前の関数はありません。
> int day[2][13] = {
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> };
> この場合、[1][3]といったら、29なのに31になってません?
C言語の配列はゼロ始まりであることを再確認してください。
>あと、day関数でreturnで数値を返していないのはどうしてでしょうか?
引数でアドレスを渡しているからです。
> そして、day関数に[1][3]が渡されますよね?
dayという名前の関数はありません。
> int day[2][13] = {
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> };
> この場合、[1][3]といったら、29なのに31になってません?
C言語の配列はゼロ始まりであることを再確認してください。
>あと、day関数でreturnで数値を返していないのはどうしてでしょうか?
引数でアドレスを渡しているからです。
Re:ポインタ
ついでに…
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
この2行でコンパイルエラーが出ることにも留意してください。
下段の28は29が正しいですね。
それから、tomorrow関数のスペルが、実体と呼び出す箇所とで食い違っています。
>return (year % 4 == 0 && year % 100 != 0 || year % 400);
最後の条件はyearが400で「割り切れない」ことを意味します。
本来の意図とは逆のはずです。
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
この2行でコンパイルエラーが出ることにも留意してください。
下段の28は29が正しいですね。
それから、tomorrow関数のスペルが、実体と呼び出す箇所とで食い違っています。
>return (year % 4 == 0 && year % 100 != 0 || year % 400);
最後の条件はyearが400で「割り切れない」ことを意味します。
本来の意図とは逆のはずです。
Re:ポインタ
> *d = day[1][3]?となりますよね?
> そして、day関数に[1][3]が渡されますよね?
box様のご指摘のように、day関数はありませんね。
このプログラムで関数として存在しているのは、
・閏年を求める関数
・前日と次の日を求める関数
・main関数
上記の4種類だけで、dayは配列としてしか存在していません。
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> この場合、[1][3]といったら、29なのに31になってません?
これも配列の始まりは 0からなので、2行目左から0、1、2、と数えると、day[1][3]は31になりますね。
> そして、day関数に[1][3]が渡されますよね?
box様のご指摘のように、day関数はありませんね。
このプログラムで関数として存在しているのは、
・閏年を求める関数
・前日と次の日を求める関数
・main関数
上記の4種類だけで、dayは配列としてしか存在していません。
> { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
> この場合、[1][3]といったら、29なのに31になってません?
これも配列の始まりは 0からなので、2行目左から0、1、2、と数えると、day[1][3]は31になりますね。
Re:ポインタ
> ・前の日付を求める関数で
> たとえば日付が2000年3月1日だとすると、
> *d = day[1][3]
> { 0, 31, 29, 31, 30, 31…}
> 左から4番目で31になりますよね?
> でも、前の日付なので、29にならないといけないですよね?
根本的に理解できていないようです。
yesterday関数において、
*y==2000, *m==3, *d==1 ですね。
このとき、最初のif文のelse句を通ります。
そうすると、*mが2になりますね。
そして、2000年はうるう年ですので、day[1][2]を参照します。
この値はうるう年の2月の日数(つまりうるう年の2月の最終日)ですので、
結果として、2000年3月1日の前日は2000年2月29日となります。
コンピューターになったつもりで、ソースコードの一行一行を
じゅうぶんに吟味してください。
> ・(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
> これで、どうして閏年が求められるのですか?
うるう年の定義がそうなっているからです。
西暦年が4で割り切れて100で割り切れない場合、うるう年とする。
ただし、西暦年が400で割り切れる場合、うるう年とする。
この文章で書いたことをC言語のソースに落とし込んだだけです。
> たとえば日付が2000年3月1日だとすると、
> *d = day[1][3]
> { 0, 31, 29, 31, 30, 31…}
> 左から4番目で31になりますよね?
> でも、前の日付なので、29にならないといけないですよね?
根本的に理解できていないようです。
yesterday関数において、
*y==2000, *m==3, *d==1 ですね。
このとき、最初のif文のelse句を通ります。
そうすると、*mが2になりますね。
そして、2000年はうるう年ですので、day[1][2]を参照します。
この値はうるう年の2月の日数(つまりうるう年の2月の最終日)ですので、
結果として、2000年3月1日の前日は2000年2月29日となります。
コンピューターになったつもりで、ソースコードの一行一行を
じゅうぶんに吟味してください。
> ・(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
> これで、どうして閏年が求められるのですか?
うるう年の定義がそうなっているからです。
西暦年が4で割り切れて100で割り切れない場合、うるう年とする。
ただし、西暦年が400で割り切れる場合、うるう年とする。
この文章で書いたことをC言語のソースに落とし込んだだけです。