ページ 1 / 1
C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 14:19
by nassangogo
初めて質問するので、テンプレートを使わさせていただきます。
[1] 質問文
[1.1] 2001年から2100年にある13日の金曜日を全て求め、表示したいのです
[1.2] 明日までの宿題なので数日前からじっくり組み立てました。
しかし、どうしてもうまくいかないで行き詰まってます。
先程yahoo知恵袋を使って質問したが、その通りにやっても上手に行かなかたです。
http://detail.chiebukuro.yahoo.co.jp/qa ... 4108524104
さっきからmacのターミナルを使って実行してみても、コンパイルの時点で行き詰まっています。
コード:
#include <stdio.h>
int main()
{
int y,m,d,h,y1,m2;
y=2001;
m=1;
d=13;
y1=2001;
m2=1;
while (y1<2100){
while (m2<12){
if(m < 3){
y=y-1;
m=m+12;
}
h = (y + y/4 - y/100 + y/400 + (13 * m + 8)/5 + d)%7;
if (h=5){
printf ("%d %d %d",y,m,d);
}
m2=m+1;
}
y1=y+1;
}
return 0;
}
[1.3] gcc ちぇーんそーのひ.c
ちぇーんそーのひ.c: In function ‘main’:
ちぇーんそーのひ.c:33: error: stray ‘\343’ in program
ちぇーんそーのひ.c:33: error: stray ‘\200’ in program
ちぇーんそーのひ.c:33: error: stray ‘\200’ in program
ちぇーんそーのひ.c:33: error: stray ‘\343’ in program
ちぇーんそーのひ.c:33: error: stray ‘\200’ in program
ちぇーんそーのひ.c:33: error: stray ‘\200’ in program
nakamotos-MacBook-Air:てすと tomoko$
なお、ソースコードは最初のメモ8行を省略しているので、エラーを起しているのは、元のソースコードで33行目のreturn 0では無いかと睨んでいる。
[1.4] どうしたら自分が動かしたいように動くようになるのか教えてください。
どうソースコードを改変したら動くようになるのかよく分からないのです。
何故エラーになるのかよく分からず困っています。
[2] 環境
[2.1] OS :MACOS
[2.2] コンパイラ名 :macのterminal
[3] その他
・どの程度C言語を理解しているか
授業で今年4月に初めて触れた
今までループや実数の扱い方などを習った
・Xcodeを使って書いた
どうかよろしくお願いします。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 16:06
by かずま
nassangogo さんが書きました:
ちぇーんそーのひ.c:33: error: stray ‘\343’ in program
"error: stray ‘\343’ in program" で検索してみましたか?
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 16:44
by あたっしゅ
こういうのは、全角空白が入っているぽいよな、と思いつつ、
"error: stray ‘\343’ in program" で検索してみたら、
やっぱり、全角空白が入っているせいらしい。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 16:47
by nassangogo
勉強不足ですみませんでした。
今検索した所、変な空白が入り込んでいるようですね。
空白を消した所、やっとコンパイルが通りました。
しかし、実行されても何も表示されません・・・。
何所がおかしいのでしょうかね…。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 17:07
by 初級者
20行目で h に 5 を代入しています。
それは意図どおりでしょうか?
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 17:08
by トントン
nassangogo さんが書きました:勉強不足ですみませんでした。
今検索した所、変な空白が入り込んでいるようですね。
空白を消した所、やっとコンパイルが通りました。
しかし、実行されても何も表示されません・・・。
何所がおかしいのでしょうかね…。
まず、インデントを揃えましょう。
解決方法として、
printf関数に渡すもの間違っていなければ
条件を確認していきます。
printf関数を呼び出す直前のif分の条件は成り立つのか。
1つ目のwhile文にはそもそも入っているのか。
2つ目のwhile文にはそもそも入っているのか。
条件の前後にprintf関数を埋め込むなり、
デバッガを使えるのであればブレークポイント張ってステップ実行すれば確認できると思います。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 18:14
by box
他の回答者さんからもありましたが、せめてこのくらいの字下げはできないものでしょうか。
字下げがきたないと見る気が失せますし、ミスを見つけにくくなると思います。
なお、下記はあくまで私の流儀です。何も押しつけようとしているわけではありません。
コード:
#include <stdio.h>
int main()
{
int y, m, d, h, y1, m2;
y = 2001;
m = 1;
d = 13;
y1 = 2001;
m2 = 1;
while (y1 < 2100) {
while (m2 < 12) {
if (m < 3) {
y = y - 1;
m = m + 12;
}
h = (y + y/4 - y/100 + y/400 + (13 * m + 8)/5 + d) % 7;
if (h = 5) {
printf("%d %d %d", y, m, d);
}
m2 = m + 1;
}
y1 = y + 1;
}
return 0;
}
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 22:27
by nassangogo
すみません。
非常に自分の勉強不足を自覚してます。
字下げすると非常に見易くなりますね。
hに代入しているのは、自分の意思通りです。
hでツエラーの定理を使って曜日が何であるかを求めています。
hはツエラーの定理の答えを入れるために作った代数です。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 22:45
by box
nassangogo さんが書きました:
hに代入しているのは、自分の意思通りです。
問題となっているのは、20行目の
if文の中で
と書いているのが本当に意図どおりですか?ということです。
本当は、hと5とが「等しいかどうか比較したい」のではありませんか?
その場合、等号は1個でいいんでしょうか?
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月09日(日) 23:20
by 超絶右留斗羅天才プログラマー
ツエラーの法則を使わず、全探索のアルゴリズムを用いてプログラムを作成してみました。ツエラーの法則を使うより重いですが、もしよろしければ参考にしてください(^^♪
コード:
#include <stdio.h>
int main()
{
// 12ヶ月分の日数
int m_max[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
int w = 0; // 0なら月曜日
// 100年分
for( int y = 2001; y <= 2100; y++ ){
// 閏年なら2月は29日
if( y % 4 == 0 )
m_max[1] = 29;
// 閏年でないなら2月は28日
else
m_max[1] = 28;
// 12ヶ月分
for( int m = 0; m < 12; m++ ){
// 日数分
for( int d = 0; d < m_max[m]; d++ ){
// 13日の金曜日ならカウント
if( d == 12 && w == 4 ){
printf("%d年%2d月%2d日(金)\n",y,m+1,d+1);
}
// 曜日補正
w++;
if(w==7)w=0;
}
}
}
// 入力待ち
rewind(stdin);
getchar();
return 0;
}
課題が「ツエラーの法則を必ず使うことでしたらすみません(ノ_・;)
(2013/6/9/23:43 文章を一部訂正しました)
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 01:24
by トントン
nassangogo さんが書きました:勉強不足ですみませんでした。
今検索した所、変な空白が入り込んでいるようですね。
空白を消した所、やっとコンパイルが通りました。
しかし、実行されても何も表示されません・・・。
何所がおかしいのでしょうかね…。
とりあえず、最新のコードと現在の状況が知りたいですね。
初級者さん、boxさんが指摘されてる「if (h=5)」が解決できたとしても
そもそも、「実行されても何も表示されません」というのは
確認したソースの条件からはありえないわけで。。。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 02:04
by かずま
トントン さんが書きました:
初級者さん、boxさんが指摘されてる「if (h=5)」が解決できたとしても
そもそも、「実行されても何も表示されません」というのは
確認したソースの条件からはありえないわけで。。。
本当ですか?
元のソースから、全角スペースを除去すると、コンパイルできるように
なります。if (h=5){ のままのものを、
VC++ でコンパイルして実行した場合は 2000 13 13 と表示されますが、
gcc でコンパイルした場合は、出力が行バッファリングされるので
改行のない 2000 13 13 は表示されません。
if (h==5){ に修正さればものは、VC++ であろうと、gcc であろうと、
y = 2000, m = 13 のまま無限ループになるので、何も表示されません。
「実行されても何も表示されません」というのは
確認したソースの条件からはありえるわけです。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 02:20
by トントン
かずま さんが書きました:トントン さんが書きました:
初級者さん、boxさんが指摘されてる「if (h=5)」が解決できたとしても
そもそも、「実行されても何も表示されません」というのは
確認したソースの条件からはありえないわけで。。。
本当ですか?
元のソースから、全角スペースを除去すると、コンパイルできるように
なります。if (h=5){ のままのものを、
VC++ でコンパイルして実行した場合は 2000 13 13 と表示されますが、
gcc でコンパイルした場合は、出力が行バッファリングされるので
改行のない 2000 13 13 は表示されません。
if (h==5){ に修正さればものは、VC++ であろうと、gcc であろうと、
y = 2000, m = 13 のまま無限ループになるので、何も表示されません。
「実行されても何も表示されません」というのは
確認したソースの条件からはありえるわけです。
1.ありえないわけで
→調べました。なるほどです。
訂正、ありえます。
2.if (h==5){ に修正
→ごめんなさい。こちらはミスですね。
仰るとおりの状態になりますね。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 07:35
by nassangogo
宿題はヘロンの定理のプログラムを作った上で、
そのプログラムを少し改変してプログラムを組もうという宿題です。
それに私も何故動かないのか疑問なので、提出期限の夕方まで少し頑張ってみようと思います。
コード:
#include <stdio.h>
int main()
{
int y, m, d, h, y1, m2;
y = 2001;
m = 1;
d = 13;
y1 = 2001;
m2 = 1;
while (y1 < 2100) {
while (m2 < 12) {
y=y+1;
m=m+1;
if (m < 3) {
y=y-1;
m=m+12;
}
h=(y+y/4-y/100+y/400+(13*m+8)/5+d)%7;
if (h==5) {
printf("%d%d%d",y,m,d);
}
m2=m+1;
}
y1=y+1;
}
return 0;
}
にしてみましたが、何も表示されません・・・。
どうしてなのでしょうか?
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 09:00
by non
yとy1、mとm1の使い方が明確でないようです。もう一度整理してみてはどうでしょうか。
また、内側のwhile(m2<12)を抜けたら、m2はまた1月から始めなくては。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 09:39
by novelmaniagogo
本当ですね・・・。
これじゃあ、明らかにおかしいですね・・・。
コード:
#include <stdio.h>
int main()
{
int y, m, d, h, y1, m2;
y = 2001;
m = 1;
d = 13;
y1 = 2001;
m2 = 1;
while (y1 < 2100) {
while (m2 < 12) {
y=y+1;
m=m+1;
if (m < 3) {
y=y-1;
m=m+12;
}
h=(y+y/4-y/100+y/400+(13*m+8)/5+d)%7;
if (h==5) {
printf("%d%d%d",y1,m2,d);
}
m2=m+1;
}
y1=y+1;
}
return 0;
}
にしてみました。
今一生懸命文字が何も出力されない理由を探してます。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 09:56
by YuO
xcodeとかのデバッガ使って追った方が楽なのですが……。
terminalとのことなので,とりあえずprintfデバッグを。
whileの開始直後や終了直前,ifの前や後などに,printfで変数の内容を出力してみて下さい。
例えば,14行目の直後には
コード:
printf("while(1).begin : y=%d, m=%d, d=%d, y1=%d, m2=%d", y, m, d, y1, m2);
23行目の直後には
コード:
printf("if(2).before : y=%d, m=%d, d=%d, h=%d, y1=%d, m2=%d", y, m, d, h, y1, m2);
のように,どこで出力したかもわかるように書いておきます。
最初は100年分ではなく,5年分とかでやってみるとよいでしょう。
あとは,結果を見て,想定した値になっているかを検証します。
恐らく,想定した値にはなっていないはずなので,その理由を考えてバグを潰していくのがよいでしょう。
# 一番の元凶は,forでなくwhileを使ったことだと思いますが……。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 10:33
by novelmaniagogo
コード:
#include <stdio.h>
int main()
{
int y, m, d, h, y1, m2;
d = 13;
for (y=2001; y<2002;y++){
y1=y;
for(m=1;m<13;m++){
m2=m;
if (m<3){
y=y-1;
m=m+12;
}
h=(y+y/4-y/100+y/400+(13*m+8)/5+d)%7;
if (h==5){
printf(y,y1,m2);
}
}
}
return 0;
}
先程のアドバイスを踏まえて変更してみました。
そして上でおっしゃられた確認用の文を入れた所、確認用の数字が沢山出力されました。
恐らく条件文の所がおかしいのだと思います。
if (h==5){
printf(y,y1,m2);
のところが。
少し頑張ってみようと思います
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 10:50
by non
non さんが書きました:yとy1、mとm1の使い方が明確でないようです。もう一度整理してみてはどうでしょうか。
まだ、明確でないことが原因です。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 12:45
by YuO
ループ変数の値をループ中で変更してはいけません。
これは絶対ではないですが,理由なくやることは今回のようにバグの元になります。
出力された値をよく見れば,yに関するループの先頭でyの値が2001から変化していないことがわかるはずです。
また,mに関するループの末端でmの値が常に13であることもわかるはずです。
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 15:30
by novelmaniagogo
コード:
#include <stdio.h>
int main()
{
int y, m, d, h, o, p;
d = 13;
for (y=2001; y<2100;y++){
o=y;
for(m=1;m<13;m++){
p=m;
if (m<3){
o=y-1;
p=m+12;
}
h=(o+o/4-o/100+o/400+((13*p+8)/5)+d)%7;
if (h==5){
printf("%d/%d/%d/",y,m,d);
}
}
}
}
にしたらちゃんと表示されるようになりました。
ありがとう御座いました
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 15:38
by non
あってる気がしないなぁ。カレンダで確認してみた?
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月10日(月) 21:52
by みけCAT
Re: C言語で13日の金曜日を求めたい
Posted: 2013年6月11日(火) 00:53
by かずま
o=y; を p=m; の直前に持ってくるといいですね。
おまけ
コード:
#include <stdio.h>
int dow(int y, int m, int d) // day of week
{
return y -= m<3, (y + y/4 - y/100 + y/400 + "([^]=*-/+_)%."[m] + d) % 7;
}
int main(void)
{
int y, m;
for (y = 2001; y <= 2100; y++)
for (m = 1; m <= 12; m++)
if (dow(y, m, 13) == 5)
printf("%d/%2d/13\n", y, m);
return 0;
}
文字コードに依存するようなこんなコードを書いてはいけません。