餃子を食べるとき、何をつけますか?

次に示すプログラムは、100までの素数を表示するものです。
見てのとおり、C言語のwhile文を使って書いてあります。

#include <stdio.h>

int main(void)
{
int a, b;
int flag = 0;

a = 2;
b = 2;

while(b <= 100){

*ここ*

while(a < b){

if(b%a == 0){
flag = 0;
break;
}

else{
flag = 1;
}

a++;
}

if(flag == 1){
printf("%dは素数\n", b);
}

b++;
}


getch();
return 0;
}

最初、手本を参考にしながら上記のように書きましたが、うまく機能せず、3から100までの数字すべてが素数であると表示されました。
どこが間違っているのかと、手本と厳密に見比べてみたら、8行目の
a = 2
が*ここ*と書いてある場所に書かれていました。
まさかないだろうと思いつつ、もとあったのを消して*ここ*に書き換えたら、正しく素数が表示されるようになりました。
値を代入する場所が違うだけで、なぜこのような違いが起こるのか全く理解できません。
教えてください。
(一応、書いておきますが使っているコンパイラはBorlandのやつです
コンパイラのせいってことはないですよね)

A 回答 (6件)

>つまり、a = 2 はwhileの{}に入れないといけないということで、あってますか?



はい。

#2は無視か,flag = 1の誤り(変数の初期化時も)。勘違いしていた,すまん。

>下のほうは、なぜ値が増えていかないのですか?
毎回
a=0;
が実行されるから。

#1の「階乗」とは言わないだろうな。なんと言うか思いつかんけど。
    • good
    • 0
この回答へのお礼

> >下のほうは、なぜ値が増えていかないのですか?
> 毎回
> a=0;
> が実行されるから。
この文でかなりすっきりしました。
a = 0 は一度実行されたら、それ以降は関係ないと思い込んでいました。
たしかに、printf("debug:%d",a); で見た時もaの値は毎回2にリセットされてました。

1から10まで全部表示されるのを階乗とは言わないですね…
すみません、訂正します…

flagはどこに入れても問題ありませんが、なんか、こうするといいっていうのがあるみたいですね。(自分には分かりませんが)

ひとまず、解決まで導いていただきありがとうございました。

お礼日時:2009/08/19 03:05

>#5


>flag の初期化」は意味をなしません

うん,自分でも解ってて,

>flag = 1;
>a = 2;
>while (a < b) {
>if (b % a == 0) {
>flag = 0;
>break;
>}
>a++;
>}

自分はこの形を望んでいたからflagを初期化する処理を書いたんだけど,
コードを書いて説明するのが面倒くさかったものだから

>2は無視か,

っていう部分が入っているの(汗。やっぱり無駄に混乱させる分俺の回答自体が害悪になっちゃったかなあ?
    • good
    • 0
この回答へのお礼

結論から言うと、Tacosanさんと同じように flag = 1 にする else はいらない、
だから、flag を 1 で初期化すべしってことですね。

害悪なんてことはないです。
#4は自分が求めていたような回答でした。
何回も質問を見ていただき、ありがとうございました。

お礼日時:2009/08/19 15:05

えぇと, このプログラムにおいて「flag の初期化」は意味をなしません>#4. だからどこにあってもいいしどんな値にしてもいいのですが, 本質をいうとこのプログラムは「動作はあっているけど論理的に間違っている」と思います. 内側の while ループで if の else 部分が無駄ですし, 変数 flag が「b が素数なら 1, そうでなければ 0」という値を取る以上「素数かどうかをチェックする途中で 1 にする」のは誤解を招きかねません.


flag = 1;
a = 2;
while (a < b) {
if (b % a == 0) {
flag = 0;
break;
}
a++;
}
の方が「しなければならないことを過不足なく表している」という点でより正しい. もっとコンパクトにするなら
a = 2;
while (b % a != 0) {
a++;
}
でも (あとの if の条件を a == b に変えれば) 同じような動作になりますが, あんまりお勧めしない.
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
flag = 0 としていた(flag の初期化)のは、もとのプログラムでは何も意味をなしていなかったんですね。
最初に flag = 1 とすることで
else{
flag = 1;
}
の部分が省けて、分かりやすくすることができました。
それ以上コンパクトにすると自分には少し分かりづらそうな気がするのでやめておきます。
論理は分かりますが…

お礼日時:2009/08/19 14:52

プログラムは、書いてある命令を書いてあるとおりに実行していきます。

書いてある内容が変われば実行結果は変わるのが当然です。もちろん、たまたま変わらない場合もありますが、この場合は変わると言うことです。

a=0;
for(i=0;i<10;i++){
a++;
printf("%d\n",a);
}
と、
for(i=0;i<10;i++){
a=0;
a++;
printf("%d\n",a);
}
の違いがわかりますか?

この回答への補足

回答ありがとうございます。

違いはよく分かりません。
でも、やってみたら、上は1の階乗が表示されましたが、
下は1だけが表示されました。
下のほうは、なぜ値が増えていかないのですか?

補足日時:2009/08/19 01:27
    • good
    • 0
この回答へのお礼

himajin100000さんに違いを教えていただいて解決しました。
a++が実行オブジェクトであるのと同じようにa=0も実行オブジェクト
ただ、それだけのことが分からずに悩んでたみたいです。
ありがとうございました。

お礼日時:2009/08/19 03:13

あともうひとつ。

flag = 0もそこにあるべきだと思う。
    • good
    • 0

やっていることがそもそも違うから


その処理だと
2は素数(a == 2,b==2)
3は素数(3 % 2 == 1)
4は素数(4 % 3 == 1) ←ここで 4 % 2 == 0をチェックしない
5は素数(5 % 4 == 1) ←ここで 5 % 3 == 0, 5 %2 == 0はチェックしない
6は素数(6 % 5 == 1) ←ここで 6 % 4 == 0, 6 % 3 == 0, 6 % 2 == 0はチェックしない

となっちゃうよね?

while(a < b){
printf("debug:%d",a); /* ここで値を見張ってみればたぶん一目瞭然 */
/* 略 */
}

この回答への補足

回答ありがとうございます。

やっていることが違うのは分かりました。
つまり、a = 2 はwhileの{}に入れないといけないということで、あってますか?

補足日時:2009/08/19 01:20
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報