Bagaimana cara menerapkan yang berikut (Python pseudocode) di C ++?
if argv[1].startswith('--foo='):
foo_value = int(argv[1][len('--foo='):])
(Misalnya, jika argv[1]
ada --foo=98
, maka foo_value
adalah 98
.)
Pembaruan: Saya ragu-ragu untuk melihat Boost, karena saya hanya ingin membuat perubahan kecil ke alat command-line kecil yang sederhana (saya lebih suka tidak harus belajar cara menautkan dan menggunakan Boost untuk anak di bawah umur perubahan).
Jawaban:
Gunakan kelebihan
rfind
yang memilikipos
parameter:Siapa yang butuh yang lain? STL murni!
Banyak yang salah membaca ini berarti "mencari mundur seluruh string mencari awalan". Itu akan memberikan hasil yang salah (misalnya
string("tititito").rfind("titi")
mengembalikan 2 sehingga bila dibandingkan terhadap== 0
akan kembali salah) dan itu akan menjadi tidak efisien (melihat seluruh string bukan hanya awal). Tapi itu tidak melakukan itu karena melewatipos
parameter sebagai0
, yang membatasi pencarian hanya cocok pada posisi itu atau sebelumnya . Sebagai contoh:sumber
find
hanya akan nol jikatiti
berada di awal string. Jika ditemukan di tempat lain, Anda akan mendapatkan nilai balik tidak nol dan, jika tidak ditemukan, Anda akan mendapatkannpos
yang juga bukan nol. Dengan asumsi saya benar, saya lebih suka jawaban ini karena saya tidak harus membawa barang-barang non-standar (ya, saya tahu Boost ada di mana-mana, saya hanya lebih suka core C ++ libs untuk hal-hal sederhana seperti ini).titi
, tetapi bagian konversi tidak ada.rfind()
yang tidak mengambilpos
parameter. Jika Anda menggunakan overload yang mengambilpos
parameter maka itu tidak akan mencari seluruh string, hanya posisi itu dan sebelumnya. (Sama seperti biasafind()
denganpos
parameter hanya terlihat di posisi itu atau yang lebih baru.) Jadi jika Anda luluspos == 0
, seperti yang ditunjukkan dalam jawaban ini, maka secara harfiah hanya akan mempertimbangkan untuk pertandingan di satu posisi itu. Itu sudah menjelaskan baik dalam jawaban maupun komentar.Anda akan melakukannya seperti ini:
Mencari lib seperti Boost.ProgramOptions yang melakukan ini untuk Anda juga merupakan ide yang bagus.
sumber
atoi("123xyz")
kembali123
, sedangkan Pythonint("123xyz")
melemparkan pengecualian.atoi
denganstrtol
ataustrtoll
, yang memungkinkan kami mendeteksi kondisi kesalahan dalam nilai input.rfind
yang tergantung pada optimasi untuk bekerja.Hanya untuk kelengkapan, saya akan menyebutkan cara C untuk melakukannya:
(awalnya diposting oleh Yaseen Rauf di sini , markup ditambahkan)
Untuk perbandingan case-insensitive, gunakan
strnicmp
sebagai gantistrncmp
.Ini adalah cara C untuk melakukannya, untuk string C ++ Anda dapat menggunakan fungsi yang sama seperti ini:
sumber
memcmp()
Jika Anda sudah menggunakan Boost, Anda bisa melakukannya dengan meningkatkan algoritma string + boost cast lexical:
Pendekatan semacam ini, seperti banyak jawaban lain yang disediakan di sini adalah ok untuk tugas yang sangat sederhana, tetapi dalam jangka panjang Anda biasanya lebih baik menggunakan parsing library baris perintah. Boost memiliki satu ( Boost.Program_options ), yang mungkin masuk akal jika Anda sudah menggunakan Boost.
Kalau tidak, pencarian untuk "c ++ command line parser" akan menghasilkan sejumlah opsi.
sumber
Kode yang saya gunakan sendiri:
sumber
substr
lead untuk menyalin yang tidak perlu. Thestr.compare(start, count, substr)
Metode yang digunakan dalam jawaban Thomas' lebih efisien. Jawaban razvanco13 memiliki metode lain yang menghindari penyalinan dengan menggunakanstd::equal
.Thomas uses atoi which is only for windows
Huh?atoi
telah menjadi fungsi perpustakaan standar C sejak ... sebelumnya. Pada kenyataannya,atoi
itu buruk - bukan karena itu khusus Windows - tetapi karena itu (1) C, bukan C ++, dan (2) ditinggalkan bahkan di C (Anda harus menggunakanstrtol
atau salah satu dari yang lain, fungsi terkait. Karenaatoi
memiliki tidak ada penanganan kesalahan. Tapi, sekali lagi, itu hanya di C, sih).Belum ada yang menggunakan fungsi algoritma / ketidakcocokan STL . Jika ini mengembalikan true, awalan adalah awalan dari 'toCheck':
Contoh lengkap prog:
Edit:
Seperti yang disarankan @James T. Huggett, std :: equal lebih cocok untuk pertanyaan: Apakah A awalan B? dan kode sedikit lebih pendek:
Contoh lengkap prog:
sumber
std::equal
untuk string memiliki kelemahan yang tidak mendeteksi akhir string, jadi Anda perlu memeriksa secara manual apakah awalan lebih pendek dari seluruh string. (Seperti yang dilakukan dengan benar dalam contoh prog, tetapi dihilangkan dalam satu-liner di atas.)Mengingat bahwa kedua string -
argv[1]
dan"--foo"
- adalah string C, jawaban @ FelixDombek adalah solusi terbaik.Namun, melihat jawaban lain, saya pikir perlu dicatat bahwa, jika teks Anda sudah tersedia sebagai
std::string
, maka ada solusi sederhana, tanpa salinan, dan efisien maksimal yang belum disebutkan sejauh ini:Dan jika foo sudah menjadi string:
sumber
rfind(x, 0) == 0
harus benar-benar didefinisikan dalam standar sebagaistarts_with
rfind()
(sebagai penggantistartswith()
) sangat tidak efisien - ia terus mencari hingga akhir string.Dengan C ++ 17 Anda dapat menggunakan
std::basic_string_view
& dengan C ++ 20std::basic_string::starts_with
ataustd::basic_string_view::starts_with
.Manfaat
std::string_view
dibandingkan denganstd::string
- mengenai manajemen memori - adalah bahwa ia hanya memegang pointer ke "string" (urutan berdekatan objek seperti char) dan tahu ukurannya. Contoh tanpa memindahkan / menyalin string sumber hanya untuk mendapatkan nilai integer:sumber
std::atoi
tidak apa-apa. Itu melempar pengecualian pada input buruk (yang ditangani dalam kode ini). Apakah Anda memikirkan hal lain?atoi
dari<cstdlib>
? The dokumentasi mengatakan "tidak pernah melempar pengecualian".atoi
alih - alihstd::atoi
. Yang pertama tidak aman untuk digunakan, sementara yang kedua baik-baik saja. Saya menggunakan yang terakhir dalam kode di sini.std::atoi
memang melempar pengecualian, dengan mengutip referensi yang sesuai. Sampai Anda melakukannya, saya tidak percaya Anda karena akan sangat membingungkan untuk memiliki keduanya::atoi
danstd::atoi
bertindak dengan cara yang sama sekali berbeda.std::atoi
digunakan alih-alihstd::stoi
. Saya sudah memperbaikinya.sumber
if (one-liner)
Menggunakan STL ini bisa terlihat seperti:
sumber
if (prefix.size()<=arg.size() && std::equal(...))
.Dengan risiko dinyalakan karena menggunakan konstruksi C, saya pikir
sscanf
contoh ini lebih elegan daripada kebanyakan solusi Peningkatan. Dan Anda tidak perlu khawatir tentang hubungan jika Anda menjalankan di mana saja yang memiliki juru bahasa Python!Berikut adalah beberapa contoh output yang menunjukkan solusi menangani terkemuka / trailing sampah dengan benar sebagai kode Python yang setara, dan lebih tepat daripada apa pun yang menggunakan
atoi
(yang keliru mengabaikan akhiran non-numerik).sumber
argv[i]
adalah"--foo=9999999999999999999999999"
, perilaku tidak terdefinisi (meskipun sebagian besar atau semua implementasi harus bersikap secara masuk akal). Saya berasumsi9999999999999999999999999 > INT_MAX
.Saya menggunakan
std::string::compare
metode utilitas terbungkus seperti di bawah ini:sumber
Mengapa tidak menggunakan getah gnu? Inilah contoh dasar (tanpa pemeriksaan keamanan):
Untuk perintah berikut:
Kamu akan mendapatkan
sumber
Jika Anda membutuhkan kompatibilitas C ++ 11 dan tidak dapat menggunakan boost, berikut adalah drop-in yang kompatibel dengan boost dengan contoh penggunaan:
sumber
Anda juga dapat menggunakan
strstr
:tapi saya pikir itu bagus hanya untuk string pendek karena harus mengulang seluruh string ketika string tidak benar-benar dimulai dengan 'substr'.
sumber
Ok mengapa rumit menggunakan perpustakaan dan barang-barang? C ++ String objek membebani operator [], jadi Anda bisa membandingkan karakter .. Seperti yang baru saja saya lakukan, karena saya ingin membuat daftar semua file dalam direktori dan mengabaikan file yang tidak terlihat dan .. dan. pseudofil.
Sesederhana itu ..
sumber
sumber
Dengan C ++ 11 atau lebih tinggi, Anda dapat menggunakan
find()
danfind_first_of()
Contoh menggunakan find untuk menemukan char tunggal:
Contoh menggunakan find untuk menemukan string penuh & mulai dari posisi 5:
Contoh menggunakan
find_first_of()
dan hanya karakter pertama, untuk mencari di awal saja:Semoga berhasil!
sumber
Karena C ++ 11
std::regex_search
juga dapat digunakan untuk memberikan pencocokan ekspresi yang lebih kompleks. Contoh berikut ini menangani juga angka mengambang thorughstd::stof
dan pemain berikutnyaint
.Namun
parseInt
metode yang ditunjukkan di bawah ini bisa melemparstd::invalid_argument
pengecualian jika awalan tidak cocok; ini dapat dengan mudah disesuaikan tergantung pada aplikasi yang diberikan:Jenis sulap dari pola regex terinci dengan baik dalam jawaban berikut .
EDIT: jawaban sebelumnya tidak melakukan konversi ke bilangan bulat.
sumber
Dimulai dengan C ++ 20, Anda dapat menggunakan
starts_with
metode ini.sumber
Ini sama sekali belum diuji. Prinsipnya sama dengan yang Python. Membutuhkan Boost.StringAlgo dan Boost.LexicalCast.
Periksa apakah string dimulai dengan string lain, lalu dapatkan substring ('slice') dari string pertama dan konversikan menggunakan lexical cast.
sumber