dポイントプレゼントキャンペーン実施中!

Javaの学習を始めて数週間の初心者です。
皆さんのお知恵を貸してください。

条件分岐、ループ、配列、メソッドを使用したプログラムを作成する、
という課題です。習っただけでなく自分でちゃんと使えるか、という意図だと思います。

素数を判定するプログラムにしようと考えました(もっと単純なもので構わないのですが、思いつかなかった…)。
ネットを検索して考え方を参考にしながら、書いてみました(コピペではないです)。
不細工で読みにくいかもしれませんがよろしくお願いします。

概要(問題のソースは最下部)
・キーボードで3つの数字を入力し、それらを配列numに代入する(readLine使用)。[メソッド][配列]
・(ここからペーストしたソース)配列をfor文で足し込み合計値をsumに代入。[ループ]
・2以上とそれ以外に分ける(素数は2~)。[条件分岐]
・2以上、sum未満の数で順番に割っていく。
・1回でも割り切れたらboolean型sosuにfalseを代入、処理を終了させる。
(ここには載っていませんが、sosuはtrueで初期化済み)
・sosuがtrueかfalseかで表示を変える。

とりあえずソースを書いてコンパイルも通り、実行した結果も一応私の意図通りに動きます。。
が、これを講師の方に動きを説明しないといけません。一つ一つの動きは理解できるのですが、
ifの入れ子のブロックで処理がどう移っていくのかが不明瞭です。
お訊きしたいのは以下のケースで処理がどう動くのか、です。理由もお願いします。
(1)2つ目のfor文、1回目でfalseの場合(例えばsumが2の時)
…2の場合、「素数です」と表示されますが、改めて読むと「elseに飛んでsosu = falseになるのでは?」
という疑問があります。具体的な内容を伏せて講師の方に訊いてみると「上のif文でtrueになっても
その下のfor文でfalseならばelseに飛ぶはず」と言われました。
(2)2つ目のif文、falseになった場合
…この場合、falseなら素数と判定された、と思っていて実行結果もそのようになるのですが、
「elseに飛ぶ、が正しいならおかしくないかな?」と感じます。
(3)breakの後
…大体上と同じ疑問です。

(4)要は入れ子になっている場合、どこに処理が移るかがちゃんと解っていないのだと思います。
このような場合の読み方のアドバイスをお願いします。

情報に不足があればご指摘ください。

↓ここからソース↓

(略)
System.out.println("※合計値はint型の範囲内になるよう注意してください。");
(略)
int sum = 0;
for (int i = 0; i < num.length; i++) {
sum += num[i];
}
if (sum >= 2) {
for (int i = 2; i < sum; i++) {
if (sum % i == 0) {
sosu = false;
break;
}
}
} else {
sosu = false;
}
if (sosu == true) {
System.out.println("\n合計値" + sum + "は素数です。");
} else {
System.out.println("\n合計値" + sum + "は素数ではありません。");
}
(以下略)

A 回答 (3件)

> 「上のif文でtrueになってもその下のfor文でfalseならば


> elseに飛ぶはず」これは正しいでしょうか?

いいえ,間違っています。

--------
01 if (sum >= 2) {
02 ■ for (int i = 2; i < sum; i++) {
03 ■● if (sum % i == 0) {
04 ■●★ sosu = false;
05 ■●★ break;
06 ■● }
07 ■ }
08 } else {
09 □ sosu = false;
10 }
--------

上記のコードにおいて,

01行目の if (sum >= 2) { が真のときに実行される■のブロックと,
それが偽のときに実行される 08行目 else { 以降の□のブロックは,
二者択一の関係にあります。

02行目,03行目,05行目が実行されたとしても
それらはすべて■ブロック内にある命令ですから,
□ブロックに実行が移ることはありません。

ちなみに,
05行目の break は,もっとも内側にあるループ(今回は,02行~07行のforブロック)に作用する命令であり,このループから脱出するという機能を実現しています。

したがって,
「05行目 break; の実行」→「forループを脱出して 07行目の次に移動」→「08行目の }で ■ブロックの実行もすべて終了」→「(if{} else{}の固まりの外にある)10行目の次の命令に移動」という実行の流れになります。

----------------
> if (sum >= 2) { // sumが2ならここはtrueですよね。
> for (int i = 2; i < sum; i++) {
> // iを2で初期化するので2 < 2となりfalseである
> と理解するのは間違いでしょうか?

そこまでの理解は正しいです。

回答No.1は次のことを指摘しているわけです。
「この場合のループ継続条件 2 < 2 はfalseなので,●で示されたforブロックの内部は一度も実行されない。前述の理由で □ブロックに実行が移ることもない。つまり,sum=2 の場合は 04行目も09行目も実行されないから,質問文に提示されていない「(略)」の箇所のコードで設定されたsosuの値がそのまま適用される」
    • good
    • 0
この回答へのお礼

お礼をしたつもりができていませんでした…大変失礼致しました!

遅くなりましたが、
■●★を使った視覚的な説明は大変解りやすく納得出来ました。
これからも頑張って学習を進めて行きたいと思います。
ありがとうございました。

お礼日時:2013/11/14 16:39

変数の値を追いかけて、このプログラムのルートを全て通るにはどのような変数の値をとれば良いかを考えます。



影響を与えるのはsumだと考えます(readLineによる入力はどうとでもできるので)。

このプログラムでは、
sumが0以下の場合
sumが1の場合
sumが2の場合
sumが3以上の場合
で動作が異なると考えられます。

>iを2で初期化するので2 < 2となりfalseであると理解するのは間違いでしょうか?
falseとなり、forブロックは実行されません。
forブロックは実行されないので、変数sosuがfalseになる機会がなく、変数sosuの初期値がtrueなので、sum==2の場合は「合計値 2 は素数です。」という結果が得られています。

>…2の場合、「素数です」と表示されますが、改めて読むと「elseに飛んでsosu = falseになるのでは?」
飛ぶと思われるelseブロックにSystem.out.printlnを挿入して、実際にsum==2として実行してみると良いと思います。

>その下のfor文でfalseならばelseに飛ぶはず
この文だけを読む限りは飛びません。if~elseとforの判定処理は独立しているからです。
    • good
    • 0

入れ子になってるならどう対応するのかを考えなきゃならない. マーカーなりボールペンなりで対応関係に色を付けてみたら?



あと, (1) で sum が 2 だと「2つ目のfor文、1回目でfalseの場合」には当てはまらないよ.

この回答への補足

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

> (1) で sum が 2 だと「2つ目のfor文、1回目でfalseの場合」には当てはまらないよ.
あれ、そうなのですか…?

if (sum >= 2) {           // sumが2ならここはtrueですよね。
 for (int i = 2; i < sum; i++) {  // iを2で初期化するので2 < 2となりfalseであると理解するのは間違いでしょうか?

もしかして私基本的な勘違いしてたりするのかな。
ソースとテキストfor文の箇所を見返していますがわからない…。
自分のプログラムなのに混乱してきました(笑)。もう少し考えます。
後、「上のif文でtrueになってもその下のfor文でfalseならばelseに飛ぶはず」
これは正しいでしょうか?


※投稿した後でソースのTabインデントが無効になっているのに気付き、
(私が)読みにくいので、スペースで下げます(内容は同一)。

(略)
System.out.println("※合計値はint型の範囲内になるよう注意してください。");
(略)
int sum = 0;
for (int i = 0; i < num.length; i++) {
 sum += num[i];
}
if (sum >= 2) {
 for (int i = 2; i < sum; i++) {
  if (sum % i == 0) {
   sosu = false;
   break;
  }
 }
} else {
 sosu = false;
}
if (sosu == true) {
 System.out.println("\n合計値" + sum + "は素数です。");
} else {
 System.out.println("\n合計値" + sum + "は素数ではありません。");
}
(以下略)

補足日時:2013/09/09 15:28
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。
皆さんのアドバイスを総合するとより理解が深まりました。

これからは対応関係を常に意識するように心がけたいと思います。

お礼日時:2013/09/18 13:30

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