Saat ini saya menggunakan kode berikut untuk memotong kanan semua std::strings
program saya:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Ini berfungsi dengan baik, tapi saya ingin tahu apakah ada beberapa kasus akhir di mana ia mungkin gagal?
Tentu saja, jawaban dengan alternatif yang elegan dan juga solusi kiri diterima.
std::string
kelas, ketika fungsi seperti ini yang membuat bahasa lain begitu bagus untuk digunakan (misalnya Python).Jawaban:
EDIT Sejak c ++ 17, beberapa bagian dari perpustakaan standar telah dihapus. Untungnya, dimulai dengan c ++ 11, kami memiliki lambdas yang merupakan solusi terbaik.
Terima kasih kepada https://stackoverflow.com/a/44973498/524503 untuk membuka solusi modern.
Jawaban asli:
Saya cenderung menggunakan salah satu dari 3 ini untuk kebutuhan pemangkasan saya:
Mereka cukup jelas dan bekerja dengan sangat baik.
EDIT : BTW, saya ada
std::ptr_fun
di sana untuk membantu disambiguasistd::isspace
karena sebenarnya ada definisi kedua yang mendukung lokal. Ini bisa saja menjadi pemeran yang sama, tapi saya cenderung lebih suka ini.EDIT : Untuk membahas beberapa komentar tentang menerima parameter dengan referensi, memodifikasi dan mengembalikannya. Saya setuju. Sebuah implementasi yang saya lebih suka akan menjadi dua set fungsi, satu untuk di tempat dan satu yang membuat salinan. Satu set contoh yang lebih baik adalah:
Saya menyimpan jawaban asli di atas untuk konteks dan untuk menjaga agar jawaban yang dipilih tetap tersedia.
sumber
boost::trim
untuk memecahkan masalah.Menggunakan algoritma string Boost akan lebih mudah:
str
sekarang"hello world!"
. Ada jugatrim_left
dantrim
, yang memangkas kedua belah pihak.Jika Anda menambahkan
_copy
akhiran ke salah satu nama fungsi di atastrim_copy
, mis . Fungsi tersebut akan mengembalikan salinan string yang terpotong alih-alih memodifikasinya melalui referensi.Jika Anda menambahkan
_if
akhiran ke salah satu nama fungsi di atastrim_copy_if
, misalnya , Anda dapat memangkas semua karakter yang memenuhi predikat khusus Anda, bukan hanya spasi putih saja.sumber
Gunakan kode berikut untuk memangkas spasi (trailing) dan karakter tab dari
std::strings
( ideone ):Dan hanya untuk menyeimbangkan semuanya, saya akan memasukkan kode trim kiri juga ( ideone ):
sumber
str.substr(...).swap(str)
lebih baik. Simpan tugas.basic_string& operator= (basic_string&& str) noexcept;
?Apa yang Anda lakukan baik dan kuat. Saya telah menggunakan metode yang sama untuk waktu yang lama dan saya belum menemukan metode yang lebih cepat:
Dengan memasok karakter yang akan dipangkas Anda memiliki fleksibilitas untuk memangkas karakter yang bukan spasi dan efisiensi untuk memangkas hanya karakter yang ingin Anda pangkas.
sumber
trim
, yaitu membuatnyartrim(ltrim(s, t), t)
akan sedikit lebih efisienAgak terlambat ke pesta, tapi tidak apa-apa. Sekarang C ++ 11 ada di sini, kami memiliki lambdas dan variabel otomatis. Jadi versi saya, yang juga menangani semua spasi putih dan string kosong, adalah:
Kita dapat membuat iterator terbalik dari
wsfront
dan menggunakannya sebagai kondisi penghentian di detikfind_if_not
tetapi itu hanya berguna dalam kasus string semua-spasi, dan gcc 4,8 setidaknya tidak cukup pintar untuk menyimpulkan jenis iterator terbalik (std::string::const_reverse_iterator
) denganauto
. Saya tidak tahu seberapa mahal membangun iterator terbalik, jadi YMMV di sini. Dengan perubahan ini, kode ini terlihat seperti ini:sumber
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
Coba ini, ini bekerja untuk saya.
sumber
str.find_last_not_of(x)
mengembalikan posisi karakter pertama tidak sama dengan x. Ini hanya mengembalikan npos jika tidak ada karakter yang tidak cocok dengan x. Dalam contoh, jika tidak ada ruang suffixing, itu akan mengembalikan setara denganstr.length() - 1
, menghasilkan dasarnyastr.erase((str.length() - 1) + 1).
Yaitu, kecuali saya sangat keliru.std::string&
.Saya suka solusi tzaman, satu-satunya masalah dengan itu adalah tidak memangkas string yang hanya berisi spasi.
Untuk memperbaiki 1 cacat itu, tambahkan str.clear () di antara 2 garis pemangkas
sumber
ltrim
ataurtrim
seperti ini.std::stringstream
.http://ideone.com/nFVtEo
sumber
it
) dan membalikkan: posisi karakter setelah hanya ada spasi (rit
) - setelah itu mengembalikan string yang baru dibuat == salinan bagian dari string asli - bagian berdasarkan iterator itu ...Dalam kasus string kosong, kode Anda mengasumsikan bahwa menambahkan 1 untuk
string::npos
memberikan 0.string::npos
adalah tipestring::size_type
, yang tidak ditandatangani. Dengan demikian, Anda mengandalkan perilaku penambahan yang melimpah.sumber
1
kestd::string::npos
harus memberi0
sesuai denganC++ Standard
. Jadi itu asumsi yang bagus yang bisa diandalkan.Diretas dari Cplusplus.com
Ini berfungsi untuk kasus nol juga. :-)
sumber
rtrim
, tidakltrim
Dengan C ++ 17 Anda dapat menggunakan basic_string_view :: remove_prefix dan basic_string_view :: remove_suffix :
Alternatif yang bagus:
sumber
Solusi saya berdasarkan jawaban oleh @Bill the Lizard .
Perhatikan bahwa fungsi-fungsi ini akan mengembalikan string kosong jika string input hanya berisi spasi kosong.
sumber
Jawaban saya adalah peningkatan pada jawaban teratas untuk posting ini yang memangkas karakter kontrol serta spasi (0-32 dan 127 pada tabel ASCII ).
std::isgraph
menentukan apakah karakter memiliki representasi grafis, sehingga Anda dapat menggunakan ini untuk mengubah jawaban Evan untuk menghapus karakter yang tidak memiliki representasi grafis dari kedua sisi string. Hasilnya adalah solusi yang jauh lebih elegan:Catatan: Atau Anda dapat menggunakan
std::iswgraph
jika Anda membutuhkan dukungan untuk karakter lebar, tetapi Anda juga harus mengedit kode ini untuk mengaktifkanstd::wstring
manipulasi, yang merupakan sesuatu yang belum saya uji (lihat halaman referensi untukstd::basic_string
menjelajahi opsi ini) .sumber
Dengan C ++ 11 juga muncul modul ekspresi reguler , yang tentu saja dapat digunakan untuk memangkas ruang depan atau belakang.
Mungkin kira-kira seperti ini:
sumber
Inilah yang saya gunakan. Terus keluarkan ruang dari depan, dan kemudian, jika ada yang tersisa, lakukan hal yang sama dari belakang.
sumber
sumber
Untuk apa nilainya, berikut ini adalah implementasi yang ramping dengan pandangan terhadap kinerja. Ini jauh lebih cepat daripada banyak rutinitas trim lainnya yang pernah saya lihat. Alih-alih menggunakan iterator dan std :: ditemukan, ia menggunakan string dan indeks c mentah. Ini mengoptimalkan kasus khusus berikut: ukuran 0 string (tidak melakukan apa-apa), string tanpa spasi untuk memangkas (tidak melakukan apa-apa), string dengan hanya trailing spasi untuk memotong (hanya mengubah ukuran string), string yang sepenuhnya spasi putih (hanya menghapus string) . Dan akhirnya, dalam kasus terburuk (string dengan spasi kosong), ia melakukan yang terbaik untuk melakukan konstruksi salinan yang efisien, hanya melakukan 1 salinan dan kemudian memindahkan salinan itu di tempat string asli.
sumber
Cara yang elegan untuk melakukannya bisa seperti
Dan fungsi pendukung diimplementasikan sebagai:
Dan setelah Anda memiliki semua ini, Anda dapat menulis ini juga:
sumber
Implementasi Trim C ++ 11:
sumber
Saya kira jika Anda mulai meminta "cara terbaik" untuk memotong string, saya akan mengatakan implementasi yang baik adalah yang:
Jelas ada terlalu banyak cara berbeda untuk mendekati ini dan itu pasti tergantung pada apa yang sebenarnya Anda butuhkan. Namun, pustaka standar C masih memiliki beberapa fungsi yang sangat berguna di <string.h>, seperti memchr. Ada alasan mengapa C masih dianggap sebagai bahasa terbaik untuk IO - stdlibnya adalah efisiensi murni.
sumber
Saya tidak yakin apakah lingkungan Anda sama, tetapi di tambang, case string kosong akan menyebabkan program dibatalkan. Saya akan membungkus panggilan penghapusan dengan if (! S.empty ()) atau menggunakan Boost seperti yang telah disebutkan.
sumber
Inilah yang saya pikirkan:
Ekstraksi aliran menghilangkan spasi putih secara otomatis, jadi ini berfungsi seperti pesona.
Cukup bersih dan elegan juga, jika saya mengatakannya sendiri. ;)
sumber
Menyumbangkan solusi saya untuk kebisingan.
trim
default untuk membuat string baru dan mengembalikan yang dimodifikasi sambiltrim_in_place
memodifikasi string yang diteruskan ke sana. Thetrim
mendukung fungsi c ++ 11 langkah semantik.sumber
Ini dapat dilakukan lebih sederhana di C ++ 11 karena penambahan
back()
danpop_back()
.sumber
Ini versi saya:
sumber
Metode di atas bagus, tetapi kadang-kadang Anda ingin menggunakan kombinasi fungsi untuk apa yang rutin Anda anggap sebagai spasi kosong. Dalam hal ini, menggunakan functors untuk menggabungkan operasi bisa berantakan jadi saya lebih suka loop sederhana yang saya bisa modifikasi untuk trim. Berikut ini adalah fungsi trim sedikit dimodifikasi disalin dari versi C di sini di SO. Dalam contoh ini, saya memangkas karakter non alfanumerik.
sumber
Berikut ini adalah implementasi lurus ke depan. Untuk operasi sederhana seperti itu, Anda mungkin tidak boleh menggunakan konstruksi khusus apa pun. Fungsi built-in isspace () menangani berbagai bentuk karakter putih, jadi kita harus memanfaatkannya. Anda juga harus mempertimbangkan kasus khusus di mana string kosong atau hanya sekelompok spasi. Potong kiri atau kanan dapat diturunkan dari kode berikut.
sumber
Inilah solusi yang mudah dimengerti bagi pemula yang tidak terbiasa menulis di
std::
mana-mana dan belum terbiasa denganconst
-correctness,iterator
s, STLalgorithm
s, dll ...Semoga ini bisa membantu ...
sumber
Versi ini memangkas spasi putih internal dan non-alfanumerik:
sumber
Namun pilihan lain - menghapus satu atau lebih karakter dari kedua ujungnya.
sumber