- ベストアンサー
C言語で作成した万年カレンダーのプログラムがエラーになる件について
- C言語で作成した万年カレンダーのプログラムがエラーになります。
- 日付を入力して実行すると止まってしまい、どこがおかしいのかわかりません。
- 初心者のため、皆さんのアドバイスをいただけると助かります。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
#include <stdio.h> int main(void) { int mdata[12]={ 31 ,28 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31 }; /*一月の日数*/ char youbi[7][4]={"日","月","火","水","木","金","土"}; /*曜日*/ int year ,month ,date ,a ,b ,ichi ,uruu=0 ,days=0; printf("西暦="); scanf("%d",&year); /*西暦入力*/ printf("月="); scanf("%d",&month); /*月名入力*/ printf("日="); scanf("%d",&date); /*日付入力*/ for(a = 1900 ; a < year ; a++) /*西暦1990年からスタート*/ { /*入力された年になったら抜ける*/ if(a%4 == 0 && (a%100 != 0 || a%400 == 0)) { /*うるう年の際は通常より*/ uruu=uruu+1; /*1日増える*/ } } if(y%4 == 0 && (y%100 != 0 || y%400 == 0)) /*入力された年がうるう年か調べる*/ { mdata[1] = 29; /*うるう年なら2月は29日にする*/ } for(b = 0 ; b < month-1 ; b++) /*入力された月よりも前の各月の*/ { /*日数を足しこんでいく。*/ days = mdate[b]+days; } days = days+date; /*入力された年内の日数*/ zure = (year-1900)+uruu+days; /*365=7*52+1なので1年でひとつずれる*/ ichi = zure%7; /*曜日の位置を求める*/ printf("%s",youbi[ichi]); /*多分文字列指定にしないと駄目ですよね*/ return 0; } 20年ぶりに考えてみました。 ですから正しいとは限りません。 変数名を出来るだけ分かりやすいものに変えたつもりです。 西暦入力のデータ型を変える(10万年対応(^_^;))とか、不正入力チェックも入れたいですね。 基点(1990年1月1日)からの総日数(alldays)を出しても面白いと思います。 alldays = (year-1900)*365 + uruu + days
その他の回答 (5)
こんにちは。 プログラミングにおいて問題が発生した場合は、 どこまで上手く動作しているのか、 どこで上手くいかなくなったのか、 を見極める作業が必要だと思います。 そのためには、#2さんが言われているように、プログラムの要所要所にprintfなど を用いて、その実行時点の実際の変数等の中身がどうなっているのか(意図した 値なのか、そうでないのか)を確認した方が良いと思います。 また、デバッガが使用できる環境であれば、デバッガを用いて、プログラムを ステップ実行しながら変数の中身を確認するのも良いと思います。 ご提示のソースで、実行時にエラーになるのは、2つ目のforループ内の処理に 問題がある為だと思われます。 1)なぜ、m+=1 しているのか不明? ・これは必要ないと思われます。 2)1)のため、ループ終了条件が成立しなくなり、ループが終了しない。 3)2)のため、配列 d[] のアクセス用のインデックス値 b が要素数の上限を オーバーしてしまい、不正エリアにアクセスしてしまう。 4)3)のため、実行時エラーが発生していると思われます。 forループ内に、printf等で参照している変数の値を表示するようにしてみれば、 その状態がわかると思います。 ※この他にも、他の回答者の方が言われているように、幾つか問題点がある ようです。 参考までに(参考になるかどうかわかりませんが)、ご提示のソースの原型を できるだけ保ちつつ修正を加えたソースを作成してみました。 宜しければ試してみて下さい。(※下記リンク先参照) ※下記ソース内にコメントとして、問題点、修正点などを記述してあります。 ■修正版ソース http://ideone.com/RfcQK 以上です。
- wild_kit
- ベストアンサー率32% (581/1804)
訂正 変数zureが宣言されていないので、追加してください。 コメント「1990年からスタート」は「1900年からスタート」 days = mdate[b]+days; は、 days = mdata[b]+days; 尚、youbi[ichi][0]はyoubi[ichi]と省略できます。 論理演算部分は正しいのではないかと思いますが、実際に動かして確認出来る環境にはありません。 1900年なら1900%4 == 0<T>,1900%100 != 0<F>,1900%400 ==0<F> T && (F||F)ですから、T && FでFでしょう。(=平年) 2000年なら、2000%4 == 0<T>,2000%100 != 0<F>,2000%400 == 0<T> T && (F||T)ですから、T && Tとなり、Tでしょう。(うるう年) あるいは、2004年なら2004%4 == 0<T>,2004%100 != 0<T>,2004%400 == 0<F> T && (T||F)ですから、T && Tとなり、Tでしょう。(うるう年) <T=真、F=偽> もしかすると演算の優先順位がからんで期待通りにならないのかもしれませんね。 その時は括弧でくくってください。
お礼
本当にありがとう!!すごい参考になりました!!
- asuncion
- ベストアンサー率33% (2127/6289)
みんな、そろそろ閏年の判定をちゃんとしたらどうかな。 西暦が4で割り切れて100では割り切れない、もしくは400で割り切れるのが閏年。 だから、1900年は平年で2000年は閏年。
- kmee
- ベストアンサー率55% (1857/3366)
前と変わってないんだけどなぁ for(b = 0 ; b <= m-1 ; b++){ printf("開始時: b=%d,e=%d,m=%d\n",b,e,m); e = d[b]+e; printf("e=..後: b=%d,e=%d,m=%d\n",b,e,m); m += 1; printf("m+=1後: b=%d,e=%d,m=%d\n",b,e,m); printf("次は..: b=%d, ループ条件 <= m-1(%d)\n",b + 1, m-1); } printf("for終了:b=%d,e=%d,m=%d\n",b,e,m); printf("条件..: b=%d, ループ条件 <= %d (= m-1)\n",b, m-1); これで実行してみてください。ループの各所で各変数がどんな値になっているかが表示されます。 おそらく、その結果はあなたの意図していないものになっているはずです。 一度、各コマンドが何をやっているかの説明を日本語(あなたが他の言語の方がわかりやすいなら英語でも中国語でもいいですが)で書いてみることをお勧めします。できるだけ具体的に。 例えば、m+=1 なら 「mに1加える」ではなく「求める月mを次の月にする」といった具合に。 > printf("%c",youbi[cc]); ←調べてみたけど出力の仕方がいまいちわかんないです・・・ 本当に基本ですから、確実に憶えてください。 「%c」はマニュアルにはなんと書いてありました?例えば下のマニュアルには http://www.linux.or.jp/JM/html/LDP_man-pages/man3/printf.3.html > c (略)int 引き数を unsigned char に変換して、その結果に対応する文字を出力する(略) char youbi[7][4] ; と宣言してあります。 では、youbi[cc]の型は何だかわかりますか? 「文字」と「文字列」の違いは把握していますか?
- DarkMoon
- ベストアンサー率21% (225/1046)
5行目で char youbi[7][4]={"日","月","火","水","木","金","土"}; と宣言しているので printf("%c",youbi[cc]); では変数に入っている値を呼び出せません。 youbi[ ][ ] というように二つのカギ括弧に数値を入れて指定します。
お礼
わかりやすい説明から修正ソースまで 親切にありがとうございました!!無事にプログラムを完成する事ができました