質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.79%

ネストの動きを教えてください。

解決済

回答 5

投稿

  • 評価
  • クリップ 0
  • VIEW 671

r--

score 18

for文の中のfor文で回した値をif文で判定してtrueならその処理が実行され、
falseならelseが実行される。実行されたらブロックを抜けてまたfor文に戻って回された値が
trueならその処理falseならelseの処理をする。for文が5以下なら5の値が入ったらブロックを抜ける。

と説明を受けましたが、紙に自分で流れを書けません。
皆さんどう流れを理解されましたか。

package lesson06;

public class Sample8
{
    public static void main(String[] args)
    {
        boolean b1 = false;
        for(int i=0; i<5; i++) {
            for(int j=0; j<5; j++) {
                if(b1 == false) {
                    System.out.print("*");
                    b1 = true;
                }else {
                    System.out.print("-");
                    b1 = false;
                }
            }
        }System.out.print("\n");
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

+13

この例はまだまだ分かり易い方だと思いますが、複雑になればなるほど「コード全体を漠然ととらえようとしてもどんどん認識できなくなる」と思います。人間の頭ってのはそうそうややこしいことをすぐに把握できるようにはできてない気がするのです。単に私の頭がよくないからかも知れませんが・・・

自分の場合、小さな部分から機能を把握しそれを自分なりに捉えやすい概念に置き換えるようなことをしている気がします。

boolean b1 = false;
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        if (b1 == false) {
            System.out.print("*");
            b1 = true;
        } else {
            System.out.print("-");
            b1 = false;
        }
    }
}
System.out.print("\n")


==>

boolean b1 = false;
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        b1に従い'*''-'を印字
        そしてb1を反転
    }
}
System.out.print("\n")

==>

b1を偽に初期化
以下を5回繰り返す
    以下を5回繰り返す
        b1に従い'*'か'-'を印字
        そしてb1を反転
改行


一番内側は実行するたびに'*'と'-'を交互に印字する機能と捉える
一つ外側のループは「5回繰り返す」わけだが、
b1が偽から始まれば
*-*-*
b1が真から始まれば
-*-*-
となるってことだろう

==>

b1を偽に初期化
以下を5回繰り返す
    b1に従い'*-*-*'か'-*-*-'を印字
    そしてb1を反転
改行


こんな具合に「自分自身の言葉で」「捉えやすい単位で」「機能」をイメージするようにします。

この例のように機能をまとめやすいものもありますが論理が素直でないものの場合うまくまとまらないこともあります。そういう場合は「ループの初回は状態がこうのときどうなるか」「次のループではどうなるか」というのを自分自身の頭の中で「実行」しコードの動きをとらえようとすることもあります。

for (int j = 0; j < 5; j++) {
   if (b1 == false) {
       System.out.print("*");
       b1 = true;
   } else {
       System.out.print("*");
       b1 = true;
   }
}


==>
1回目実行前: jは0, b1がfalse, 印字結果は何もなし
1回目実行後: jは1, b1がtrue,  印字結果は*
2回目実行前: jは1, b1がtrue,  印字結果は*
2回目実行後: jは2, b1がfalse, 印字結果は*-
...
5回目実行前: jは4, b1がfalse, 印字結果は*-*-
5回目実行後: jは5, b1がtrue,  印字結果は*-*-*


またこうした「機能の把握」の過程で「冗長と思える論理」「不明瞭な論理」は自分自身が理解しやすいように置き換えを行うこともあります。

if (b1 == false)これは「b1がfalseなら」と読めるがb1はboolean、すなわち真偽値なのだから「b1だ」「b1でない」と捉える方がより簡単に頭の中に入ってくるので

if (!b1)「b1でなければ」と捉える

if (b1 == false) {
   ...
   b1 = true;
} else {
   ...
   b1 = false;
}


このパターンは「もし条件が成立すれば・・・、そうでなければ・・・」と捉えるより
単に「要するにb1の真偽を反転」と捉えます。


追記:最初に書こうと思っていたことを回答しているうちに書き忘れてました・・・
プログラミング言語の仕様(書き方、意味、人が書いたコードの把握)や様々なアルゴリズム(計算手順)の把握は自分自身の頭に焼き付くぐらい定着していないとパっ見てすぐにわかるようにはなりません。そうなるためにはひたすら反復訓練が必要(体育会系のノリが必要)と自分は思います。

自動車の運転に慣れてないとき「えーとまずブレーキとクラッチを踏んでギアを入れて・・・」なんて手順を頭の中で一生懸命考えます。しかしそんなことを一々考えなければならない段階ではスムーズな運転は困難です。なんども繰り返すうちに意識的に考えなくても自然に体が動くようになってきます。プログラミングも同じで「一つ一つの知識がしっかり頭に定着してあまり意識的に考えなくても自然に意味が連想できるぐらいまで練習すれば」自ずと「見てすぐに理解できるようになる」はずです。

反復訓練しましょう。ひたすらコードを書いて、ひたすらコードを読んで、ひたすら様々な論理を頭に焼き付けていくのです。そうすれば苦もなくプログラミングできるようになります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/14 10:59

    > このパターンは「もし条件が成立すれば・・・、そうでなければ・・・」と捉えるより
    > 単に「要するにb1の真偽を反転」と捉えます。

    これって、初学者向けの参考書のなかの悪しき慣習だと思うのですよね。
    慣れた人はみんな、頭の中で以下のようになるので
    > b1に従い'*'か'-'を印字
    > そしてb1を反転

    最初から、if使わずに、
    System.out.print(b1 ? "-" : "*");
    b1=!b1;
    って、教えたほうが理解が速い人もいっぱいいそう。

    キャンセル

  • 2019/05/14 15:06 編集

    > 理解が速い人もいっぱいいそう。

    そこに書かれているコードというか論理の意味を認識できるようになる過程がプログラミングを学ぶことだと思うので、分岐による実装例を見て
    print(b1 ? "-" : "*");
    b1 = !b1;
    というイメージを浮かべられるようになるのも通過すべき過程ではあると思います。

    momon-gaさんがおっしゃるように「なるべくわかりやすく把握するコツ」を随所にちりばめた教科書があると面白いと思います。ただ振り返ると自分が初学者のころはおよそプログラミングについて書かれた本ならなんでも面白く感じはしたものの、本当に面白い本は「厚ぼったい本」だった気がします。
    初学者向けの本はどうしても特定言語の知識を優先でたたきこむことに終始し「論理そのもの」を説くのに許されるスペースが限られてしまうのかも知れませんね。

    キャンセル

  • 2019/05/14 20:13

    KSwordOfHasteさん
    どうでもいいコメントにわざわざリアクションありがとうございます。
    おっしゃる通りたしかに、まずは意味を認識できることというのはありますね。

    > 本当に面白い本は「厚ぼったい本」だった気がします
    ですよねー。

    キャンセル

+6

デバッグ実行

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/15 00:03

    自動で直されるものを使うのは、自分が動きを理解するまで頼りません。

    キャンセル

  • 2019/05/15 05:33

    デバッグの意味と有用性を調べてからコメントしてください。
    自動で直されるって何の話ですか?
    プログラミングやっていく上でデバッグを知らないって本当に致命的です。基礎です。

    キャンセル

  • 2019/05/15 06:18 編集

    「自動で直される」を「デバッガーで動きを観察すること」や「デバッグすること」だと読み替えると・・・

    > 自分が動きを理解するまで頼りません。

    という態度は悪くないと思います。プログラムを書いた後、期待どおりに動かないのは普通なので必ずデバッグをしますが、その方法には以下の(A)~(C)などの手段を用います。

    ・実際には動かさず自分の頭の中で実行の様子をシミュレートする(A)
    ・プログラムの中に情報の印字コードを挿入し実際に動かして何が印字されるかで動きを観察する(B)
    ・デバッガーを使って実際に動かし要所要所で実行を止めながら変数の値をみたりして動きを観察する(C)

    質問者さんが「自分が動きを理解する」というのは(A)を行うために必要なことです。ぜひしっかり理解してください。ただある程度の大きさのプログラムは(A)だけで全て済むかといえばNOなので、大抵(B)や(C)をやることになります。どんなにベテランでもそうです。

    さて(A)~(C)は「自分が書いたコードが期待どおり動かないときの対処(デバッグ)」に用いる手法ですが、そういう場面ではなく「学習の段階で動きを理解する」目的でも有効と言えましょう。

    自分の回答は(A)のアプローチの際にどうコードの意味を把握するかということを述べたもので、mts10806さん回答は(C)のことを言っており、azuapricotさんの回答は(B)のアプローチを述べたものです。これらは全て「デバッグすること」「デバッグできるようになること」に関わる似たようなアドバイスだといえましょう。どれか一つだけでは充分ではありません。結局のところ(A)~(C)の全てができるようにならなければプログラミングはできないです。

    キャンセル

checkベストアンサー

+1

public class Main {
    public static void main(String[] args) throws Exception {
        boolean b1 = false;
        System.out.println("コード開始");
        for(int i=0; i<5; i++) {

            System.out.println("for文 i :" + (i + 1) + "回目開始");

            for(int j=0; j<5; j++) {

                System.out.println("for文 j :" + (j + 1) + "回目開始");

                if(b1 == false) {

                    System.out.println("b1がfalseなのでtrueにします。");

                    System.out.print("*");
                    b1 = true;
                }else {

                    System.out.println("b1がtrueなのでfalseにします。");

                    System.out.print("-");
                    b1 = false;
                }

                System.out.println("for文 j :" + (j + 1) + "回目終了");

            }

            System.out.println("for文 i :" + (i + 1) + "回目終了");
        }
        System.out.print("\n");
    }
}

↑ 初心者のときで流れがわからないなら要所要所でsysoutしましょう。
デバッグのやり方がわからなくてもこれなら流れがわかりますよね?

ちなみに実行結果は↓です

コード開始
fori :1回目開始

forj :1回目開始
b1がfalseなのでtrueにします。
*forj :1回目終了
forj :2回目開始
b1がtrueなのでfalseにします。
-forj :2回目終了
forj :3回目開始
b1がfalseなのでtrueにします。
*forj :3回目終了
forj :4回目開始
b1がtrueなのでfalseにします。
-forj :4回目終了
forj :5回目開始
b1がfalseなのでtrueにします。
*forj :5回目終了

fori :1回目終了

fori :2回目開始

forj :1回目開始
b1がtrueなのでfalseにします。
-forj :1回目終了
forj :2回目開始
b1がfalseなのでtrueにします。
*forj :2回目終了
forj :3回目開始
b1がtrueなのでfalseにします。
-forj :3回目終了
forj :4回目開始
b1がfalseなのでtrueにします。
*forj :4回目終了
forj :5回目開始
b1がtrueなのでfalseにします。
-forj :5回目終了

fori :2回目終了

fori :3回目開始

forj :1回目開始
b1がfalseなのでtrueにします。
*forj :1回目終了
forj :2回目開始
b1がtrueなのでfalseにします。
-forj :2回目終了
forj :3回目開始
b1がfalseなのでtrueにします。
*forj :3回目終了
forj :4回目開始
b1がtrueなのでfalseにします。
-forj :4回目終了
forj :5回目開始
b1がfalseなのでtrueにします。
*forj :5回目終了

fori :3回目終了

fori :4回目開始

forj :1回目開始
b1がtrueなのでfalseにします。
-forj :1回目終了
forj :2回目開始
b1がfalseなのでtrueにします。
*forj :2回目終了
forj :3回目開始
b1がtrueなのでfalseにします。
-forj :3回目終了
forj :4回目開始
b1がfalseなのでtrueにします。
*forj :4回目終了
forj :5回目開始
b1がtrueなのでfalseにします。
-forj :5回目終了

fori :4回目終了

fori :5回目開始

forj :1回目開始
b1がfalseなのでtrueにします。
*forj :1回目終了
forj :2回目開始
b1がtrueなのでfalseにします。
-forj :2回目終了
forj :3回目開始
b1がfalseなのでtrueにします。
*forj :3回目終了
forj :4回目開始
b1がtrueなのでfalseにします。
-forj :4回目終了
forj :5回目開始
b1がfalseなのでtrueにします。
*forj :5回目終了

fori :5回目終了

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

for文の中のfor文で回した値をif文で判定してtrueならその処理が実行され、
falseならelseが実行される。実行されたらブロックを抜けてまたfor文に戻って回された値が
trueならその処理falseならelseの処理をする。for文が5以下なら5の値が入ったらブロックを抜ける。

プログラムは箇条書きです. 箇条書きを続き文にすると分かり難いです.

私は「変数による各部への影響」から見ることが多い気がします.

i のループによる「j のループと if への影響」も, j のループによる「if への影響」も無い(変数 i も j もその内側で使われていない)ので, 2つのループで「5回ずつ回る」=「5x5=25回if文を実行」, です.

if 文では b1 だけが考慮され for には関係していないので, if 文のみに注目できます.
if の実行により b1 は, true → false または false → true になります. つまり if の実行前後で反転し, その時に print で(b1 に応じて}'*' や '-' を表示するので, 「交互の表示」となります.

「25回if文を実行」して「交互に表示」するので, '*' と '-' が交互に計25個表示される(b1 の初期値は false なので '*' から), と理解します.
おまけ的に最後に改行("\n")です.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/15 00:05

    今、 理解出来ました。1%から99%頭で解りました。

    キャンセル

0

一般論で回答します。

極論、プログラム処理を文書で示すことには限界があります。

私も就職して時間が経ち、「プログラミングよりも文書で仕事しろ」とか言われますが、結局プログラムについての説明はソースコードで示したほうが楽だと思うことは多々あります。

プログラム言語上では曖昧性がないですが、自然言語ではそうはいかないことも多いです。また、「AのときBをせよ、CのときDをせよ、そうでないときEをせよ」。といったことも文法上成立してしまいます(if-if-elseの曖昧性)。仕様書のバグに悩まされることも多々あります。

そして、仕様書どころか契約書にもバグは起こり得ます。世の中にはこのような解釈の多様性を悪用しようとか考える人もいます。私の学生時に、どう考えても出資金踏み倒しを前提としたインチキ計画に巻き込まれました。私の卒論題材となったアイディア(指導教官の特許)は、現物を作れないのに書類上仕事が成立したことになるというトンデモでした。

書面体制の打ち合わせでお金を集め、現物を作れない旨をバレたら契約書の欠陥を使って責任を逃れようとするという繰り返しに呆れました。

これなら書類に拘らない方がマシです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/15 01:20

    まず、この話しの趣旨は理解できました。

    コードを説明出来ないことにはコードが書けないので、そこは理解して説明できるまで質問はさせてください。

    ただ、仕様や設計書で文章に意味合いまで正しく書くことに拘らないという認識で正しいでしょうか。
    すみません。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る