回答:
私の知る限り、C ++はJavaや他の言語のように命名ループをサポートしていません。gotoを使用するか、使用するフラグ値を作成できます。各ループの最後にフラグの値を確認します。trueに設定されている場合、その反復から抜け出すことができます。
goto
それが最善の選択肢である場合は、使用することを恐れないでください。
goto
:悪いプログラマーと実用的なプログラマー。前者は自明です。後者は、それらをうまく使用することを選択した場合に当てはまるものであり、(2つの)悪のほうが小さい場合は、いわゆる「悪」の概念を使用します。時々使用する必要があるかもしれないいくつかのC ++の概念(マクロ、goto、プリプロセッサ、配列)をよりよく理解するためにこれを読んでください:parashift.com/c++
goto
ですが、ほとんど使用しないことが最善のオプションです。ループを独自の関数に入れて(inline
速度が気になる場合は)、これからreturn
どうですか?
いいえ、それを台無しにしないでくださいbreak
。これは、を使用するための最後の残りの拠点ですgoto
。
ラムダを使用して明示的な回答を追加するだけです:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
もちろん、このパターンには一定の制限があり、明らかにC ++ 11のみですが、それは非常に便利だと思います。
ネストされたループから抜け出す別のアプローチは、両方のループを別々の関数に分解し、return
終了するときにその関数から取り除くことです。
もちろん、これによりreturn
、関数の最後以外の場所から明示的に関数を明示的に実行する必要があるかどうかという別の議論が生じます。
continue_processing
は、関数のさらに下のコードブロックの実行を制御するブール変数(などの名前)が散らばった関数がありました。
breakは、それを含む最も内側のループのみを終了します。
gotoを使用して、任意の数のループから抜け出すことができます。
もちろんgotoはしばしば有害と見なされます。
ブレーク機能を使用するのは適切ですか[...]?
breakとgotoを使用すると、プログラムの正確性を判断するのが難しくなる場合があります。これについての議論はここを見てください: ダイクストラは正気ではありませんでした。
break
orの使用を勧めreturn
ます。
break
そしてreturn
、goto
どこに行くかを見つけるためにラベルを探す必要がないという利点よりも優れています。はい、その下にはなんらかの種類がgoto
ありますが、非常に制限されています。それらは、制限のないものよりも、プログラマーのパターンマッチングの脳によって解読するのがはるかに簡単goto
です。したがって、IMOの方が望ましいです。
goto
。よりも許容範囲が広いです。
この回答はすでに提示されていますが、次のようにすることをお勧めします。
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
gotoMainLoop
サイクルごとにチェックされるため、コードが「かなり」遅くなります
goto
を使用すると、コアが読みやすくなり、パフォーマンスが向上します。
これはどう?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
ネストされた複数のループから抜け出すための良い方法の1つは、コードを関数にリファクタリングすることです。
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
gotoはネストされたループを壊すのに非常に役立ちます
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
私はgoto
この状況では有効だと思います:
break
/ をシミュレートするにはcontinue
、次のようにします。
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
。したがってi++
、
PHPなどの他の言語では、break(つまり、break 2;)のパラメーターを受け入れて、ブレークアウトしたいネストされたループレベルの量を指定しますが、C ++では受け入れません。ループの前にfalseに設定したブール値を使用してそれを解決する必要があります。ブレークする場合はループでtrueに設定し、ネストされたループの後に条件付きブレークを実行して、ブール値がtrueに設定されているかどうかを確認します。はいの場合は中断します。
私はこれが古い記事であることを知っています。しかし、私は少し論理的で簡単な答えを提案します。
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
j = conditionj
代わりに複雑な述語がある場合は機能しないため、これは非常にスケーラブルなソリューションではありませんj < conditionj
。
bool
以下の1つの変数だけでループをいくつでも分割できます。
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
このコードでは、break;
すべてのループを処理しています。
価値があるかどうかはわかりませんが、Javaの名前付きループをいくつかの簡単なマクロでエミュレートできます。
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
使用例:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
もう一つの例:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
try ... catchを使用できます。
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
一度に複数のループから抜け出す必要がある場合は、とにかく例外です。
forループのセマンティクスは通常、指定された回数実行されることを示しているため、forループから抜け出すことは少し奇妙です。ただし、すべての場合に悪いわけではありません。コレクションで何かを検索していて、それを見つけた後で中断したい場合は、便利です。ただし、ネストされたループから抜け出すことは、C ++では不可能です。ラベル付きの区切りを使用することにより、他の言語でも使用できます。ラベルと後藤を使うこともできますが、夜になると胸が痛くなるかもしれません。しかし、最良のオプションのようです。