
/*
プログラム作成に当たっては以下の注意を守ること。
•入力は整数変数に格納し、有効な日付かどうかチェックせよ。
•日付チェックでは、月の最終日が月によって違うことも考慮にいれること。
•日付チェックにおけるif文を減らすため、daynum[]を必ず使うこと。
•日付チェック以外でも、if文やswitch-case文の数はなるべく少なくするよう工夫せよ。今回は、if文の7行並列も、12行並列も禁止。
•日付の範囲チェックと計算とを同時に実行してもよい。
2個の整数を入力し、それぞれを2011年度の月、日とみなして、
その日付からおよその月齢と月相を計算して表示するプログラムを作成せよ。
月齢と月相の対応は簡便的に3.75齢毎に相が進むとしてよい。
suuumは月齢であるが、計算は以下のもので間違いない。
また、以下の配列を定義して使うこと。
char moonphasename[][15]= {"new moon", "new crescent", "first quarter", "waxing gibbous",
"full moon", "waning gibbous", "last quarter", "old crescent"};
*/
#include <stdio.h>
int main(void)
{
int daynum[]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int i=0,j=0;
/*15はもじすう+1*/
char moonphasename[][15]= {"new moon", "new crescent", "first quarter","waxing gibbous", "full moon", "waning gibbous", "last quarter", "old crescent"};
int month,day,sum,suum,suuum;
printf("月と日付を入力してね:");
scanf("%d%d", &month, &day);
if(day>daynum[month]){
printf("2011年にそんな日はありません");
return(-1);
}
sum=(2011-1740)*210;
suum=((sum/19)-2)+month+day;
if(month==1)
suuum=suum+1;
else if(month==2)
suuum=suum+2;
else if(month==3 ||month==5)
suuum=suum-1;
else suuum=suum;
printf("月齢は%d",suuum%30);
for(i=0; i<=suuum &&suuum<i+3.75 ; i=i+3.75){
printf("月相は",moonphasename[j][15]);
j++ ;
}
return (0);
}
と書いてリナックスのeclipsで実行させました。月齢はでるのですが、月相が表示されません(月相は という文字も非表示)。
どうしたらいいでしょうか?
また、最後のfor文ではsuuumが0から3.75のときしか反応しません(見ての通り)。どう書き直せばいいでしょうか?
詳しいかたおねがいします。

No.4ベストアンサー
- 回答日時:
とりあえず、
i<=suuum &&suuum<i+3.75
と
(i<=suuum) &&(suuum<i+3.75)
はちゃんと同じ意味になります。
Cのトークン解析は、意味が通じる「最も長い」文字を切り取りますから、スペースがないからと言って、
i<=suuum &&suuum<i+3.75 を i<=suuum & &suuum<i+3.75 と解釈したりはしません。
と、それだけでは何なので、問題についても含めて、周辺を少々。
> •日付チェック以外でも、if文やswitch-case文の数はなるべく少なくするよう工夫せよ。今回は、if文の7行並列も、12行並列も禁止。
とわざわざ指定するなら、月齢の計算も、
int offset[] = {1, 2, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0};
sum = (2011-1740)*210;
suuum = sum/19 + month + day + offset[month - 1] - 2;
か、最後の -2 も offset に取り込むなら、
int offset[] = {-1, 0, -3, -2, -3, -2, -2, -2, -2, -2, -2, -2};
sum = (2011-1740)*210;
suuum = sum/19 + month + day + offset[month - 1];
あと、ひとつ計算をするたびに、sum suum suuum なんていう変数を使うのも、間違いの元なので、お断りしたいところ。
こんな変数を使わなくても、
int offset[] = {-1, 0, -3, -2, -3, -2, -2, -2, -2, -2, -2, -2};
getsurei = (2011-1740)*210;
getsurei = getsurei/19 + month + day + offset[month - 1];
で十分だし、
offset[month - 1] がいやなら、(daynum とおなじようにして)
int offset[] = {0, -1, 0, -3, -2, -3, -2, -2, -2, -2, -2, -2, -2};
getsurei = (2011-1740)*210;
getsurei = getsurei/19 + month + day + offset[month];
でも。
あと、もうひとつ大きな間違いは、この時点で、30に正規化していない点。
それを含めれば、最後に、
getsurei %= 30;
が必要です。
質問のソースの中で、これも引っかかってますね。
月齢の表示は、suuum % 30 を表示しているので、それらしい数字が表示できてきますが、月相の判定は、suuum をそのまま使ってしまっているから、ここでも、正解から遠ざかっています。
あと、入力された日付の判定で、「有効な月か」の判定がないですし(問題の指定にもないけど)
マイナスの日付に対するチェックもないですね。
複数のチェックをする場合には、関数を使って
int dayIsOK(int month, int day)
{
if (month <= 0) return 0;
if (month > 12) return 0;
if (day <= 0) return 0;
if (day > daynum[month]) return 0;
return 1;
}
として、main() で、
if (! dayIsOK(month, day)
{
printf("2011年にそんな日はありません");
return(-1);
}
などとすれば、チェックの条件が複雑になっても見かけを単純にすることができます。
No.3
- 回答日時:
for文の 「 i<=suuum &&suuum<i+3.75 ; 」 ですが、実際のソースもこのままの状態ですか?
きちんと空白を挟むか、試しに「 (i<=suuum) &&(suuum<i+3.75) ; 」 としてみてはどうでしょうか?
(&& と & の優先順のような気がします...)
あと、「 printf("月相は",moonphasename[j][15]); 」 ですが、
「 printf("月相は",moonphasename[j]); 」 なのでは?
参考URL:http://www.bohyoh.com/CandCPP/C/operator.html

No.2
- 回答日時:
> 月相が表示されません(月相は という文字も非表示)
と
> 最後のfor文ではsuuumが0から3.75のときしか反応しません
というのは、矛盾するような気がしますがどうなのでしょう?
「最後の for で、suuum が、0 から 3.75のときには『反応する』」
というのは、どういう状況なのかなと。
ソースを見ると、suuum が、0以上 3.75未満の時には、「月相は」だけ表示。
それ以外の時には、何も表示されないというのだとは思いますが。
まず、月齢計算は、int で良いのじゃないかなと思います。
簡易的な月齢の計算式で、あえて、切り捨てをしている気がしますが。
それ以前に、いろいろな問題があります。
printf("月相は",moonphasename[j][15]);
これでは、(表示されたとしても)「月相は」しか表示されません。
文字(列)の表示方法を復習しましょう。
(少なくとも、2つ間違いがあります)
あと、たとえば、suuum が、20 の時に、
for(i=0; i<=suuum &&suuum<i+3.75 ; i=i+3.75)
{
printf("月相は",moonphasename[j][15]);
j++ ;
}
が、どういう風に実行されるのか、ひとつずつ確かめましょう。
(i が int なのは問題ですが、それ以外にも大きな間違いをしています)
前にやった似たような(と思う)課題から、ひっぱってくるのではなく、
どう動くはずなのか、suuum が、0のとき、10のとき、20のとき、くらいは
手作業で確認しましょう。
No.1
- 回答日時:
アルゴリズムが合っているのならsuum変数の宣言の問題かと思います。
suumは整数でないからfloat宣言して
float suum;
float f;
suum=((sum/19.)-2.)+(float)month+(float)day;
:
if(month==1)
suuum=suum+1.;
:
for(f=0; f<=suuum && suuum<f+3.75 ; f=f+3.75){
のようにキャストした変数を代入して、整数値の後ろは念のためドットをつけたらどうでしょう?
もしくはsuumが小数点2桁まで有効にしたいのであれば1000倍して整数のまま計算するとか
suum=((sum*1000/19)-2*1000)+(month+day)*1000;
:
if(month==1)
suuum=suum+1000;
:
for(i=0; i<=suuum &&suuum<i+3750 ; i=i+3750){
この場合は問題無いと思いますが、suumがオーバーフローしないように注意して下さい。
------------
ともかく小数を扱うならfloatかdouble変数を利用して
しないのなら整数の範囲で扱えるように値を常数倍しましょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
構文エラー";"が型の前にあり...
-
教えてください
-
for文について
-
raspberrypiでロータリエンコーダ
-
#if 1 #elseの意味について
-
プログラミングで二番目に大き...
-
getcの改行判定
-
1年単利金利 0.2% の A銀行と...
-
素因数分解のプログラムを作成...
-
for文の中にswitch文はいれられ...
-
配列を関数に渡す方法
-
for文
-
計算結果がlong型以上になる場...
-
信頼区間の1.96や1.65ってどこ...
-
「Aに対するBの割合」と「Aに対...
-
2÷3などの余りについて
-
プログラミング初心者です。 Py...
-
「指定されたキャストは有効で...
-
Aの値からBの値を除するとは??
-
20'(角度)の計算がわかりま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
#if 1 #elseの意味について
-
構文エラー";"が型の前にあり...
-
for文の中にswitch文はいれられ...
-
配列を関数に渡す方法
-
配列を使って魔方陣
-
プログラミングで二番目に大き...
-
getcの改行判定
-
C言語の二分法のプログラムにつ...
-
C言語階乗の総和を求める
-
C言語 プログラム
-
c言語のプログラミングでこま...
-
1からnまでの和を求めるプログ...
-
初心者です。for文、if文を使っ...
-
計算結果がlong型以上になる場...
-
while文について、c言語...
-
最大値と最小値を表示したいの...
-
scanf関数を用いての加減乗除%...
-
プログラムの内容
-
10進数からN進数に変換するプロ...
-
scanfが実行されません
おすすめ情報