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

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

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

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

Q&A

解決済

5回答

3520閲覧

入力した年月日の前の日を求める関数

takemark20

総合スコア9

C

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

0グッド

1クリップ

投稿2018/05/02 10:04

前提・実現したいこと

C言語で、西暦 y 年 m 月 d 日の前の日の日付を求めるプログラムを書きました。

発生している問題・エラーメッセージ

日がその月の最終日でなくても、月まで-1されてしまいます。

該当のソースコード

C

1#include<stdio.h> 2 3void yesterday(int *y, int *m, int *d) 4{ 5 int feb; 6 7 //閏年かどうか 8 if(*y%4==0 && *y%100!=0 || *y%400==0){ 9 feb = 29; 10 }else feb = 28; 11 12 //前の日の計算 13 *d = *d - 1; 14 if(*d==0){ 15 if(*m==3){ 16 *d = feb; 17 }else if(*m==5 || *m==7 || *m==10 || *m==12){ 18 *d = 30; 19 }else *d = 31; 20 } 21 22 //前の月の計算 23 *m = *m - 1; 24 if(*m==0){ 25 *m = 12; 26 *y = *y - 1; 27 } 28} 29 30int main() 31{ 32 int y, m, d; 33 34 //西暦月日の入力 35 printf("西暦は?\n"); scanf("%d", &y); 36 printf("月は?\n"); scanf("%d", &m); 37 printf("日は?\n"); scanf("%d", &d); 38 39 //前の日の出力 40 printf("%d年%d月%d日の前の日は", y, m, d); 41 yesterday(&y, &m, &d); 42 printf("%d年%d月%d日です。\n", y, m, d); 43 44 return 0; 45} 46

試したこと

//前の月の計算 の所が問題なのはわかるんですが、どう直したらいいのかわかりません。
if文でdが~の時にm - 1にしたらいいのでしょうか?

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

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

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

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

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

guest

回答5

0

月も変更しないといけないのは、日が0になるときだけですよね。

C

1//前の日の計算 2*d = *d - 1; 3if(*d==0){ 4 if(*m==3){ 5 *d = feb; 6 }else if(*m==5 || *m==7 || *m==10 || *m==12){ 7 *d = 30; 8 }else *d = 31; 9 10 // 前の月の計算 11 ... 12}

ただ、こんな風にネストしていくと処理を追いづらくなります。
次のようにアーリーリターンを利用すると良いでしょう。

C

1void yesterday(int *y, int *m, int *d) { 2 dを一日前にする; 3 if(dが0でない) return; 4 5 dに正しい値をセット; 6 mをひと月前にする; 7 if(mが0でない) return; 8 9 mに正しい値をセット; 10 yを一年前にする; 11}

投稿2018/05/02 10:09

編集2018/05/02 10:10
LouiS0616

総合スコア35660

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

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

0

1.西暦1年1月1日からの任意の日付の通算日数を求める関数を作る
2.任意の通算日数から日付けを算出する関数を作る
3.西暦 y 年 m 月 d 日の通算日数を求め、1引いて、日付けを算出する

バッチシ

#1.2.は、ぐぐるとでてきます

投稿2018/05/02 12:48

y_waiwai

総合スコア87747

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

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

0

回答は既に付いているので、別のアドバイス。
閏年かどうか判断が必要なのは、3月1日の前日を求めるときだけなので、

C

1~~~ 2 *d = *d - 1; 3 if(*d==0){ 4 if(*m==3){ 5 if(*y%4==0 && *y%100!=0 || *y%400==0){ 6 *d = 29; 7 } else { 8 *d = 28; 9 } 10~~~

のようにすると、ほとんどのケースで無駄な処理を省けます。変数febも不要。

投稿2018/05/02 12:33

otn

総合スコア84491

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

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

0

ベストアンサー

月をまたぐ処理は入力された日付が「1」の場合のみ、のはずですが、それと関係なく月を一律前月にしてしまっているのが問題。

//前の日の計算 *d = *d - 1; if(*d==0){ if(*m==3){ *d = feb; }else if(*m==5 || *m==7 || *m==10 || *m==12){ *d = 30; }else *d = 31; *m = *m - 1; // <- ここで月またぎ分を減算 } //前の月の計算 //*m = *m - 1; // <- ここは不要 if(*m==0){ *m = 12; *y = *y - 1; }

投稿2018/05/02 10:14

tkturbo

総合スコア5572

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

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

takemark20

2018/05/02 15:38

回答ありがとうございます。 わかりやすっかったです。 ほかの皆さんもありがとうございました。
guest

0

struct tm → time_t → struct tmと変換すれば、よろしくやってくれます。

c

1#include <time.h> 2 3void yesterday(int *y, int *m, int *d) 4{ 5 struct tm st = {0}; 6 time_t tt; 7 8 st.tm_year = *y - 1900; 9 st.tm_mon = *m - 1; 10 st.tm_mday = *d - 1; /* 1日前の日付を設定 */ 11 12 tt = mktime(&st); 13 st = *localtime(&tt); 14 *y = st.tm_year + 1900; 15 *m = st.tm_mon + 1; 16 *d = st.tm_mday; 17}

投稿2018/05/02 10:11

編集2018/05/02 10:35
hichon

総合スコア5737

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問