質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.05%

  • C

    2957questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

閏年の計算方法について etc...

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 421

nonbirikame

score 32

前提

書籍で勉強している学生です。
書籍の解答がないため問題のヒントや解説をしていただけると嬉しいです。

問題

西暦 *y年 *m月 *d日の日付を、”前の日”あるいは”次の日”の日付に更新する関数を作成せよ。

void decrement_date(int *y, int *m, int *d){/*...*/}
void increment_date(int *y, int *m, int *d){/*...*/}


閏年を考慮して計算を行うこと。

コード

void decrement_date(int *y, int *m, int *d)
{
    *d -= 1;
    if(*d == 0){
        switch(*m){
            //前月が31日
            case 2:
            case 4:
            case 6:
            case 8:
            case 10:
            case 11:
                *m -= 1;
                *d = 31;
                break;

            //前月が30日
            case 5:
            case 7:
            case 9:
            case 12:
                *m -= 1;
                *d = 30;
                break;

            //前月が閏年によって変化する
            case 3:
                *m -= 1;
                if(*y % 4 == 0){
                    *d = 29;
                }else{
                    *d = 28;
                }
                break;

            //年が変わる
            case 1:
                *y -= 1;
                *m = 12;
                *d = 31;
                break;
        }
    }    
}


increment_date()は省略しました。

疑問点

閏年の計算方法がよく分からずに行っているので、厳密な計算方法を知りたいです。
少し調べてみましたが、しっかりとした理解が出来なかったため、解説をして頂けると有り難いです。

蛇足になるのですが、変数の数字を1減らしたい時に
*m --;
では、上手く動作せず
*m -= 1;
としたら上手く動作したのがなぜだか分からないため、それもできれば教えて頂きたいです。

補足情報

書籍: 新明解C言語 入門編
演習 10-2

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+1

こんにちは。

例えば、このサイトの説明は判りやすいと思います。

*m --;
では、上手く動作せず
*m -= 1;

演算子の優先順位の問題です。
間接演算子* と 後置デクリメント演算子--では後者の方が優先順位が高いので、*m --;はmのアドレスがデクリメントされるだけです。
間接演算子* と 代入演算子-=では前者の方が優先順位が高いのでmの指す先に対して、-=の処理が実行されます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/12 00:38

    引用のサイト有り難うございます。
    分かりやすいです!

    キャンセル

+1

閏年の条件:
(西暦が4で割り切れる && 西暦が100で割り切れない || 西暦が400で割り切れる)

疑問点2:
以下が意図した結果にならないのは、デリファレンス(*)より、デクリメント(--)の方が優先順位が高いためです。

*m --;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/12 00:35

    簡潔で分かりやすい解説有り難いです!

    キャンセル

+1

疑問点に対する回答ではないのですけれど、気になったことがあったので回答させてください。

31日がない月って、「西向く侍」(2,4,6,9,11月)ですよね?偶数月だと思われたのでしょうか?

あとmから1を引く処理が重複してますから、先に引くように直した方がいいのではないでしょうか?その方が月との対応も見やすくなると思います。

以下あまりテストはしていない拙いコードですが、参考になれば幸いです。

void decrement_date(int *y,int *m,int *d){
  *d -= 1;
  if(*d == 0){
    *m -= 1;
    switch(*m){
      // 31日の月
      case 1:
      case 3:
      case 5:
      case 7:
      case 8:
      case 10:
      case 12:
        *d = 31;
        break;

      // 30日の月
      case 4:
      case 6:
      case 9:
      case 11:
        *d = 30;
        break;

      // 閏年によって変化する2月
      case 2:
        if(( *y % 4 ) == 0 &&
        (( *y % 100 ) != 0 ||
        ( *y % 400 ) == 0)){
          *d = 29;
        }else{
          *d = 28;
        }
        break;

      //年が変わる
      case 0:
        *y -= 1;
        *m = 12;
        *d = 31;
        break;
    }
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/12 01:03

    なるほど!
    確かに *m-=1 は、あらかじめ処理を行っていた方が、後の処理が楽になりますね。
    有り難うございます。

    キャンセル

0

閏年は、年が、
1.400で割り切れれば閏年
2.そうじゃなくて、100で割り切れれば平年
3.そうじゃなくて、4で割り切れれば閏年
です。

*m --;ですが、後置の--は前置の*より優先度が高いので、無駄な括弧を付けると*(m--);という意味になります。
*m -= 1;は、無駄な括弧を付けると(*m) -= 1;です。これは(*m)--;と同じです。
演算子の優先順序は基本なので、覚えましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/12 00:36

    ()つきの説明分かりやすいです!
    演算子の優先順位・・・
    しっかり覚えときます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    2957questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。