ポインタ

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
馬鹿太郎

ポインタ

#1

投稿記事 by 馬鹿太郎 » 16年前

以下はポインタを使って西暦y年m月d日の≪前の日≫あるいは≪次の日≫の日付を求めてプログラムです。
#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で数値を返していないのはどうしてでしょうか?

馬鹿太郎

Re:ポインタ

#2

投稿記事 by 馬鹿太郎 » 16年前

すいません。最後の[/pre]入れ忘れてしまいました。
見にくいです。

box

Re:ポインタ

#3

投稿記事 by box » 16年前

>  *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で数値を返していないのはどうしてでしょうか?

引数でアドレスを渡しているからです。

box

Re:ポインタ

#4

投稿記事 by box » 16年前

ついでに…

> { 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で「割り切れない」ことを意味します。
本来の意図とは逆のはずです。

Kou

Re:ポインタ

#5

投稿記事 by Kou » 16年前

>  *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になりますね。

馬鹿太郎

Re:ポインタ

#6

投稿記事 by 馬鹿太郎 » 16年前

box様、kou様回答ありがとうございます。

・前の日付を求める関数で
 たとえば日付が2000年3月1日だとすると、
 *d = day[1][3]
 { 0, 31, 29, 31, 30, 31…}
 左から4番目で31になりますよね?
 でも、前の日付なので、29にならないといけないですよね?
 この場合、どうしたらいいのでしょうか?

・(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
 これで、どうして閏年が求められるのですか?

kazuoni

Re:ポインタ

#7

投稿記事 by kazuoni » 16年前

閏年の求め方
ttp://iseries.fc2web.com/appx/leapyr.html

box

Re:ポインタ

#8

投稿記事 by box » 16年前

> ・前の日付を求める関数で
>  たとえば日付が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言語のソースに落とし込んだだけです。

馬鹿太郎

Re:ポインタ

#9

投稿記事 by 馬鹿太郎 » 16年前

ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る