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.