年月日をもとに曜日を求めるプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
デミチェリス

年月日をもとに曜日を求めるプログラム

#1

投稿記事 by デミチェリス » 15年前

ツェラーの法則を使って入力した年月日で曜日を表示するプログラムですが、
このプログラムだとビルドエラーがでてしまいます。
おかしな点を教えてください、お願いします。
#include <stdio.h>

int main (void)
{
int year,month,date,day;

printf("西暦,月,日にちを入力してください\n");
printf("西暦:");
scanf("%d", &year);
printf("月:");
scanf("%d", &month);
printf("日にち:");
scanf("%d", &date);

day = (year+year/4-year/100+year/400+(13*month+8)/5+date)%7;

if (day=0)
printf("日曜日です。\n",day);
else if (day=1)
printf("月曜日です。\n",day);
else if (day=2)
printf("火曜日です。\n",day);
else if (day=3)
printf("水曜日です。\n",day);
else if (day=4)
printf("木曜日です。\n",day);
else if (day=5)
printf("金曜日です。\n",day);
else
printf("土曜日です。\n",day);

return 0;
}

DVDM

Re:年月日をもとに曜日を求めるプログラム

#2

投稿記事 by DVDM » 15年前

>>デミチェリスさん
[color=gray>> このプログラムだとビルドエラーがでてしまいます。[/color]
どの様なビルドエラーが出るのでしょうか。
私が見た感じ動きそうな気が致します。

気になった点は day=0 ~ day=5 の部分で、= ではなく == ではないでしょうか。

へろりくしょん

Re:年月日をもとに曜日を求めるプログラム

#3

投稿記事 by へろりくしょん » 15年前

0が日曜日、1が月曜日と固定なのですから、配列を使うとすっきりしますよ。

static const char *Week[/url] = {"日", "月", "火", "水", "木", "金", "土"};

printf("%s曜日です。\n", Week[day]);

DVDMさんのおっしゃっているようなバグが入り込む余地も無くなります。

toyo

Re:年月日をもとに曜日を求めるプログラム

#4

投稿記事 by toyo » 15年前

文法的な間違いはないのでプログラムにはエラーの原因はありません
DVDMさんの指摘された部分ですべて月曜日となるバグはありますが

以下規約と注意事項から引用です

※回答者が困る質問例※

「コンパイルしたのですが、うまくコンパイルできません」
この手の質問はよく回答に困ります。

使っているOS名・コンパイラ名・ライブラリ名も明記しましょう。
コンパイルエラーの質問時は必ず最低限のエラーメッセージも書きましょう。

ぜらーちん

Re:年月日をもとに曜日を求めるプログラム

#5

投稿記事 by ぜらーちん » 15年前

これこのままできちんと入力できます?
>>scanf("%d", &year);
ここを入力、エンター押すと
>>scanf("%d", &month);
とかスルーされていく気が(改行ががが

charの配列を取って、scanfの後に
gets(xxx);
って付けて改行をキャッチしてあげないとまずいと思います。

もしくはscanfを使わない等など

後は好みですが、列挙型を使って0~6 に日~月を割り当てて
最後のif~else文をswitch文にした方が好きかな


ちなみに私の環境でもそのプログラム(コピペ)にビルドエラーは出ませんでしたよ
XP VC++2010 コマンドプロンプト
cl test.cpp

白い時空

Re:年月日をもとに曜日を求めるプログラム

#6

投稿記事 by 白い時空 » 15年前

>>printf("日曜日です。\n",day);
printfの最後にあるdayは必要ないです。抜いてください。


>>ぜらーちんさん
scanfは問題ありません。
多分そういう問題はscanfの後、getsやgetcharを使うと出ると思います。

ぜらーちん

Re:年月日をもとに曜日を求めるプログラム

#7

投稿記事 by ぜらーちん » 15年前

>>白い時空さん

scanfは問題ないのは分かりますが、そのあとエンター分をキャッチしないとまずくないですか?
試しに今やってみましたが、西暦入力後、何も入力できないでプログラム終わります。

%sならいいでしょうが、数値しか取れない%dだとまずいと思います。

>>多分そういう問題はscanfの後、getsやgetcharを使うと出ると思います。
むしろ、やらないとダメです。

へろりくしょん

Re:年月日をもとに曜日を求めるプログラム

#8

投稿記事 by へろりくしょん » 15年前

>scanfは問題ないのは分かりますが、そのあとエンター分をキャッチしないとまずくないですか?
>試しに今やってみましたが、西暦入力後、何も入力できないでプログラム終わります。

書式指定子に %d を与えた場合、空白文字は読み飛ばされると思うのですが。


>%sならいいでしょうが、数値しか取れない%dだとまずいと思います。

>>多分そういう問題はscanfの後、getsやgetcharを使うと出ると思います。
>むしろ、やらないとダメです。

最初の scanf("%d", &year); のコードで改行コードは入力バッファに残りますが、続く
scanf("%d", &month); では読み飛ばされますので、問題は無いかと。

scanf("%d", &year); とした後に
scanf("%c", &hoge); とでもしたら変数 hoge には改行コードが入りますが。

ぜらーちん

Re:年月日をもとに曜日を求めるプログラム

#9

投稿記事 by ぜらーちん » 15年前

>>へろり
あーなるほど、覚えていたことを勘違いしてましたごめんなさい。
確かに改行読み飛ばされますね

↑の状態が必要なのは、%dであるから例えば[t]とかとかの文字を入力した時でしたね
かなり恥ずかしいことをしてました>>白い時空さん申し訳ない。

whileか何かでループさせて、入力
対応外の文字だと、再入力って形が望ましいですね。思い出しました。

デミチェリス

Re:年月日をもとに曜日を求めるプログラム

#10

投稿記事 by デミチェリス » 15年前

>使っているOS名・コンパイラ名・ライブラリ名も明記しましょう。
コンパイルエラーの質問時は必ず最低限のエラーメッセージも書きましょう。

・XP,Microsoft Visual C++2010,test.cppです。
・たぶん#include <stdio.h>の付け忘れで識別子見つかりませんでしたと、表示されたのだと思います。
 申し訳ないです。いちよ上記のプログラムで表示されました。


ただMicrosoft Visual C++2010のことなのですが、、
・年月日を入力するとコンパイルはされてると思うのですが、画面がすぐに閉じてしまいます。。なので結果がどうなったかはわかりません。


>0が日曜日、1が月曜日と固定なのですから、配列を使うとすっきりしますよ。
charは初めてなので使い方があってるかわかりませんが・・、

#include <stdio.h>

int main (void)
{
int year,month,date,day;
static const char *Week[7] = {"日", "月", "火", "水", "木", "金", "土"};

printf("西暦,月,日にちを入力してください\n");
printf("西暦:");
scanf("%d", &year);
printf("月:");
scanf("%d", &month);
printf("日にち:");
scanf("%d", &date);

day = (year+year/4-year/100+year/400+(13*month+8)/5+date)%7;

printf("%s曜日です。\n", Week[day]);

return 0;
}

デミチェリス

Re:年月日をもとに曜日を求めるプログラム

#11

投稿記事 by デミチェリス » 15年前

いちよへろりさんのやり方ででました。0コンマ、一瞬で表示されて消えたのですが、はっきり見えました。
ありがとうございます^^
ただ、これから今度はその年月のカレンダーを作ります。またわからないことがあったらここに書かせて頂きます。

DVDMさん、へろりさん、toyoさん、ぜらーちんさん、白い時空さん、ありがとうございました^^

ドラ

Re:年月日をもとに曜日を求めるプログラム

#12

投稿記事 by ドラ » 15年前

ツェラーの公式は、1月,2月を前年の13月,14月として扱わないと計算が狂いますよ。

>画面がすぐに閉じてしまいます。
コマンドプロンプトから実行ファイル名を指定して起動するとか、
main関数でリターンする前に getchar(); を書いておけばいいのではないですか?
今のような確認方法ではこの先やってられないと思います。

バグ

Re:年月日をもとに曜日を求めるプログラム

#13

投稿記事 by バグ » 15年前

×いちよ
○一応(いちおう)

デミチェリス

Re:年月日をもとに曜日を求めるプログラム

#14

投稿記事 by デミチェリス » 15年前

>コマンドプロンプトから実行ファイル名を指定して起動するとか、
main関数でリターンする前に getchar(); を書いておけばいいのではないですか?
今のような確認方法ではこの先やってられないと思います。

・デバックなしでやるようにしたら、とりあえず問題は解決しました^^

>×いちよ ○一応(いちおう)

・そうですね、幼稚言葉というやつですね。一応=いちおう=いちよ、だと思って使ってました。すいません。



・カレンダーの表示は未だ、日にちの表示で迷っています。
 printf("---------------------\n");の下からが表示されないです。

#include <stdio.h>

int main (void)
{
int year,month,date,day,i,e;
static char *Week[7] = {"日", "月", "火", "水", "木", "金", "土"};

printf("西暦,月,日にちを入力してください。\n");
printf("西暦:");
scanf("%d", &year);
printf("月:");
scanf("%d", &month);
printf("日:");
scanf("%d", &date);

day = (5 * year / 4 - year / 100 + year / 400 + (26 * month + 16) / 10 + date ) % 7;

printf("%s曜日です。\n", Week[day]);

i = 1;

printf(" ** %d年%d月 **\n", year, month);
printf(" 日 月 火 水 木 金 土\n");
printf("---------------------\n");

while( i <= day )
{
printf(" ");

i = i + 1;
}

if (month == 1 || 3 || 5 || 7 || 8 || 10 || 12)
e <= 31;
else if (month == 4 || 6 || 9 || 11 )
e <= 30;
else
  e == 28;

while( i <= e)
{
printf(" %d", i);

if ( (i + e) % 7 == 0)
printf("\n");

}

return 0;
}

へろりくしょん

Re:年月日をもとに曜日を求めるプログラム

#15

投稿記事 by へろりくしょん » 15年前

if (month == 1 || 3 || 5 || 7 || 8 || 10 || 12)

上記のコードは
if(month == 1 || 3 != 0 || 5 != 0.....
というコードと等価です。

if(month == 1 || month == 3 || month == 5....
すべてを month と比較する必要があります。

また、閏年の2月は29日までありますよ。

naohiro19

Re:年月日をもとに曜日を求めるプログラム

#16

投稿記事 by naohiro19 » 15年前

switch caseを使う方法もありますね

デミチェリス

Re:年月日をもとに曜日を求めるプログラム

#17

投稿記事 by デミチェリス » 15年前

>if(month == 1 || 3 != 0 || 5 != 0..... というコードと等価です。

・なるほど勉強になりました。


> また、閏年の2月は29日までありますよ。

・そうですね。一応、式はできてるんですが、printfに表示がうまくいかなくて・・。
 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))


>switch caseを使う方法もありますね

・習ってないので使い方はわかりませんが、調べてみます。

へろりくしょん

Re:年月日をもとに曜日を求めるプログラム

#18

投稿記事 by へろりくしょん » 15年前

配列を使えばすっきりしますよ。

static const int Days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

e = Days[month - 1];

2月だけは閏年を判定して+1しなければなりませんが。

デミチェリス

Re:年月日をもとに曜日を求めるプログラム

#19

投稿記事 by デミチェリス » 15年前

>配列を使えばすっきりしますよ。

こうですか?
printf(" ** %d年%d月 **\n", year, month);
printf(" 日 月 火 水 木 金 土\n");
printf("---------------------\n");

while( i <= day )
{
printf(" ");

i = i + 1;
}

static const int Days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

e = Days[month - 1];

while( i <= e)
{
printf(" %d", i);

if ( (i + day) % 7 == 0)
printf("\n");

}
while( month == 2 )
{
if ( year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ))

e == 29;
}

return 0;
}

box

Re:年月日をもとに曜日を求めるプログラム

#20

投稿記事 by box » 15年前

閏年の求め方が間違っています。

西暦年が4で割り切れて100で割り切れない
または
西暦年が400で割り切れる
とき、閏年です。

今のif文を見直しましょう。

白い時空

Re:年月日をもとに曜日を求めるプログラム

#21

投稿記事 by 白い時空 » 15年前

閏年の求め方は多分あっていると思います。

while(month==2)の内部の意味がよくわからないです。
閏年かつ2月ならeに1を足せばいいので、

static const int Days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

e = Days[month - 1];
//2月で閏年なら1日増やす
if(month==2 && year % 4 == 0 && ( year % 100 != 0 || year % 400 == 0 ))
e++;

こうですかね。

他には
・while(i<=day)の中ではiを加算していますが初期化していません。
・while(i<=e)の中でiもeも変更しないので無限ループになります。またiを初期化してません。
ここではwhileよりforを使うべきだと思います。

あと、
printf(" %d",i);
の%dを%2dに変更してください。こうしないときれいに並びません。

デミチェリス

Re:年月日をもとに曜日を求めるプログラム

#22

投稿記事 by デミチェリス » 15年前

おかげ様でできました。ありがとうございます。

>ここではwhileよりforを使うべきだと思います。
・while文の限界を感じました。

box

Re:年月日をもとに曜日を求めるプログラム

#23

投稿記事 by box » 15年前

> ・while文の限界を感じました。

なぜ?

A;
while (B) {
/* 何かの処理 */
C;
}

と、

for (A; B; C) {
/* 何かの処理 */
}

とは、一部の例外を除いて等価ですよ。
等価である双方を比べて、
whileを使う「べき」とかforを使う「べき」なんてことは言えません。 画像

box

Re:年月日をもとに曜日を求めるプログラム

#24

投稿記事 by box » 15年前

閏年の求め方が間違っていると書いたのは正確ではありませんでした。
お詫びいたします。
「間違ってはいないが冗長な部分がある」というのが正確です。

if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0 ))

というif文は

if ((y % 4 == 0 && y % 100 != 0) || (y % 4 == 0 && y % 400 == 0))

と等価です。ここで、|| 演算子の後ろの部分は

y % 400 == 0

と等価です。4でも400でも割りきれるということは、要するに400で割りきれるってことですからね。
よって、冗長でないif文は

if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))

である、という結論を得ます。

ドラ

Re:年月日をもとに曜日を求めるプログラム

#25

投稿記事 by ドラ » 15年前

if ( (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 )
これだとyが4の倍数でない場合にも、yが400の倍数かどうかを調べないと
式全体の評価は決まりません。

if ( y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) )
こっちは、yが4の倍数でない場合はそこで評価が終了します。

どちらのケースもyが4の倍数であった場合は100の倍数かどうか調べ、
100の倍数であった場合のみ400の倍数かどうかを調べます。

以上から、下の方法の方が計算効率が良いと言えるのではないでしょうか?
この程度の計算効率の差などあまり気にしなくても良さそうですが。

box

Re:年月日をもとに曜日を求めるプログラム

#26

投稿記事 by box » 15年前

何億回も閏年の判定をするならごくわずかに実行時間の差が出るかもしれませんが、
先に書いた閏年の定義をもっとも端的に表わすif文は
私が示したものでありましょう。
画像

ドラ

Re:年月日をもとに曜日を求めるプログラム

#27

投稿記事 by ドラ » 15年前

確かにboxさんが書いた閏年の定義だと
if ( (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 )
の方が分かりやすいですね。

私も閏年の判定とはこのように書くものだと思っていたので、
デミチェリスさんが書いたコードは間違っているのではないかと思いましたが、
よく見ると正しく判定できていていました・・・。

閉鎖

“C言語何でも質問掲示板” へ戻る