多重ループの脱出。

ループを途中で抜けるにはbreak;を呼びます。

for( int i = 0; i < size; ++i ){
	if( ... ){
		break;
	}
}

まあどんな入門書でも載っている内容ですね(^^;
ただし、多重ループは簡単には抜けられません。

for( int z = 0; z < iSizeZ; ++z ){
	for( int y = 0; y < iSizeY; ++y ){
		for( int x = 0; x < iSizeX; ++x ){
			if( ... ){
				//ここでbreakしても・・・
				break;
			}
		}
		//ここまでしか抜けられない。
	}
}

breakはループ1個分しか抜けられないので普通には全部抜けられません。しかし、多重ループを抜けるための構文はC++にはありません。というわけでいろいろ技巧的なことが必要になってきます。そんなわけでよくある方法をいくつか列挙すると・・・


方法その1:gotoを使う

for( int z = 0; z < iSizeZ; ++z ){
	for( int y = 0; y < iSizeY; ++y ){
		for( int x = 0; x < iSizeX; ++x ){
			if( ... ){
				goto LABEL;
			}
		}
	}
}
LABEL:

個人的にgoto否定派なのでまずやりませんが最も効率的だと思われる方法(根拠ナシ)。ただしgotoは静的解析ツールで無条件で警告が出ることが多いので企業の商品でやるといろいろ面倒かも。


方法その2:フラグを使う

bool bEnd = false;
for( int z = 0; z < iSizeZ; ++z ){
	for( int y = 0; y < iSizeY; ++y ){
		for( int x = 0; x < iSizeX; ++x ){
			if( ... ){
				bEnd = true;
			}
			if( bEnd ){ break; }
		}
		if( bEnd ){ break; }
	}
	if( bEnd ){ break; }
}

例だと3重ループなのでちょっと冗長ですが、2重ループくらいならよく使うと思います。チェックが多い分若干重くなります。


方法その3:関数を作る。

void Loop()
{
	for( int z = 0; z < iSizeZ; ++z ){
		for( int y = 0; y < iSizeY; ++y ){
			for( int x = 0; x < iSizeX; ++x ){
				if( ... ){
					return;
				}
			}
		}
	}
}

個人的に一番よく使います(^^; これが一番スッキリするんじゃないかなぁ・・・と思うのだがしかし場所によっては突然よくわからん関数が出てきて若干可読性に影響が。


方法その4:無理矢理1重ループにする

const int iSize = iSizeZ * iSizeY * iSizeX;
for( int xyz = 0; xyz = iSize; ++xyz ){
	const int z = xyz / ( iSizeY * iSizeX );
	const int y = ( xyz / iSizeX ) % iSizeY;
	const int x = xyz % iSizeX;
	if( ... ){
		break;
	}
}

たまにやります。というか、多重ループを抜けるのが目的でない場合が多いです。結果としてbreakしやすくなる場合が多いです。


方法その5:終了条件を偽造する。

for( int z = 0; z < iSizeZ; ++z ){
	for( int y = 0; y < iSizeY; ++y ){
		for( int x = 0; x < iSizeX; ++x ){
			if( ... ){
				x = iSizeX - 1;
				y = iSizeY - 1;
				z = iSizeZ - 1;
			}
		}
	}
}

これコードレビューやってて見つけました(^^;こんなやり方もあるんだなぁと感心してしまいました。開発者本人にレビュー会で指摘したら「他にどうやるの?」という至極当然な返事が返ってきました。


まあ、言語レベルでサポートされていればこんな苦労は無いんですけどね!