Bagaimana cara iterate atas kata-kata dari string?
I'm mencoba untuk iterate atas kata-kata dari sebuah string.
String dapat diasumsikan terdiri dari kata-kata yang dipisahkan oleh spasi.
Perhatikan bahwa I'm tidak tertarik pada C fungsi-fungsi string atau karakter manipulasi/akses. Juga, silakan mendahulukan keanggunan atas efisiensi dalam jawaban anda.
Solusi terbaik yang saya miliki sekarang adalah:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string s = "Somewhere down the road";
istringstream iss(s);
do
{
string subs;
iss >> subs;
cout << "Substring: " << subs << endl;
} while (iss);
}
Apakah ada cara yang lebih elegan untuk melakukan hal ini?
2885
76
Saya menggunakan ini untuk split string dengan delimiter. Pertama menempatkan hasil di pra-dibangun vektor, pengembalian kedua vektor baru.
Perhatikan bahwa solusi ini tidak melewatkan kosong token, jadi berikut akan menemukan item 4, salah satu yang kosong:
Untuk apa itu's worth, di sini's cara lain untuk mengekstrak bukti dari sebuah string masukan, hanya mengandalkan standar fasilitas perpustakaan. It's contoh dari kekuatan dan keanggunan di balik desain STL.
Alih-alih menyalin diekstrak token ke output stream, yang bisa memasukkan mereka ke dalam sebuah wadah, menggunakan generik yang sama
copy
algoritma.... atau membuat
vektor
langsung:Solusi yang mungkin menggunakan Boost mungkin:
Pendekatan ini mungkin bahkan lebih cepat dari
stringstream
pendekatan. Dan karena ini adalah template generik fungsi ini dapat digunakan untuk membagi jenis lain dari string (wchar, dll. atau UTF-8) menggunakan semua jenis pembatas.Lihat dokumentasi untuk rincian.
Untuk orang-orang dengan siapa ia tidak duduk baik untuk mengorbankan semua efisiensi untuk kode ukuran dan lihat "efisien" sebagai jenis keanggunan, berikut ini harus memukul sweet spot (dan saya pikir template wadah kelas awesomely selain elegan.):
Saya biasanya memilih untuk menggunakan
std::vektor<std::string>
jenis sebagai parameter kedua (ContainerT
)... tapidaftar<>
adalah cara yang lebih cepat darivektor<>
ketika akses langsung tidak diperlukan, dan anda bahkan dapat membuat sendiri class string dan menggunakan sesuatu sepertistd::daftar<subString>
dimanasubString
tidak melakukan rangkap untuk kecepatan yang luar biasa meningkat.It's lebih dari dua kali lebih cepat seperti yang tercepat tokenize di halaman ini, dan hampir 5 kali lebih cepat dari beberapa orang lain. Juga dengan pilihan jenis parameter anda dapat menghilangkan semua string dan daftar salinan tambahan untuk meningkatkan kecepatan.
Selain itu tidak melakukan (sangat tidak efisien) kembali dari hasilnya, melainkan melewati token sebagai referensi, sehingga juga memungkinkan anda untuk membangun token menggunakan beberapa panggilan jika anda begitu ingin.
Akhirnya hal ini memungkinkan anda untuk menentukan apakah akan memangkas kosong token dari hasil melalui lalu parameter opsional.
Semua yang dibutuhkan adalah
std::string
... sisanya adalah opsional. Tidak menggunakan sungai atau dorongan perpustakaan, tetapi cukup fleksibel untuk dapat menerima beberapa asing jenis secara alami.Berikut ini's solusi lain. It's kompak dan cukup efisien:
Hal ini dapat dengan mudah menjadi templatised untuk menangani string pemisah, lebar string, dll.
Perhatikan bahwa membelah
","
hasil dalam satu string kosong dan membelah","
(ie. sep) hasil di dua string kosong.Hal ini juga dapat dengan mudah diperluas untuk melewatkan kosong token:
Jika membelah string di beberapa pembatas sambil melompat-lompat kosong token yang diinginkan, versi ini dapat digunakan:
Ini adalah cara favorit saya untuk iterate melalui sebuah string. Anda dapat melakukan apapun yang anda inginkan per kata.
Hal ini serupa dengan Stack Overflow pertanyaan [Bagaimana saya tokenize string di C++?][1].
Aku seperti berikut karena menempatkan hasil dalam vektor, mendukung string sebagai pembatas dan memberikan kontrol lebih menjaga nilai-nilai kosong. Tapi, itu doesn't terlihat baik kemudian.
Tentu saja, Meningkatkan memiliki
split()
yang bekerja sebagian seperti itu. Dan, jika dengan 'white-space', anda benar-benar tidak berarti semua jenis white-space, menggunakan Boost's split denganis_any_of()
karya besar.STL tidak memiliki metode tersebut sudah tersedia.
Namun, anda dapat menggunakan C's
strtok()
fungsi dengan menggunakanstd::string::c_str()
anggota, atau anda dapat menulis anda sendiri. Berikut ini adalah contoh kode yang saya temukan setelah pencarian Google cepat ("STL string split"):Diambil dari: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
Jika anda memiliki pertanyaan tentang kode sampel, meninggalkan komentar dan saya akan menjelaskan.
Dan hanya karena tidak menerapkan
typedef
disebut iterator atau membebani<<
operator tidak berarti itu adalah kode yang buruk. Saya menggunakan fungsi C cukup sering. Misalnya,printf
danscanf
kedua lebih cepat daristd::cin
danstd::cout
(signifikan), yangfopen
syntax ini jauh lebih ramah untuk biner jenis, dan mereka juga cenderung menghasilkan lebih kecil Ongkos.Don't mendapatkan yang dijual ini "Keanggunan atas kinerja" kesepakatan.
Berikut ini adalah membagi fungsi yang:
template vektor split(const T & str, const T & pembatas) { vektor v; typename T::size_type mulai = 0; auto pos = str.find_first_of(pembatas, mulai); sementara(pos != T::npo) { jika(pos != start) // abaikan kosong token v. emplace_back(str, mulai, pos - start); start = pos + 1; pos = str.find_first_of(pembatas, mulai); } jika(start < str.length()) // abaikan tertinggal pembatas v. emplace_back(str, mulai, str.length() - start); // menambahkan apa yang's kiri string kembali v; }
Contoh penggunaan:
Saya memiliki 2 jalur solusi untuk masalah ini:
Namun lain fleksibel dan cepat cara
Untuk menggunakannya dengan vektor string (Edit: Karena seseorang menunjukkan tidak mewarisi kelas STL... hrmf ;) ) :
Yang's itu! Dan yang's hanya salah satu cara untuk menggunakan tokenizer, seperti bagaimana hanya menghitung kata-kata:
Dibatasi oleh imajinasi ;)
Berikut ini's solusi sederhana yang hanya menggunakan standar regex perpustakaan
Regex argumen memungkinkan memeriksa beberapa argumen (spasi, koma, dll.)
Saya biasanya hanya memeriksa untuk split pada ruang dan koma, jadi saya juga memiliki fungsi default:
The
" [\\\\\s,]+"
cek untuk spasi (\\\\\s
) dan koma (,
).Catatan, jika anda ingin membagi
wstring
bukanstring
,std::regex
untukstd::wregex
sregex_token_iterator
untukwsregex_token_iterator
Catatan, anda mungkin juga ingin mengambil string argumen dengan referensi, tergantung pada compiler.
Menggunakan
std::stringstream
seperti yang anda telah bekerja baik-baik saja, dan lakukan apa yang anda ingin. Jika anda're hanya mencari cara yang berbeda dalam melakukan sesuatu meskipun, anda dapat menggunakan [std::cari()
][1]/[std::find_first_of()
][2] dan [std::string::substr()
][3].Berikut ini's contoh:
Jika anda ingin menggunakan boost, tapi ingin menggunakan seluruh string sebagai pembatas (bukan karakter tunggal seperti di sebagian besar dari sebelumnya mengusulkan solusi), anda dapat menggunakan
boost_split_iterator
.Contoh kode termasuk perangkat template:
Ada sebuah fungsi bernama
strtok
.Heres regex solusi yang hanya menggunakan standar regex perpustakaan. (Saya'm sedikit berkarat, jadi mungkin ada beberapa kesalahan sintaks, tapi ini setidaknya gambaran umum)
The stringstream dapat nyaman jika anda perlu untuk mengurai string dengan non-ruang simbol-simbol:
Sejauh ini saya menggunakan salah satu di [Meningkatkan][1], tapi aku butuh sesuatu yang doesn't tergantung pada hal itu, jadi aku datang untuk ini: