[C++] 如果達到結束條件,是否可以在C ++之前退出?



Answers

儘管“ goto認為有害”的論點,這似乎是goto的理想場所。 這基本上就是你在Perl中所做的。 認真...考慮替代方案:

額外狀態變量

for (int i=0; i<maxi; ++i) {
    bool leaveLoop = false;
    for (int j=0; j<maxj; ++j) {
        if (i == 4 && j == 3) {
            leaveLoop = true;
            break; // leave the inner loop
        }
    }
    if (leaveLoop) {
        break; // leave the outside loop
    }
}

離開異常

try {
    for (int i=0; i<maxi; ++i) {
        for (int j=0; j<maxj; ++j) {
            if (i == 4 && j == 3) {
                throw leave_loop();
            }
        }
    }
} catch (leave_loop const&) {
}

複雜的邏輯

int j = 0;
for (int i=0; i<maxi && !(i==4 && j==3); ++i) {
    for (j=0; j<maxj && !(i==4 && j==3); ++j) {
        // inner loop
    }
}

goto

for (int i=0; i<maxi; ++i) {
    for (int j=0; j<maxj; ++j) {
        if (i==4 && j==3) {
            goto leave_loop;
        }
    }
}
leave_loop:

最後一個不太清楚嗎? 我不相信。 它更脆弱嗎? 恕我直言,其他人相當容易出錯和易碎的goto版本。 對不起,在這里站在肥皂箱,但這是困擾了我一段時間;)

你唯一需要認識的是goto和異常是非常相似的。 他們都為洩漏資源開闢了機會,不小心照顧他們。

Question

我想知道是否有可能在結束條件(不同於迭代的正確迭代次數)被驗證時,以C ++結束for循環。 例如:

for (int i = 0; i < maxi; ++i)
    for (int j = 0; j < maxj; ++j)
        // But if i == 4 < maxi AND j == 3 < maxj, 
        // then jump out of the two nested loops.

我知道這是可能的Perl與下一個LABEL或最後LABEL調用和標記塊,是有可能做到這一點在C + +或我應該使用一個while循環?

謝謝。




你不能用一個中斷指令跳出兩個循環,但你可以使用goto從外部的內部循環跳轉。

如果goto是本地化的,並且意味著邏輯比其他邏輯要少,那麼我認為這是完全可以接受的代碼。 有額外的標誌變量,或提升迭代器變量的內部循環,所以你可以比較它在外部循環不會使得更容易理解代碼恕我直言。




我一直試圖遠離goto語句(因為某種原因,在學校和我的工作中總是被忽視)。 我會用大明建議的東西。




重新考慮for結構的另一個原因是它的範圍限制在循環結束後阻止訪問受控變量。 在循環中被變異的變量的值可能由於各種原因而有用(例如,為了區分搜索中的成功和失敗)否則將需要額外的變量來在範圍退出之後保留該信息。 下面是一個小例子,它搜索名為a的方形數組作為target (假設SIZE不為零,否則不需要搜索!):

int i = 0;
int j = 0;
while (i < SIZE && a[i][j] != target) { // still in array but not at target
    if (SIZE <= ++j) {                  // fallen off the end of a row
        j = 0;
        ++i;
    }
}

後面的代碼可以使用i < SIZE來確定所需的值是否被定位。

以上的另一個優點是靈活性。 假設我們現在被告知a行中的值是遞增的,所以如果遇到大於target的值,則行的其餘部分是無關緊要的。 很容易知道要做出什麼樣的改變,以及在哪裡做出來。 因為這個新的信息讓我們放棄了目前的行,只有內在的決定受到影響,變成:

    if (target < a[i][j] || SIZE <= ++j) { // can't be in row or fallen off end
    ...

我看到更多的新語言(尤其是面向功能的語言)放棄了舊的“計數”循環結構; 這可能是一件好事,因為它鼓勵我們思考循環的意義 ,而不是簡單地計算。




bool done = false;

for (int i = 0; i < maxi && !done; ++i)
    for (int j = 0; j < maxj && !done; ++j)
        if (i == 4 && i < maxi && j == 3 && j < maxj )
             done = true;
        else {
        }

或者你可以轉到 或不 :-)




for (int i = 0; i < maxi; ++i)
{
    int j = 0;
    for (j = 0; j < maxj; ++j)
    {
         if (i == 4 && j == 3) // i < maxi and j < maxj otherwise we would not be here
             break; // exit inner loop
    }
    if (i == 4 && j == 3) // i < maxi and j < maxj otherwise we would not be here
        break; // exit outer loop
}



閱讀代碼不應該像讀一本偵探書(總是需要弄清楚)...

一個例子:

Java的:

iterate_rows:
for (int i = 0; i < maxi; ++i)
{       
    for (int j = 0; j < maxj; ++j)
    {
        if (i == 4 < maxi && j == 3 < maxj) 
            break iterate_rows;
        else
            continue iterate_rows;
    }   
}

你不需要弄清楚iterate_rows做了什麼,你只是閱讀它。

C ++:

//iterate_rows:
for (int i = 0; i < maxi; ++i)
{
    for (int j = 0; j < maxj; ++j)
    {
        if (i == 4 < maxi && j == 3 < maxj) 
            goto break_iterate_rows;
        else
            goto continue_iterate_rows;
    }

continue_iterate_rows:;
}
break_iterate_rows:;

goto break_iterate_rows只是break iterate_rows可見版本

如果你僅僅使用這種代碼來使用goto和標籤,你就不會搞清楚這個意圖。 限制你在這類代碼中使用goto和標籤會使你只是閱讀代碼,而不是分析或計算出來。 你不會被指責為一個邪惡的程序員。

如果你真的限制了你的代碼,你就可以養成一個習慣,不需要弄清楚代碼中的代碼是什麼。 增加的好處是你不必引入布爾值和跟踪他們(哪些恕我直言,導致你檢測代碼 ,使其有點難以理解,這就違背了避免goto的目的)

PS

將這些標籤與註釋(在循環之前)結合在一起,當你用goto語句讀過這些行時,你已經知道這些goto的意圖了






Links