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

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

ただいまの
回答率

90.84%

  • JavaScript

    14304questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • HTML

    7805questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

break ラベル;で思うように飛ばないです

解決済

回答 2

投稿 編集

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

ko20vonobird

score 41

前提・実現したいこと

フォームから得られた自然数で四則演算のみが用いられた数式を評価して、答えを返すというプログラムの製作途中です。

発生している問題

ブレークポイントを用いて確認したところ、break subloop;でsubloop:に戻るという動作を期待しているのですが、なぜかいくらかforが実行された後for文を抜けて最後のアラート(式の評価)に飛びます。感覚的にはbreak ラベル;が実行されていない感じです。

該当のソースコード

function keisan() { //a
            /*try{*/
            var chk1 = 0
            var str = document.siki.mainsiki.value;
            var strlong = str.length;
            for (var cnt = 0; cnt < 10; cnt++) { //b
                if (str.indexOf(cnt, 0) != 0) { //c
                    chk1++
                } //c
            } //b
            if (chk1 > 9) { //d
                alert("最初の文字は数字にしてください");
                return;
            } //d
            var siki = str;
            var sikilong = siki.length; //0-x + 1
            var sisoku = new Array();
            sisoku[0] = '+';
            sisoku[1] = '-';
            sisoku[2] = '*';
            sisoku[3] = '/';
            var sisokunum = 0;
            /*var sisokunochk = 0;*///不要?
            for (var cntstrnum = 0; cntstrnum < sikilong; cntstrnum++) { //e
                var chk = siki.charAt(cntstrnum);
                for (var cnta = 0; cnta < 4; cnta++) { //f
                    if (chk == sisoku[cnta]) { //g
                        sisokunum = sisokunum + 1;
                    } //g
                } //f
            } //e
            if (sisokunum == 0) { //h
                alert("答え:" + siki);
                return;
            } //h
            var sisokunochk = 0;//テスト//
            /*loop:*/
            for (var cntmain = 0; cntmain < 2; cntmain++) { //i////gotoの代わり
                /*var sikip = "";
                if (sisokunochk != 0) {
                    continue loop;
                }*/
                subloop: 
                for (var cntb = 0; cntb < sikilong; cntb++) { //j
                    var sisokunochk = 0;//テスト//
                    var sikip = "";//テスト//
                    var counter = 0;
                    var countertwo = 0;
                    var sikipa = "";
                    var sikipb = "";
                    var sikisisoku = "";
                    var sikiright = "";
                    var twosisoku = 0;////
                    for (var cntxyz = 2; cntxyz < 4; cntxyz++) {//xyz
                        if (sisoku[cntxyz] == siki.charAt(cntb)){//cntxyz
                            twosisoku = 1;
                        }//cntxyz
                    }//xyz
                    for (var cntz = 0; cntz < 4; cntz++) { //k
                        if (sisoku[cntz] == siki.charAt(cntb)) { //l
                            counter = 1;
                        } //l
                    } //k
                    if (counter == 0) { //m
                        sikip = sikip + siki.charAt(cntb); //sikipはsikiの計算する部分の記録用
                        if (cntb == sikilong - 1) { //n
                            sikipb = sikip;
                        } //n
                    } else if (counter == 1) { //m
                        for (var cnty = 2; cnty < 4; cnty++) { //o
                            if (sisoku[cnty] == siki.charAt(cntb)) { //p
                                if (sikipa == "") { //q
                                    sikipa = sikip;
                                    sikip = "";
                                } else { //q
                                    sikipb = sikip;
                                    sikiright = siki.substr(cntb + 1, sikilong - 1); //怪しい
                                } //q
                                sikisisoku = siki.charAt(cntb);
                                continue;
                            } //p
                        } //o
                    } //m
                    for (var cntx = 0; cntx < 2; cntx++) { //r
                        if (sisoku[cntx] == siki.charAt(cntb) && twosisoku == 0) { //s//twosisokuは*/の数
                            sikipa = sikip
                            sikip = "";
                            sikisisoku = siki.charAt(cntb);
                        } else if (sisoku[cntx] == siki.charAt(cntb) && twosisoku > 0) { //s
                            sikip = "";
                        } //s
                    } //r

                    if (sikisisoku != "" && sikipa != "" && sikipb != "") { //s2
                        if (sikisisoku == sisoku[0]) { //t
                            sikileft = sikipa + sikipb;
                            siki = sikileft.toString() + sikiright.toString(); //以下共通
                        } else if (sikisisoku == sisoku[1]) { //t
                            sikileft = sikipa - sikipb;
                            siki = sikileft.toString() + sikiright.toString();
                        } else if (sikisisoku == sisoku[2]) { //t
                            sikileft = sikipa * sikipb;
                            siki = sikileft.toString() + sikiright.toString();
                        } else if (sikisisoku == sisoku[3]) { //t
                            sikileft = sikipa / sikipb;
                            siki = sikileft.toString() + sikiright.toString();
                        } //t
                    } //s2
                    sikilong = siki.length; //計算後を想定した記述
                    sisokunochk = 0;
                    for (var cntc = 0; cntc < sikilong; cntc++) { //t
                        var chka = siki.charAt(cntc);
                        for (var cntd = 0; cntd < 4; cntd++) { //u
                            if (chka == sisoku[cntd]) { //v
                                sisokunochk = sisokunochk + 1;
                            } //v
                        } //u
                    } //t
                    if (sisokunochk == 0) { //w
                        continue; //もう四則演算子がない
                    } //w
                    if (sisokunochk != 0) { //x
                        continue subloop; //まだ四則演算子がある
                    } //x
                } //j

            } //i
            alert("答え:" + siki);
            return;

            /*}catch(e){
            alert("式が不適合もしくはエラーです。");
            return;
            }
            finally{
            return;
            }*/
        } //a

試したこと

ブレークポイントを設定し、どうプログラムが進んでいるのかを詳細に調べました。また、ラベルで該当する文を{}で囲み、for文としてでなくラベル文として機能するようにしました。

補足

"1+4"で検証しました。

修正したこと

ラベル {}の{}を削除
break ラベルをcontinue ラベルに変更

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2017/01/08 20:45

    回答が付いた質問の編集は慎重に行ってください。質問文のコードについて回答にて指摘があった場合は「追記」し、元のコードを編集する場合も「直したこと」がわかるようにしてください。

    キャンセル

  • ko20vonobird

    2017/01/08 21:00

    修正したこと、の項目を設けました。

    キャンセル

回答 2

checkベストアンサー

+2

たぶん、やりたいことと、berakの動作についての認識が逆になっていると思われます。

やりたいことは、break subloop;の所で、ループの最初からやり直したいということであってますでしょうか?もし、そうであれば、使うのはbreakではなくcontinueです。しかし、このままcontinueに変えても動作しません。

まず、次のコードを動かしてみてください。

console.log("test before");
test: for (let i = 0; i < 10; i++) {
  console.log(i);
  if (i < 5) {
    continue test;
  } else {
    break test;
  }
}
console.log("test after");

下記のようになったと思います。

"test before"
0
1
2
3
4
5
"test after"

コードの動作を見てみると、iが0から4のときは、continue test;が処理されますが、これはループの最初に戻っています。逆に、iが5になった瞬間にbreak test;が処理され、ループを抜けています。

コードからわかるとおり、break ラベルはラベルの位置に戻るのではなく、ラベルの付いたブロック(ループでない場合も同じ)を抜ける、つまり、ブロックが終わったところに処理が移ると言うことです。もし、ラベルの位置に戻りたい場合は、continue ラベルを使う必要がありますが、continueループにしか使用できません

以上を踏まえて処理を見直してみてください。また、深いループは混乱の元ですので、関数に小分けすると、わかりやすくなると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/01/08 20:50

    なるほど、つまり、breakラベルは他の言語でのgotoの働きではないのですね、、、勘違いをしていました。continueはforがラベルの次の文章に記述されていれば、ラベルに飛ぶということでしょうか?
    また、ここ2、3日これを作っているのですが、恥ずかしながら混乱しております。なので、お聞きしますが、これの目的は式を計算し答えを出すというものなのですがなぜか式が返されます。これの原因は一体何なのでしょうか??

    キャンセル

  • 2017/01/08 20:59

    そうですね。JavaScriptのラベルはbreakやcontinuneの対象を指定できるという意味以上は無いですので、gotoとは同じ動作になりません。

    すいません、私も途中でコードが追えなくなってきて、何をやっているのかよくわからないです。私からのアドバイスは一つ、処理を関数に小分けすることです。ブロック単位でもいいですので、何が入力で何が出力なのかをはっきりさせながら、別の関数にしてみてはいかがでしょうか?

    キャンセル

  • 2017/01/08 21:18

    恐縮です。
    関数に小分けするということを試してみようと思うのですが、大元のfunction()の中にさらにfunction()を作るということで合っていますか?また、その場合、子関数は親関数の中に記述するということで良いのでしょうか?

    キャンセル

  • 2017/01/08 22:06

    JavaScriptは関数の中に関数を作れますが、クロージャーを理解しておく必要がありますので、必要で無ければお勧めしません。基本的にトップレベルに関数を並べると考えてください。関数にするのは「入力」と「出力」をはっきりさせるためです。例えば、「演算子、値1、値2」という入力に対して「結果」という出力を得る、等と言った一つの処理を関数として小分けに作って行きます。それを、大本の関数から呼び出します。

    あまり関数を作ったことが無ければ、いきなりこの課題でするのはちょっと難しいかも知れません。計算機のようなものを作るという課題は、結構ハードルは高めです。

    キャンセル

  • 2017/01/08 22:15

    クロージャ―、少々調べてみましたが、一筋縄ではいかないようですね。他の言語にあるメンバ変数とかが関わってくるのでしょうか。
    ハードルは確かに、今やっていて難しいと感じるばかりです、、、。
    今は言うて暇があまりないので勉強する時間は取れませんが、取れるようになれば再び勉強しようかと思います。

    キャンセル

0

ブレークポイントが指定できているのであれば、ループカウンタの値がどのように変化しているのか分かりますか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/01/08 19:50

    調べたところ、ループカウンタcntbは、0のままでした

    キャンセル

  • 2017/01/08 20:16

    subloopラベルの直前にあるfor文のループカウンタ [cntmain]はどうですか?

    キャンセル

  • 2017/01/08 20:45

    cntmainは0から1にて動作していました。

    キャンセル

  • 2017/01/08 21:06

    そのカウンタの変化は想定されているものでしょうか?
    [break subloop;]が実行されているので、そのような動作になると思うのですが・・・。
    あと、他の方の回答にもありますが、処理の見通しが悪いように思いますので、関数化したほうが良いと思います。

    キャンセル

  • 2017/01/08 21:16

    cntmainに関しては、0から1に変化する際に必要な処理を記述するためだけのfor文です。
    なるほど、break subloop;ですか、、。
    そうですね、関数化する方向で調整しようと思います。

    キャンセル

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

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

関連した質問

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

  • JavaScript

    14304questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • HTML

    7805questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。