Menggunakan lanjutkan dalam pernyataan sakelar

91

Saya ingin melompat dari tengah switchpernyataan, ke pernyataan loop dalam kode berikut:

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();
}

Apakah ini cara yang valid untuk digunakan continue? Apakah continuepernyataan diabaikan oleh switchpernyataan? Apakah C dan C ++ berbeda dalam perilakunya di sini?

Matt Joiner
sumber
Ide Anda bagus tetapi loop di atas tidak akan pernah dijalankan do_something().
antik
5
Bahkan jika kontrol mencapai kasus A atau kasus B?
Alexander Poluektov
18
Tadi saya akan berkata, antik salah tentang itu. Dalam kasus A atau B maka do_something () akan dieksekusi. Secara default, itu akan memberi jaminan.
Antony Woods
3
@acron, itulah perilaku yang diinginkan
Matt Joiner
1
Saya pikir ini terlihat jauh lebih mencurigakan & membingungkan dan karena itu lebih berbahaya daripada file goto.
phoeagon

Jawaban:

57

Tidak apa-apa, continuepernyataan tersebut terkait dengan loop yang melingkupi, dan kode Anda harus setara dengan (menghindari pernyataan lompat seperti itu):

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

Tetapi jika Anda berharap breakuntuk keluar dari loop, seperti yang disarankan oleh komentar Anda (selalu mencoba lagi dengan sesuatu yang lain, sampai bernilai false), Anda memerlukan struktur yang berbeda.

Sebagai contoh:

do {
    something = get_something();
} while (!(something == A || something == B));
do_something();
pengunjung
sumber
2
'setara' hanya dalam arti semantik. kode yang dihasilkan kompilator sangat berbeda. dengan pernyataan switch, kompilator dapat menghasilkan tabel lompat yang menghindari banyak perbandingan dan karenanya jauh lebih cepat daripada membandingkan dengan setiap elemen 1 dengan 1.
chacham15
@ chacham15, mengapa kompilator tidak dapat menghasilkan kode yang sama untuk keduanya?
avakar
Pernyataan switch @avakar menghasilkan tabel lompatan sedangkan representasi lainnya adalah serangkaian evaluasi logis. google jump table untuk informasi lebih lanjut.
chacham15
@ chacham15, apa yang mencegah kompilator untuk menghasilkan tabel lompat untuk dua pernyataan if atau serangkaian evaluasi logis untuk sakelar?
avakar
1
Pernyataan switch @avakar mengharuskan kasus menjadi nilai konstan, karena tidak demikian halnya dengan pernyataan if, tidak dapat membuat pengoptimalan yang sama (catatan: saya berbicara dalam kasus umum, dimungkinkan dengan persyaratan tertentu (misalnya hanya nilai const , hanya operator logika tertentu, dll.) untuk melakukan pengoptimalan, tetapi sangat bergantung pada compiler dan YMMV).
chacham15
21

Ya, tidak apa-apa - ini seperti menggunakannya dalam ifpernyataan. Tentu saja, Anda tidak dapat menggunakan a breakuntuk keluar dari loop dari dalam sakelar.


sumber
Tetapi iftidak berpengaruh pada perilaku continueatau break. Apa maksudmu itu sama?
Matt Joiner
@Matt Maksud saya itu akan melanjutkan loop dalam kedua kasus.
1
@Neil, oke, kebingungan dihindari.
Matt Joiner
1
@ KiJéy Saya tidak dapat menemukan referensi untuk ini, dan selama bertahun-tahun pemrograman C saya belum pernah melihat kompiler yang mendukung ini ... Di mana Anda menemukan ini?
arjunyg
2
Wow maaf, saya melihat ini di PHP, saya pikir itu praktik lama, ternyata hanya PHP ...
Ki Jéy
15

Ya, lanjutkan akan diabaikan oleh pernyataan sakelar dan akan pergi ke kondisi loop yang akan diuji. Saya ingin membagikan kutipan ini dari referensi Bahasa Pemrograman C oleh Ritchie:

The continuepernyataan berkaitan dengan break, tapi kurang sering digunakan; hal itu menyebabkan iterasi berikutnya dari melampirkan for, whileatau dolingkaran untuk memulai. Dalam whiledan do, ini berarti bahwa bagian uji dijalankan segera; di for, kontrol lolos ke langkah kenaikan.

Pernyataan lanjutkan hanya berlaku untuk loop, bukan untuk switchpernyataan. A continueinside a switchinside a loop menyebabkan iterasi loop berikutnya.

Saya tidak yakin tentang itu untuk C ++.

Islam Elshahat
sumber
8

Ini benar secara sintaksis dan secara gaya oke.

Gaya yang baik mengharuskan setiap case:pernyataan harus diakhiri dengan salah satu dari berikut ini:

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

Selain itu, case (x):segera ikuti dengan

 case (y):
 default:

diperbolehkan - menggabungkan beberapa kasus yang memiliki efek yang persis sama.

Ada lagi yang dicurigai sebagai kesalahan, seperti if(a=4){...} Tentu saja Anda perlu melampirkan loop ( while,for , do...while) untuk continuebekerja. Itu tidak akan berputar kembali case()sendirian. Tapi konstruksi seperti:

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

...baik-baik saja.

SF.
sumber
2
maaf untuk necroposting, tetapi saya akan menambahkan bahwa panggilan ke exitbiasanya juga merupakan hal yang baik untuk mengakhiri kasus sakelar.
Vality
1
Baiklah, saya akan mendapatkan semua Dr. Frankenstein di sini dan juga menunjukkan bahwa default:tidak harus menjadi entri terakhir / terbawah - seperti yang ditunjukkan oleh pertanyaan ini ...
SlySven
1
@SlySven: Secara leksikal, memang tidak, tetapi jika Anda tidak memiliki alasan yang baik untuk tidak membuatnya bertahan lama, lakukanlah yang terakhir. Seringkali membingungkan jika digunakan di tempat lain.
SF.
1
@Tokopedia baik, saya dapat dengan mudah membayangkan kasus-kasus ketika akan lebih masuk akal untuk menjadikan default:kasus sebagai yang pertama daripada yang terakhir. Seperti "lakukan ini, kecuali Anda mendapatkan nilai yang tidak biasa berikut, yang harus ditangani sebagai berikut".
Ruslan
5

Meskipun secara teknis valid, semua lompatan ini mengaburkan aliran kontrol - terutama continuepernyataannya.

Saya akan menggunakan trik seperti itu sebagai pilihan terakhir, bukan yang pertama.

Bagaimana tentang

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

Ini lebih pendek dan melakukan tugasnya dengan cara yang lebih jelas.

Alexander Poluektov
sumber
1
maaf atas kebingungan Alexander, kode ini hanya untuk demonstrasi, saya punya alasan bagus (saya percaya) untuk struktur aktual dalam kode saya.
Matt Joiner
2
@Matt: Itu mungkin akan berarti struktur yang lebih kabur ... :)
pengunjung
-2

Ini mungkin megabit sampai terlambat tetapi Anda bisa menggunakannya continue 2.

Beberapa build / config php akan menampilkan peringatan ini:

Peringatan PHP: tombol penargetan "lanjutkan" sama dengan "putus". Apakah Anda bermaksud menggunakan "lanjutkan 2"?

Sebagai contoh:

$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";
}

Ini akan menghasilkan:

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

Diuji dengan PHP 5.5 dan yang lebih tinggi.

Adrian S
sumber
3
Ini BUKAN pertanyaan PHP.
Geoffrey
-4

Switch tidak dianggap sebagai loop sehingga Anda tidak dapat menggunakan Continue inside a case statement in switch ...

Jitendra Nagar
sumber
3
The switchpernyataan di dalam whileloop, sehingga continuebenar-benar berlaku.
Rick