Kompilasi kode berikut dan dapatkan kesalahan dari type illegal
.
int main()
{
// Compilation error - switch expression of type illegal
switch(std::string("raj"))
{
case"sda":
}
}
Anda tidak dapat menggunakan string di salah satu switch
atau case
. Mengapa? Apakah ada solusi yang berfungsi baik untuk mendukung logika yang mirip dengan mengaktifkan string?
c++
string
switch-statement
yesraaj
sumber
sumber
QMetaEnum
Jawaban:
Alasan mengapa ada hubungannya dengan sistem tipe. C / C ++ tidak benar-benar mendukung string sebagai tipe. Itu mendukung gagasan array char konstan tetapi tidak benar-benar sepenuhnya memahami gagasan string.
Untuk menghasilkan kode pernyataan switch, kompiler harus memahami apa artinya dua nilai menjadi sama. Untuk item seperti int dan enum, ini adalah perbandingan bit sepele. Tetapi bagaimana seharusnya kompiler membandingkan 2 nilai string? Peka huruf besar-kecil, tidak peka, sadar budaya, dll ... Tanpa kesadaran penuh akan string, ini tidak dapat dijawab dengan akurat.
Selain itu, pernyataan switch C / C ++ biasanya dihasilkan sebagai tabel cabang . Tidak mudah menghasilkan tabel cabang untuk sakelar gaya string.
sumber
std::string
literal ditambahkan. Sebagian besar sejarah. Tapi satu masalah yang datang ke pikiran adalah bahwa dengan caraswitch
bekerja saat ini, menduplikasicase
s harus dideteksi pada saat kompilasi; namun ini mungkin tidak mudah untuk string (mempertimbangkan pemilihan lokal run-time dan sebagainya). Saya kira hal seperti itu harus memerlukanconstexpr
kasus, atau menambahkan perilaku yang tidak ditentukan (tidak pernah hal yang ingin kita lakukan).std::string
nilai atau bahkanstd::string
dengan array char char (yaitu dengan menggunakan operator ==) tidak ada alasan teknis yang akan mencegah kompiler membuat pernyataan switch untuk semua jenis yang menyediakan operator itu. Ini akan membuka beberapa pertanyaan tentang hal-hal seperti seumur hidup dari lables tetapi semua dalam semua ini terutama merupakan keputusan desain bahasa, bukan kesulitan teknis.Seperti disebutkan sebelumnya, kompiler suka membuat tabel pencarian yang mengoptimalkan
switch
pernyataan mendekati waktu O (1) bila memungkinkan. Gabungkan ini dengan fakta bahwa Bahasa C ++ tidak memiliki tipe string -std::string
adalah bagian dari Perpustakaan Standar yang bukan merupakan bagian dari Bahasa itu sendiri.Saya akan menawarkan alternatif yang mungkin ingin Anda pertimbangkan, saya sudah menggunakannya di masa lalu untuk efek yang baik. Alih-alih beralih di atas string itu sendiri, alihkan hasil dari fungsi hash yang menggunakan string sebagai input. Kode Anda akan hampir sejelas peralihan string jika Anda menggunakan serangkaian string yang telah ditentukan:
Ada banyak optimasi jelas yang cukup banyak mengikuti apa yang akan dilakukan oleh kompiler C dengan pernyataan switch ... lucu bagaimana itu terjadi.
sumber
C ++
Fungsi hash constexpr:
sumber
operator ""
untuk membuat kode lebih indah.constexpr inline unsigned int operator "" _(char const * p, size_t) { return hash(p); }
Dan gunakan seperticase "Peter"_: break;
DemoPembaruan C ++ 11 dari tampaknya bukan @MarmouCorp di atas tetapi http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4067/Switch-on-Strings-in-C.htm
Menggunakan dua peta untuk mengkonversi antara string dan enum kelas (lebih baik daripada enum polos karena nilainya dicakup di dalamnya, dan membalikkan pencarian untuk pesan kesalahan yang bagus).
Penggunaan statis dalam kode codeguru dimungkinkan dengan dukungan kompiler untuk daftar penginisialisasi yang berarti VS 2013 plus. gcc 4.8.1 ok dengan itu, tidak yakin berapa jauh itu akan kompatibel.
...
sumber
Masalahnya adalah bahwa untuk alasan optimasi, pernyataan switch di C ++ tidak berfungsi pada apa pun kecuali tipe primitif, dan Anda hanya dapat membandingkannya dengan konstanta waktu kompilasi.
Agaknya alasan pembatasan ini adalah bahwa kompiler dapat menerapkan beberapa bentuk optimisasi yang mengkompilasi kode ke satu instruksi cmp dan kebagian mana alamat tersebut dihitung berdasarkan nilai argumen saat runtime. Karena bercabang dan dan loop tidak bermain dengan baik dengan CPU modern, ini bisa menjadi optimasi penting.
Untuk menyiasatinya, saya khawatir Anda harus menggunakan pernyataan if.
sumber
std::string
dan orang lain menjadi warga negara pertama dalam bahasa tersebut dan mendukung mereka dalam pergantian pernyataan dengan algoritma yang efisien.std::map
+ C ++ 11 pola lambdas tanpa enumunordered_map
untuk potensi diamortisasiO(1)
: Apa cara terbaik untuk menggunakan HashMap di C ++?Keluaran:
Penggunaan metode dalam dengan
static
Untuk menggunakan pola ini secara efisien di dalam kelas, inisialisasi peta lambda secara statis, atau Anda membayar
O(n)
setiap waktu untuk membangunnya dari awal.Di sini kita bisa lolos dengan
{}
inisialisasistatic
variabel metode: Variabel statis dalam metode kelas , tetapi kita juga bisa menggunakan metode yang dijelaskan di: konstruktor statis di C ++? Saya perlu menginisialisasi objek statis pribadiItu perlu untuk mengubah penangkapan konteks lambda
[&]
menjadi argumen, atau yang tidak akan ditentukan: const static auto lambda digunakan dengan penangkapan dengan referensiContoh yang menghasilkan output yang sama seperti di atas:
sumber
switch
pernyataan. Duplikasi nilai kasus dalamswitch
pernyataan adalah kegagalan waktu kompilasi. Menggunakanstd::unordered_map
diam-diam menerima nilai duplikat.Dalam C ++ dan C switch hanya berfungsi pada tipe integer. Gunakan tangga yang lain sebagai gantinya. C ++ jelas bisa menerapkan semacam pernyataan swich untuk string - saya kira tidak ada yang menganggapnya berharga, dan saya setuju dengan mereka.
sumber
Kenapa tidak? Anda dapat menggunakan implementasi sakelar dengan sintaks yang setara dan semantik yang sama. The
C
bahasa tidak memiliki objek dan string objek sama sekali, tapi string diC
null dihentikan string direferensikan oleh pointer. TheC++
bahasa memiliki kemungkinan untuk membuat fungsi yang berlebihan untuk benda perbandingan atau memeriksa benda kesetaraan. SepertiC
yangC++
cukup fleksibel untuk memiliki saklar tersebut untuk string untukC
bahasa dan untuk objek dari jenis apa pun bahwa dukungan comparaison atau cek kesetaraan untukC++
bahasa. Dan modernC++11
memungkinkan implementasi switch ini cukup efektif.Kode Anda akan seperti ini:
Dimungkinkan untuk menggunakan tipe yang lebih rumit misalnya
std::pairs
atau struct atau kelas apa saja yang mendukung operasi kesetaraan (atau komunikasi untuk cepat mode ).fitur
Perbedaan sintax dengan saklar bahasa adalah
Untuk
C++97
bahasa digunakan pencarian linier. UntukC++11
dan yang lebih modern, gunakanquick
mode pencarian pohon di mana pernyataan kembali dalam KASUS tidak diizinkan. TheC
pelaksanaan bahasa ada di manachar*
jenis dan nol-dihentikan comparisions string digunakan.Baca lebih lanjut tentang implementasi sakelar ini.
sumber
Untuk menambahkan variasi menggunakan wadah sesederhana mungkin (tidak perlu peta yang dipesan) ... Saya tidak akan repot dengan enum - cukup masukkan definisi wadah segera sebelum beralih sehingga akan mudah untuk melihat nomor yang diwakilkan kasus yang mana.
Ini melakukan pencarian hash di
unordered_map
dan menggunakan yang terkaitint
untuk mengarahkan pernyataan switch. Seharusnya cukup cepat. Catatan yangat
digunakan sebagai ganti[]
, karena saya sudah membuat wadah ituconst
. Menggunakan[]
bisa berbahaya - jika string tidak ada di peta, Anda akan membuat pemetaan baru dan mungkin berakhir dengan hasil yang tidak ditentukan atau peta yang terus tumbuh.Perhatikan bahwa
at()
fungsi akan mengeluarkan pengecualian jika string tidak ada di peta. Jadi, Anda mungkin ingin menguji dulu menggunakancount()
.Versi dengan tes untuk string yang tidak ditentukan mengikuti:
sumber
Saya pikir alasannya adalah bahwa dalam string C bukan tipe primitif, seperti kata tomjen, pikirkan string sebagai array char, sehingga Anda tidak dapat melakukan hal-hal seperti:
sumber
Dalam c ++ string bukan warga negara kelas satu. Operasi string dilakukan melalui pustaka standar. Saya pikir, itulah alasannya. Juga, C ++ menggunakan optimasi tabel cabang untuk mengoptimalkan pernyataan kasus sakelar. Lihat tautannya.
http://en.wikipedia.org/wiki/Switch_statement
sumber
Di C ++ Anda hanya bisa menggunakan pernyataan switch pada int dan char
sumber
long
danlong long
, yang tidak akan berubah menjadiint
. Tidak ada risiko pemotongan di sana.sumber
dalam banyak kasus, Anda dapat melakukan kerja ekstra dengan menarik karakter pertama dari string dan mengaktifkannya. mungkin akhirnya harus melakukan switch bersarang pada karakter (1) jika kasing Anda mulai dengan nilai yang sama. siapa pun yang membaca kode Anda akan menghargai petunjuk karena sebagian besar akan prob hanya jika-lain-jika
sumber
Solusi yang lebih fungsional untuk masalah sakelar:
sumber
Anda tidak dapat menggunakan string dalam sakelar kasus. Hanya int & char yang diizinkan. Sebagai gantinya, Anda dapat mencoba enum untuk mewakili string dan menggunakannya di blok sakelar kasus seperti
Gunakan itu dalam pernyataan kasus swich.
sumber
Switch hanya berfungsi dengan tipe integral (int, char, bool, dll.). Mengapa tidak menggunakan peta untuk memasangkan string dengan angka lalu gunakan angka itu dengan sakelar?
sumber
Itu karena C ++ mengubah switch menjadi tabel lompatan. Ia melakukan operasi sepele pada data input dan melompat ke alamat yang tepat tanpa membandingkan. Karena string bukan angka, tetapi array angka, C ++ tidak dapat membuat tabel lompatan darinya.
(kode dari wikipedia https://en.wikipedia.org/wiki/Branch_table )
sumber
cmp
/jcc
implementasi bisa sama validnya dengan Standar C ++.