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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

解決済

4回答

2088閲覧

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

kamecha

総合スコア41

C

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

1グッド

0クリップ

投稿2018/01/11 14:54

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

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

lang

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

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

###コード

lang

1void decrement_date(int *y, int *m, int *d) 2{ 3 *d -= 1; 4 if(*d == 0){ 5 switch(*m){ 6 //前月が31日 7 case 2: 8 case 4: 9 case 6: 10 case 8: 11 case 10: 12 case 11: 13 *m -= 1; 14 *d = 31; 15 break; 16 17 //前月が30日 18 case 5: 19 case 7: 20 case 9: 21 case 12: 22 *m -= 1; 23 *d = 30; 24 break; 25 26 //前月が閏年によって変化する 27 case 3: 28 *m -= 1; 29 if(*y % 4 == 0){ 30 *d = 29; 31 }else{ 32 *d = 28; 33 } 34 break; 35 36 //年が変わる 37 case 1: 38 *y -= 1; 39 *m = 12; 40 *d = 31; 41 break; 42 } 43 } 44}

increment_date()は省略しました。

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

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

###補足情報
書籍: 新明解C言語 入門編
演習 10-2

Bulls👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

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

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

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

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

C

1void decrement_date(int *y,int *m,int *d){ 2 *d -= 1; 3 if(*d == 0){ 4 *m -= 1; 5 switch(*m){ 6 // 31日の月 7 case 1: 8 case 3: 9 case 5: 10 case 7: 11 case 8: 12 case 10: 13 case 12: 14 *d = 31; 15 break; 16 17 // 30日の月 18 case 4: 19 case 6: 20 case 9: 21 case 11: 22 *d = 30; 23 break; 24 25 // 閏年によって変化する2月 26 case 2: 27 if(( *y % 4 ) == 0 && 28 (( *y % 100 ) != 0 || 29 ( *y % 400 ) == 0)){ 30 *d = 29; 31 }else{ 32 *d = 28; 33 } 34 break; 35 36 //年が変わる 37 case 0: 38 *y -= 1; 39 *m = 12; 40 *d = 31; 41 break; 42 } 43 } 44}

投稿2018/01/11 15:58

編集2018/01/11 15:59
namnium1125

総合スコア2043

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamecha

2018/01/11 16:03

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

0

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

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

*m --;

投稿2018/01/11 15:26

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamecha

2018/01/11 15:35

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

0

ベストアンサー

こんにちは。

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

*m --;

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

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

投稿2018/01/11 15:16

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamecha

2018/01/11 15:38

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

0

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

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

投稿2018/01/11 15:19

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamecha

2018/01/11 15:36

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問