• ベストアンサー

C言語のwhile文を使った素数判定プログラムで…

次に示すプログラムは、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のやつです コンパイラのせいってことはないですよね)

noname#183708
noname#183708

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

>つまり、a = 2 はwhileの{}に入れないといけないということで、あってますか? はい。 #2は無視か,flag = 1の誤り(変数の初期化時も)。勘違いしていた,すまん。 >下のほうは、なぜ値が増えていかないのですか? 毎回 a=0; が実行されるから。 #1の「階乗」とは言わないだろうな。なんと言うか思いつかんけど。

noname#183708
質問者

お礼

> >下のほうは、なぜ値が増えていかないのですか? > 毎回 > a=0; > が実行されるから。 この文でかなりすっきりしました。 a = 0 は一度実行されたら、それ以降は関係ないと思い込んでいました。 たしかに、printf("debug:%d",a); で見た時もaの値は毎回2にリセットされてました。 1から10まで全部表示されるのを階乗とは言わないですね… すみません、訂正します… flagはどこに入れても問題ありませんが、なんか、こうするといいっていうのがあるみたいですね。(自分には分かりませんが) ひとまず、解決まで導いていただきありがとうございました。

その他の回答 (5)

回答No.6

>#5 >flag の初期化」は意味をなしません うん,自分でも解ってて, >flag = 1; >a = 2; >while (a < b) { >if (b % a == 0) { >flag = 0; >break; >} >a++; >} 自分はこの形を望んでいたからflagを初期化する処理を書いたんだけど, コードを書いて説明するのが面倒くさかったものだから >2は無視か, っていう部分が入っているの(汗。やっぱり無駄に混乱させる分俺の回答自体が害悪になっちゃったかなあ?

noname#183708
質問者

お礼

結論から言うと、Tacosanさんと同じように flag = 1 にする else はいらない、 だから、flag を 1 で初期化すべしってことですね。 害悪なんてことはないです。 #4は自分が求めていたような回答でした。 何回も質問を見ていただき、ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

えぇと, このプログラムにおいて「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 に変えれば) 同じような動作になりますが, あんまりお勧めしない.

noname#183708
質問者

お礼

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

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.3

プログラムは、書いてある命令を書いてあるとおりに実行していきます。書いてある内容が変われば実行結果は変わるのが当然です。もちろん、たまたま変わらない場合もありますが、この場合は変わると言うことです。 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); } の違いがわかりますか?

noname#183708
質問者

お礼

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

noname#183708
質問者

補足

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

回答No.2

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

回答No.1

やっていることがそもそも違うから その処理だと 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); /* ここで値を見張ってみればたぶん一目瞭然 */ /* 略 */ }

noname#183708
質問者

補足

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

関連するQ&A

  • while文の判定について(C言語)

    while文の判定についてです たぶんすごいつまらないミスなので時間の余っている方 ご指導ください<_ _> (自分ではいろいろ調べましたが原因がわかりません><、) returnやbreakを使わないで二分探索を終了させよとの問題で low-highで2ならばデータが見つかったとき 1ならば見つからなかったときという判定で whileで抜けさせたいのですがどうしても抜けません><、 論理演算子の使い方が間違っているのでしょうか? #include<stdio.h> #define N 10 int main(void) { static int a[]={2,3,4,11,31,50,55,70,77,80}; int key,low,high,mid; high=N-1; low=0; int i=0; printf("検索するdata ? :");scanf("%d",&key); ここです while((2!=(low-high)) || (1!=(low-high))){ mid=(low+high)/2; if(a[mid]==key){ low=mid+1; high=mid-1; } else if(a[mid]<key){ low=mid+1; } else{ high=mid-1; } } if(2==(low-high)){ printf("%2dは%2d番目にありました",key,mid); } else{ printf( "見つかりませんでした" ); } return 0; } while内でlow-highをprintfで出力しましたが2と1が出力されました

  • このプログラムを見てください(C言語) m( _ _ )m

    現在乱数を使ったプログラムを作っています。 下のプログラムでコンパイルではエラーがでませんが、実行するとデバッグエラーが出てきます。コンパイラにはbccを使っています。恐らく原因は別の関数でbに値を代入してそれをaに代入しているからだろうと思いますが、なぜこれがいけないのかが分かりません。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> int ran, a=1, b, c; void test(void){ b=8; } void main(){ srand(time(NULL)); a=b;//ここを無くすとなぜかエラーが出ない。 while(1){ ran=rand()%(a*2)+1; switch(ran){ case 1: c=1; break; case 2: c=1; break; case 3: c=1; break; case 4: c=2; break; case 5: c=2; break; case 6: c=3; break; case 7: c=3; break; case 8: c=4; break; } printf("%d",c);printf("何か押してください\n");getch(); } }

  • while文でつまづいています

    C言語はじめたばかりのものです。 単細胞生物が翌日(2日目)には分裂して2細胞になるとする。1匹もしなないとすると 1万匹を超えるのは何日目になるかを算出するプログラムを作成しています。 「15日目に16384個の細胞数になります。」という結果を出したいのですが、 「1日目に1個の細胞数になります。」と表示され、1日目までしか計算されません。 まだscanfやiprintf、ifやwhileぐらいしか習っていません。 どう直したらよいでしょうか? #include<stdio.h> #include<math.h> main() { int n; /*細胞数*/ int d = 1; /*日数*/ while(n > 10000) { n = pow(2,d-1); d = d + 1; if(n > 10000) break; } printf("%d日目に%d個の細胞数になります。",d,n); }  

  • C言語 偶数判定

    下記は、「1から5までの整数で偶数の和を表示する」というプログラムなのですが、 偶数判定に用いている if ( ! ( i % 2 ) ) の意味が分からないので、どなたか教えていただけないでしょうか? ( i % 2 = = 0 で条件判定をするのなら理解できるのですが…) #include <stdio.h> int main(){ int i=1,total=0; while (1){ if(i>5)break; if ( ! ( i % 2 ) ) total+=i; i++; } printf("%d",total); return 0; }

  • c言語のプログラムで

    c言語で 2つの整数を読み込んで小さいほうの数以上で大きいほうの数以下の整数をすべて加えた値を表示するプログラム で最後の表示の仕方がわかりません。 実行結果は 整数1:37 整数2:28 28以上37以下の全整数は325です。と表示されるはずです。 この表示の3行目の28と37の表示がどうやればよいのかわかりません。 #include <stdio.h> int main(void) { int a, b; int sum=0; printf("整数1:"); scanf("%d",&a); printf("整数2:"); scanf("%d",&b); if(a>b) do{ sum=sum+b; b=b+1; }while(b<=a); else do{ sum=sum+a; a=a+1; }while(a<=b); printf("%d以上%d以下の全整数の和は%dです。",a,b,sum); return(0); } 全整数の表示はできます。 do文の中でa=cとかにしてやってみましたが、うまくいきませんでした。 お願いします。

  • C言語プログラム

    したのプログラムでgetch()の代わりにscanf()を使って、入力した数が負なら終了、正なら"次の数を入力してください"と表示してループを続けるプログラムを作りたいのですが、どこを変えればよいのですか? #include<stdio.h> #include<conio.h> void main() { int i=1,sum=0; char c='m'; while(c!='e')//eでない限りwhileループを実行する { sum=sum+i; printf("\n1 kara %d madewo tasuto %d desu.\n",i,sum); i++; printf("nanikakeywo oshitekudasai.owaru tokiha 'e'\n"); c=getch(); } printf("loopwo nukemashita\n"); getch(); }

  • C言語での方向キー入力判定

    C言語でキーの入力判定をするプログラムを作ってい ます。下の例だとeやエンターを押したときは認識できる のに、方向キー↑を押したときはなぜか無反応です。 コンパイラはボーランドでOSはXPでコンパイルした のですが、何がいけなかったのでしょうか? #include <stdio.h> #include <conio.h> #include <windows.h> void check(void){ int key; key = getch(); switch (key){ case 'e': puts("e"); break; case VK_RETURN: puts("ENTER"); break; case VK_UP: puts("UP"); break; } } int main(void) { while(1){ check(); } return 0; }

  • 2進数の足し算(C言語)

    C言語初学者です。 タイトル通り、2進数の足し算をするプログラムを作っていますが、行き詰ってしまいました。 特に、桁上げをどうするか悩んでいます。 今の自分の考えでは、入力された数値を10で割り、その余りを足していけばできると思っていたのですが、やはり桁上げや繰り上がりに悩んでいます。 全然できてませんが以下ソースです。 #include <stdio.h> int main(void) { int a, b, i; do { printf("8桁以下の非負の2進数を入力してください(1つ目): "); scanf("%d" ,&a); if (a < 0) puts("負の数を入力しないでください。"); } while (a < 0); do { printf("8桁以下の非負の2進数を入力してください(2つ目): "); scanf("%d" ,&b); if (b < 0) puts("負の数を入力しないでください。"); } while (b < 0); a = a % 10; b = b % 10; よろしくお願いします。

  • C言語のプログラムです。

    次のようなプログラムを作成しようと考えています。 1.文字列を入力し、入力した文字列にアルファベット以外の文字が含まれていたら再入力。 2."end"もしくは"END"が入力されたらプログラム終了。 3.main関数とは別の関数で入力した文字列に現れる文字を全て入力順に大文字で表示する。(小文字と大文字は同じ文字として扱い、出現個数も合わせて表示する) ※2.では文字列を比較するstrcmpを使用。 表示結果例)  入力:DxbhzAeFSXY  出力:D=1,X=2,B=1,H=1,Z=1,A=1,E=1,F=1,S=1,Y=1 (応用)3.では入力順に表示させていたが、アルファベット順に結果を表示する。 上記の2.までのプログラムは作成できたのですが、3.及び応用が分からず大変困っています。 どなたかご教授ください。 #include <stdio.h> #include <string.h> int sub(int ss[i],int n){ int x; for(x=1; x<=n; x++){ //小文字を大文字に変換 if(ss[i]>=97){ ss[i]=ss[i]-32; } } } int main(void){ char ss[80]; char sa[2][4]={{\"end\"},{\"END\"}}; int a, i, n; int flag= 0; //アルファベット以外の入力があった際の判別 do{ printf(\"文字列を入力してください\\n\"); gets(ss); n= strlen(ss); //文字列ssの長さを求める if(n=3 && ((strncmp(ss,sa[0],3)==0)) || ((strncmp(ss,sa[1],3)==0))){ //endまたはENDの判定 return 0; } for(i=0; i<n; i++){ if((ss[i]>=65 && ss[i]<=90) || (ss[i]>=97 && ss[i]<=122)){ } else{ flag=1; break; } } }while(flag=1); }

  • C言語(while構文)

    #include<stdio.h> #include<conio.h> void main() { int i=1,sum=0; char c='m'; while(c!='e')//eでない限りwhileループを実行する { sum=sum+i; printf("\n1 kara %d madewo tasuto %d desu.\n",i,sum); i++; printf("nanikakeywo oshitekudasai.owaru tokiha 'e'\n"); c=getch(); } printf("loopwo nukemashita\n"); getch(); } getch()の代わりに、scanf()を使って整数値を入力させ、負の数が入力されたら終了するプログラム(正を入力したら「次の数値を入力せよ」とだして、繰り返す。)を造りたいのですが、どこを変えればよいか教えてください。