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

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

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

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

Q&A

解決済

4回答

6590閲覧

2つの西暦で入力された年月日から,その間の日数を計算するプログラムを作成するプログラムのソースと説明を教えていただきたいです。

NB16

総合スコア14

C

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

0グッド

0クリップ

投稿2019/06/19 06:52

編集2019/06/19 07:17

あっているかは分かりませんが途中までのプログラムを組んでみました。その他をどのように処理すればいいのかが分かりません。
※配列は使わず、関数だけを使ってお願いします。

考え方としては,例えば,1967/8/7 から 2009/6/12 までを計算する場合(うるう年を考慮)、

A. 開始月の日数(1967/8/7から8/31までの日数) B. 開始年の残りの月の日数(1967/9,10,11,12の日数) C. 開始年の翌年から終了年前年までの年の日数(1968 ~ 2008年までの日数) D. 終了年の終了月前月までの日数(2009/1,2,3,4,5の日数) E.終了月の日数(2009/6/1から2009/6/12までの日数)

C

1コード 2/* daycount.c */ 3 4#include <stdio.h> 5 6//関数のプロトタイプ宣言 7int uruu(int y); 8int monthday(int y, int m); 9int remainmonth(int y, int m); 10int previousmonth(int y, int m); 11int lastyearmonth(int y, int m); 12int endmonth(int y, int m); 13 14//--------------------------------------------------------------- 15int main(){ 16 int year_a,month_a,day_a; //開始年月日 17 int year_b,month_b,day_b; //終了年月日 18 int days; //日数積算用変数 19 int i; 20 21 days = 0; //変数の初期化 22 23 printf("日数計算プログラム\n"); 24 printf("数え始める西暦年月日を入力してください(例 : 1967,8,7)\n"); 25 scanf("%d,%d,%d\n" ,&year_a, &month_a, &day_a); 26 printf(" 数え終わる西暦年月日を入力してください(例 : 2009,6,12)\n "); 27 scanf("%d,%d,%d" ,&year_b, &month_b, &day_b); 28 29 「処理」←ここの処理 30 31 32 printf("%d年%d月%d日 から %d年%d月%d日 までの日数は %d日です. \n", 33 year_a, month_a,day_a, year_b, month_b, day_b, days); 34 35 return 0; //システムに値0を返す 36} 37 38//うるう年かどうか判定し結果を返す 39//うるう年ならtrue(1),そうでないならfalse(0)を返す関数 40int uruu(int y){ 41 int ret; 42 if(y % 400 == 0 || (y % 100 != 0 && y % 4 == 0) ){ 43 ret = 1; 44 }else{ 45 ret = 0; 46 } 47 return(ret); //結果を返す 48} 49 50//A: 年,月を受け取り、その月の日数を返す関数(うるう年も考慮) 51int monthday(int y,int m){ 52 int d,ret; 53 for(y = 1; y < y+1; y++){ //その指定した年の間の時だけループ 54 for(m = 1; m < m+1; m++){ //その指定した月の間だけループ 55 if(m == 2){ 56 ret = uruu(y); 57 if(ret == 1){ 58 d -= 29; 59 }else{ 60 d -= 28; 61 } 62 } 63 if(m == 4 || m == 6 || m == 9 || m == 11){ 64 d -= 30; 65 }else{ 66 d -= 31; 67 } 68 } 69 } 70 71 return(d); //結果を返す 72} 73 74//B: 開始年の残りの月の日数 75int remainmonth(int y,int m){ 76 int d,ret; 77 for(y = 1; y < y+1; y++){ //指定された年の間だけループ 78 for(m = 1; 1 <= m && m <= 12; m++){ //指定された月から12月までの間だけループ 79 if(m == 2){ 80 ret = uruu(y); 81 if(ret == 1){ 82 d += 29; 83 }else{ 84 d += 28; 85 } 86 }else{ 87 if(m == 4 || m == 6 || m == 9 || m == 11){ 88 d += 30; 89 }else{ 90 d += 31; 91 } 92 } 93 } 94 } 95 return(d); //結果を返す 96} 97 98//C: 開始年の翌年から終了年前年までの年の日数 99int previousmonth(int y,int m){ 100 int d,end,ret; 101 for(y = y+1; y < end; y++){ //開始年の翌年から終了年の前の年までのループ 102 for(m = 1; 1 <= m && m<= 12; m++){ //指定された月から12月までのループ 103 if(m == 2){ 104 ret = uruu(y); 105 if(ret == 1){ 106 d -= 29; 107 }else{ 108 d -= 28; 109 } 110 }else{ 111 if(m == 4 || m == 6 || m == 9 || m == 11){ 112 d -= 30; 113 }else{ 114 d -= 31; 115 } 116 } 117 } 118 } 119 return(d); //結果を返す 120} 121 122//D: 終了年の終了月前月までの日数 123int lastyearmonth(int y, int m){ 124 int d,end,ret; 125 for(y = end; y <= end; y++){ 126 for(m = 1; m <= end-1; m++){ 127 if(m == 2){ 128 ret = uruu(y); 129 if(ret == 1){ 130 d -= 29; 131 }else{ 132 d -= 28; 133 } 134 }else{ 135 if(m == 4 || m == 6 || m == 9 || m == 11){ 136 d -= 30; 137 }else{ 138 d -= 31; 139 } 140 } 141 } 142 } 143 return(d); 144} 145 146//E: 終了月の日数 147 148「処理」 149 150 151

<実行結果>
日数計算プログラム
数え始める西暦年月日を入力してください(例 : 1967,8,7)
1967,8,7
数え終わる西暦年月日を入力してください(例 : 2009,6,12)
2009,6,12
1967年8月7日 から 2009年6月12日 までの日数は 15285日です.

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

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

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

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

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

y_waiwai

2019/06/19 07:03

このままではコードが見づらいので、質門を編集し、<code>ボタンで、出てくる’’’の枠の中にコードを貼り付けてください
NB16

2019/06/19 07:09

丁寧に修正点を言っていただきありがとうございます。
jimbe

2019/06/19 12:16

イキナリ全部を書こうとせず, 例えば1月1日から同年1月31日まで限定を作って動作させ, 次に同年2月1日まで限定を作って...と段階を踏んでは如何でしょう. > for(y = 1; y < y+1; y++){ このループは終わりそうにありません.
guest

回答4

3

ベストアンサー

年月日を使うと難しくなるので、話を簡単にするために、西暦 0 年 1 月 1 日からの日数を使いましょう。年月日からこの日数を求め、それを引き算すれば二つの日の差が出ます。

基本的に 1 年は 365 日です。だから、単純計算すると、2019 年 1 月 1 日は 0 年 1 月 1 日から数えて365 × 2019 日後です。しかしうるう年というものがあるので、それを計算に入れなければいけません。うるう年は 4 年に 1 回ありますが、その年が 100 で割り切れたらうるう年ではありません。しかし 400 で割り切れたらうるう年です。たとえば西暦 2000 年はうるう年ですが、2100 年は違います。
その年の前年までにうるう年が何回あったかを数え、その回数を日数に足してください。

これで、任意の 1 月 1 日を 0 年 1 月 1 日からの日数に直すことができるようになりました。

次はその月の 1 日までの日数を足します。例えば 1 月は 31 日まであるので、2 月 1 日は 1 月 1 日の 31 日後ということになります。同様に 3 月 1 日は 31 + 28 日後、4 月 1 日は 31 + 28 + 31 日後になります。この時、その年がうるう年ならば 3 月以降はもう 1 日足してください。

これで任意の年、任意の月の 1 日を 0 年 1 月 1 日からの日数に直すことができるようになりました。

最後に日を足します。2019 年 6 月 19 日であれば、2019 年 6 月 1 日までの日数を求め、それに 18 を足します。

これで任意の日付を 0 年 1 月 1 日からの日数に直すことができるようになりました。後はそれを引き算するだけです。

よって、作成しなければならない関数は次のようになります。

  • 年を引数に、その年がうるう年かどうかを返す関数 int isLeapYear(int year)
  • その年の 1 月 1 日の日数を返す関数 int getDaysFromYear(int year)
  • isLeapYear および getDaysFromYear を使い、その年、その月の 1 日までの日数を返す関数 int getDaysFromYearMonth(int year, int month)
  • getDaysFromYearMonth を使い、その日までの日数を返す関数 int getDays(int year, int month, int day)
  • getDays を使い、入力からその日までの日数を返す関数 int getDaysFromConsole()
  • それらを用いて結果を計算する main 関数
  • 結果を出力する関数 void output(int days)

以上を作ってください。

投稿2019/06/19 07:53

編集2019/06/19 07:55
Zuishin

総合スコア28656

shoshi, majiponi, ds-kawasaki👍を押しています

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

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

majiponi

2019/06/19 09:46

仕様を詰めましょう。(標準関数だけで簡単に実装できる)1970年以降だけなのか、ユリウス暦を使っていた1582年以前も含むのかでも答えは変わってきます。
Zuishin

2019/06/19 10:01

これ、質問じゃなくて回答です。
Zuishin

2019/06/19 10:02

あと、初心者用の課題なので、グレゴリオ暦以外には考えられません。
guest

1

C

1#include <stdio.h> 2 3int days(int y, int m, int d) 4{ 5 static int t[] = { 306,337,0,31,61,92,122,153,184,214,245,275 }; 6 return y -= m < 3, y*365 + y/4 - y/100 + y/400 + t[m-1] + d; 7} 8 9int main(void) 10{ 11 printf("%d\n", days(2009, 6, 12) - days(1967, 8, 7)); 12}

関数 days は、0年3月1日からの通算日を求めます。
配列 t は、m月1日がその年の 3月1日から何日後かの表です。
1月と 2月は前年の 3月1日から何日後かの値になっています。
そのため、y -= m < 3 で y を前年にしています。

[追記]
static を追加しました。これは非常に重要なことです。

投稿2019/06/19 09:41

編集2019/06/19 10:09
kazuma-s

総合スコア8224

pepperleaf👍を押しています

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

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

pepperleaf

2019/06/19 14:39

3月1日から、、ってのは、昔の定番だった気がするのですが、今は流行らないのでしょうか? それともなんか問題があったのでしょうか。
NB16

2019/06/19 15:52

これだと2009,6,12と1967,8,7という決まった数の差しか求めることができないのではないのでしょうか? 数が決まっていない場合はどのようにもとめますか?
kazuma-s

2019/06/19 20:09

変数を使えばいいだけの話では? year_a とか、month_a とか。
guest

0

参考情報

  • プログラミング技術 C言語

2つの日付(西暦、月、日)を入力して、その日の日数差を計算して表示するプログラミングを作成しなさい
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1242873317

投稿2019/06/19 13:35

katoy

総合スコア22322

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

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

0

考え方、を書いておきます

  1. 年月日を与えたら、西暦1年1月1日からの通算日数を求める関数を書きます(ぐぐればコード出てきますね)
  2. 通算日数を与えたら、西暦年、月、日を求める関数を書きます
  3. そこから、時分秒から、西暦1年1月1日0時0分0秒からの通算秒数を求める関数を書きます
  4. あとは、通算秒数通しの加算、減算などの処理を行い、そこから年月日時分秒を求めましょう

ああ、日数だけの計算なんですね。
なら3番は不要になりますね

投稿2019/06/19 07:08

編集2019/06/19 07:20
y_waiwai

総合スコア87682

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

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

NB16

2019/06/19 07:31

回答ありがとうございます。 私が書いたA,B,C,D,Eの考え方は不要でしょうか?
y_waiwai

2019/06/19 07:41

あなたのやりたいようにすればいいと思います。 私の方法は一つの例だと考えていただけるとよろしいかと。 んで、この程度以上のコードを書く場合は、VisualStudioやEclipseなど、ソースデバッグできる環境を用意したほうがいいかと思います。 コードの実行を途中で止め、変数のナカミを覗いたりもできるので、つまらないミスをなくせます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.54%

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

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

質問する

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

C

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