如何在Objective-C中打破两个嵌套for循环?
我有两个类似这样嵌套的for循环:如何在Objective-C中打破两个嵌套for循环?,c,objective-c,loops,C,Objective C,Loops,我有两个类似这样嵌套的for循环: for(...) { for(...) { } } for(i=0;i<a;i++){ for(j=0;j<a;j++){ if(Something_goes_wrong){ i=a; break; } } } 我知道有一个break语句。但是我很困惑,它是打破了两个循环,还是仅仅打破了调用它的那个循环?一旦我发现重复更多次没有意义,我就需要中断两个循环。中断从一个循环中断,但您可以向外部循环添加
for(...) {
for(...) {
}
}
for(i=0;i<a;i++){
for(j=0;j<a;j++){
if(Something_goes_wrong){
i=a;
break;
}
}
}
我知道有一个
break
语句。但是我很困惑,它是打破了两个循环,还是仅仅打破了调用它的那个循环?一旦我发现重复更多次没有意义,我就需要中断两个循环。中断从一个循环中断,但您可以向外部循环添加一个检查,当内部循环中断时,外部循环中断
bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
for ( ... ) {
if (...) {
dobreak = true;
break;
}
}
}
如果从一组嵌套循环中执行中断,则仅终止执行中断的最内层循环。(就像标准C)break语句只会在作用域中中断循环,即父循环。如果您还想中断第二个循环,那么可以使用一个布尔变量,该变量位于两个循环的范围内
bool isTerminated = false;
for (...)
{
if (!isTerminated)
{
for(...)
{
...
isTerminated = true;
break;
}
}
else
{
break;
}
}
break语句从最里面的循环中断。需要额外的test和break语句来中断外部循环。最简单的方法可能是使用“flag”变量
for(i=0; i<10 && (done==false); i++)
for(j=0;j< 10; j++){
..
..
if(...){done=true; break;}
}
for(i=0;i在中断前更改顶部循环的计数器
for(i=0; i<10 ; i++)
for(j=0;j< 10; j++){
..
..
i = 10;
break;
}
for(i=0;i的break
语句只会使您脱离最内部的循环。如果您不想增加专用状态变量在代码、内存和性能方面的额外开销,我建议将代码重构为其自身的函数或方法,并使用return
退出所有循环:
void do_lots_of_work(void)
{
int i, j;
for(i=0; i<10 ; i++)
{
for(j=0;j< 10; j++)
{
..
..
if(disaster_struck())
return; /* Gets us out of the loops, and the function too. */
}
}
}
void大量工作(void)
{
int i,j;
对于(i=0;i如果使用goto简化代码,那么它将是合适的
for (;;)
{
for (;;)
{
break; /* breaks inner loop */
}
for (;;)
{
goto outer; /* breaks outer loop */
}
}
outer:;
其他人提到了如何设置标志或使用goto
,但我建议重构代码,以便将内部循环转换为单独的方法。然后,该方法可以返回一些标志,指示外部循环应中断
。如果适当地命名方法,则可读性更高
for (int i = 0; i < 10; i++) {
if (timeToStop(i)) break;
}
-(bool) timeToStop: (int) i {
for (int j = 0; j < 10; j++) {
if (somethingBadHappens) return true;
}
return false;
}
for(int i=0;i<10;i++){
如果(时间停止(i))中断;
}
-(bool)timeToStop:(int)i{
对于(int j=0;j<10;j++){
如果(某些错误发生)返回true;
}
返回false;
}
伪代码,未经测试,但您知道了。除了前面提到的flag变量或goto之外,您可以使用Objective-C异常:
@try {
for() {
for() {
@throw ...
}
}
}
@catch{
...
}
另一种解决方案是在函数中计算出第二个循环:
int i;
for(i=0; i<10 ; i++){
if !innerLoop(i) {
break;
}
}
bool innerLoop(int i)
int j;
for(j=0;j< 10; j++){
doSomthing(i,j);
if(endcondtion){
return false;
}
}
}
inti;
对于(i=0;i而言,与最后一个完全相同,通常如下所示:
for(...) {
for(...) {
}
}
for(i=0;i<a;i++){
for(j=0;j<a;j++){
if(Something_goes_wrong){
i=a;
break;
}
}
}
对于(i=0;i仅对于GRIN,如何将此对/错检查更改为一个方法并使用return
语句:
- (bool) checkTrueFalse: parameters{
for ( ...) {
for ( ... ) {
if (...) {
return true;
}
}
}
return false;
}
我不太喜欢这个。风险是有人在一个地方更改退出条件,而忘记了另一个。NSUInteger limit=10;
然后:for(I=0;iTo对此展开,for(;){for(;){break;/*breaks internal loop*/}for(;){goto outer;/*breaks outer loop*/}outer:
(;)看起来有点像一张小脸。如果循环中的函数调用能够像专用状态变量一样执行,我会非常惊讶,尤其是如果你需要传递参数才能访问外部函数中的变量。也许如果编译器内联复制函数……在我看来,更糟糕的是失去了取消通过在一个地方读取来理解算法。所有这些都是为了避免跳转?我也遇到了这个中断/继续问题,有时想继续循环2-3级。最好的办法是将嵌套循环重构为一个方法,这样方法就可以返回是否继续父循环。如果用户只想退出e循环而不是函数?在我看来,这是最好的解决方案。它清楚地说明了发生了什么,易于控制,易于调用,不分配和计算不必要的布尔值,也不使用危险的旧做法,如goto
。在任何实际使用中,性能问题也不值得注意。IMHO,使用goto更干净。!dobreak
位于错误的位置;它应该位于条件(for的第二部分)而不是增量步骤(for的第三部分);我也会使用!dobreak&..
,这样在破坏时就不需要评估其他条件。我同意sigjuice:goto
在正确使用时并不邪恶,在这种情况下,goto
确实会产生更好的代码。这仍然会在inn之后的外部循环中执行可能的代码呃loop@Martijn-这可以通过用continue
语句替换break
来解决。不过,这只是更不明显的问题。哇,就在我即将修改我的答案以指出人们将如何建议每一个复杂的解决方案时,除了使用流控制异常以避免跳转之外。。@Ori Pessach Well异常是goto的现代OO版本;-)它们至少可以很好地清理堆栈。根据我的经验,异常非常缓慢,不应该用于处理执行流。对ObjC中的异常进行一些研究。在Apple文档中,它们特别指出性能影响很大,并说,“Cocoa框架通常不是异常安全的。通常的模式是,异常只保留给程序员错误,捕获此类异常的程序应该在之后很快退出。”@Jonny这些被称为Obj-C中的快速枚举循环