Bir switch ifadesinde Continue kullanma


91

switchAşağıdaki kodda bir ifadenin ortasından döngü ifadesine atlamak istiyorum :

while (something = get_something())
{
    switch (something)
    {
    case A:
    case B:
        break;
    default:
        // get another something and try again
        continue;
    }
    // do something for a handled something
    do_something();
}

Bu geçerli bir kullanım yolu continuemu? Are continuetarafından göz ardı ifadeleri switchifadeleri? C ve C ++ buradaki davranışlarında farklılık gösterir mi?


Fikriniz iyi ama yukarıdaki döngü asla uygulanmayacak do_something().
— antik

5
Kontrol durum A'ya veya durum B'ye ulaşsa bile?
— Alexander Poluektov

18
"Antik bu konuda yanlış" diyecektim. A veya B durumunda do_something () çalıştırılacaktır. Varsayılan olarak, kefaletle ödenecektir.
— Antony Woods

3
@acron, o amaçlanan bir davranış
— Matt Joiner

1
Bence bu, a'dan çok daha şüpheli ve kafa karıştırıcı ve bu nedenle daha zararlı görünüyor goto.
— phoeagon

Yanıtlar:


57

Sorun değil, continueifade çevreleyen döngü ile ilgilidir ve kodunuz şuna eşdeğer olmalıdır (bu tür atlama ifadelerinden kaçınarak):

while (something = get_something()) {
    if (something == A || something == B)
        do_something();
}

Ancak break, yorumunuzun önerdiği gibi döngüden çıkmayı bekliyorsanız (yanlış olarak değerlendirilene kadar her zaman başka bir şeyle tekrar dener), farklı bir yapıya ihtiyacınız olacaktır.

Örneğin:

do {
    something = get_something();
} while (!(something == A || something == B));
do_something();

2
yalnızca semantik anlamda 'eşdeğer'. derleyicinin ürettiği kod çok farklıdır. bir switch deyimiyle, derleyici birden fazla karşılaştırmayı önleyen ve böylece her bir öğeyle 1'e 1 karşılaştırmaktan çok daha hızlı olan bir atlama tablosu oluşturabilir.
— chacham15

@ chacham15, derleyici neden ikisi için aynı kodu üretemedi?
— avakar

@avakar switch deyimleri atlama tabloları üretirken, diğer gösterim bir dizi mantıksal değerlendirmedir. daha fazla bilgi için google atlama tablosu.
— chacham15

@ chacham15, derleyicinin iki if ifadesi için bir atlama tablosu veya anahtar için bir dizi mantıksal değerlendirme oluşturmasını engelleyen nedir?
— avakar

1
@avakar switch ifadeleri vakaların sabit değerler olmasını gerektirir, çünkü if ifadelerinde durum böyle değildir, aynı optimizasyonu yapamaz (not: genel durumda konuşuyorum, belirli gereksinimler için mümkündür (örn. yalnızca const değerleri optimizasyonu yapmak için yalnızca belirli mantıksal operatörler, vb.
— chacham15

21

Evet, sorun değil - tıpkı bir ififadede kullanmak gibi . Tabii ki, breakbir anahtarın içinden bir döngüden çıkmak için a kullanamazsınız .


Ancak veya ifdavranışı üzerinde hiçbir etkisi yoktur . Nasıl benziyor demek istiyorsun? continuebreak
— Matt Joiner

@Matt Demek istediğim her iki durumda da döngüye devam edecek.

1
@Neil, tamam, kafa karışıklığı önlendi.
— Matt Joiner

1
@ KiJéy Bunun için herhangi bir referans bulamıyorum ve uzun yıllar C programlamasında bunu destekleyen herhangi bir derleyici görmedim ... Bunu dünyanın neresinde buldunuz?
— arjunyg

2
Vay canına, bunu PHP'de gördüm, eski bir uygulama olduğunu düşündüm, sadece PHP olduğu ortaya çıktı ...
— Ki Jéy

15

Evet, devam et switch deyimi tarafından yok sayılacak ve test edilecek döngünün durumuna gidecek. Bu alıntıyı Ritchie'nin The C Programming Language referansından paylaşmak istiyorum:

continueİfadesi ile ilgilidir break, ama daha az sıklıkta kullanılan; çevrelemenin sonraki yinelemesine neden olur for,while ya da dobaşlamak için döngü. Gelen whileve dobu yollarla deney parçası, çabucak yürürlüğe girer bu; içinde for, kontrol artırma adımına geçer.

Continue ifadesi yalnızca döngüler için geçerlidir, bir switch deyimi deyime . Bir continueiçinde bir switchdöngü içine sonraki döngü iterasyon neden olur.

C ++ için bundan emin değilim.


8

Sözdizimsel olarak doğru ve biçimsel olarak iyi.

İyi bir stil, her case:ifadenin aşağıdakilerden biriyle bitmesini gerektirir :

 break;
 continue;
 return (x);
 exit (x);
 throw (x);
 //fallthrough

Ek olarak, case (x):hemen ardından

 case (y):
 default:

izin verilebilir - tam olarak aynı etkiye sahip birkaç durumu bir araya getirmek.

Başka bir şey gibi, bir hata olduğundan şüphelenilen if(a=4){...} Tabii ki döngü (çevreleyen gerek while, for, do...whileiçin) continueişe. case()Tek başına dönmeyecek . Ancak şöyle bir yapı:

while(record = getNewRecord())
{
    switch(record.type)
    {
        case RECORD_TYPE_...;
            ...
        break;
        default: //unknown type
            continue; //skip processing this record altogether.
    }
    //...more processing...
}

...tamam.


2
necroposting için özür dilerim, ancak bir çağrının exitda genellikle bir geçiş durumunu sonlandırmak için iyi bir şey olduğunu ekleyeceğim .
— Vality

1
Pekala, tüm Dr. Frankenstein'ı buraya getireceğim ve ayrıca default:bunun son / alt giriş olması gerekmediğine de işaret
— edeceğim

1
@SlySven: Sözcüksel olarak öyle değil, ama bunu uzun sürmemek için iyi bir sebebin yoksa, sürmesini sağla. Başka yerlerde kullanılırsa genellikle kafa karıştırıcıdır.
— SF.

1
@SF. Pekala, default:vakayı son yerine ilk duruma getirmenin daha mantıklı olacağı durumları kolayca hayal edebiliyorum . "Aşağıdaki gibi ele alınması gereken aşağıdaki sıra dışı değerleri elde etmezseniz bunu yapın" gibi.
— Ruslan

5

Teknik olarak geçerli olsa da, tüm bu sıçramalar kontrol akışını, özellikle de continueifadeyi belirsizleştirir .

Böyle bir numarayı son çare olarak kullanırdım, ilki değil.

Ne dersin

while (something = get_something())
{
    switch (something)
    {
    case A:
    case B:
        do_something();
    }        
}

Daha kısadır ve işlerini daha net bir şekilde gerçekleştirir.


1
karışıklık için özür dilerim Alexander, kod sadece gösteri amaçlıdır, kodumdaki gerçek yapı için iyi bir nedenim var (inanıyorum).
— Matt Joiner

2
@Matt: Bu muhtemelen daha karmaşık bir yapı anlamına gelir ... :)
— ziyaretçi

-2

Bu geç bir megabit olabilir ama kullanabilirsiniz continue 2.

Bazı php yapıları / yapılandırmaları şu uyarıyı verecektir:

PHP Uyarısı: "devam" hedefleme anahtarı "ara" ile eşdeğerdir. "Devam 2" mi demek istediniz?

Örneğin:

$i = 1;

while ($i <= 10) {
    $mod = $i % 4;
    echo "\r\n out $i";
    $i++;
    switch($mod)
    {
        case 0:
            break;
        case 2:
            continue;
            break;
        default:
            continue 2;
            break;
    }
    echo " is even";
}

Bu çıktı:

out 1
out 2 is even
out 3
out 4 is even
out 5
out 6 is even
out 7
out 8 is even
out 9
out 10 is even

PHP 5.5 ve üstü ile test edilmiştir.


3
Bu bir PHP sorusu DEĞİLDİR.
— Geoffrey

-4

Eğer kullanmayın böylece Anahtarı döngü olarak kabul edilmez Devam anahtarı bir olgu deyimi içinde ...


3
switchİfadesi bir içindeyse whilebu yüzden, döngü continuemükemmel geçerlidir.
— Rick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.