Sözləri necə bağlaya bilərəm?

Mən simli sözləri ilə düzəltməyə çalışıram.

Sözsüz ki, simli boşluqlarla ayrılmış sözlərdən ibarətdir.

C string funksiyaları və ya oxşar manipulyasiya / simvollara giriş məni maraqlandırmıram. Əlavə olaraq, xahiş etdiyiniz cavabı verən məhsuldarlığa üstünlük verin.

İndi mən ən yaxşı həll:

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

Bunu etmək üçün daha zərif bir yol varmı?

2749
25 окт. Ashwin Nanjappa tərəfindən təyin olunan Oct 25 2008-10-25 11:58 '08 at 11:58 2008-10-25 11:58
@ 76 cavab
  • 1
  • 2
  • 3

Nə başa düşüldüyünə görə, yalnız standart kitabxanalara istinad edərək giriş simvolundan ayıran bir başqa üsuldur. Bu STL dizaynının güc və zərifliyinə nümunədir.

 #include <iostream> #include <string> #include <sstream> #include <algorithm> #include <iterator> int main() { using namespace std; string sentence = "And I feel fine..."; istringstream iss(sentence); copy(istream_iterator<string>(iss), istream_iterator<string>(), ostream_iterator<string>(cout, "\n")); } 

Alınan tokensləri çıxış axınına kopyalamaq yerinə, eyni ümumi copy alqoritmini istifadə edərək, bir konteynerə yerləşdirə bilərsiniz.

 vector<string> tokens; copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens)); 

... və ya birbaşa bir vector yaradın:

 vector<string> tokens{istream_iterator<string>{iss}, istream_iterator<string>{}}; 
1241
26 окт. Zunino tərəfindən 26 oktyabrda cavab verildi 2008-10-26 03:43 '08 at 3:43 2008-10-26 03:43

Bunu bir məhdudlaşdırıcı ilə simli ayırmaq üçün istifadə edirəm. Birincisi, nəticələr əvvəlcədən hazırlanmış vektorda, ikincisi isə yeni bir vektor verir.

 std::vector<std::string> x = split("one:two::three", ':'); 
2343
25 окт. cavab oktyabrın 25-də Evan Teran tərəfindən verilir . 2008-10-25 21:21 '08 saat 09:21 'da 2008-10-25 21:21

Boost istifadə edərək mümkün bir həll ola bilər:

 #include <boost/algorithm/string.hpp> std::vector<std::string> strs; boost::split(strs, "string to split", boost::is_any_of("\t ")); 

Bu yanaşma stringstream yanaşma anlayışından daha sürətli ola bilər. Və bu universal şablon funksiyası olduğundan, hər cür məhdudiyyətlərdən istifadə edərək, digər strings (wchar, və s. Və ya UTF-8) növlərini ayırmaq üçün istifadə edilə bilər.

Ətraflı məlumat üçün baxın.

810
25 окт. Cavab 25 aya qədər verilir . 2008-10-25 23:28 '08 at 11:28 2008-10-25 23:28
 #include <vector> #include <string> #include <sstream> int main() { std::string str("Split me by whitespaces"); std::string buf; // Have a buffer string std::stringstream ss(str); // Insert the string into a stream std::vector<std::string> tokens; // Create vector to hold our words while (ss >> buf) tokens.push_back(buf); return 0; } 
336
06 марта '11 в 8:52 2011-03-06 08:52 Cavab verilib kev mart 06 '11 da 8:52 2011-03-06 08:52

Kod ölçüsü üçün bütün səmərəliliyi qurban vermək və zəriflik növü olaraq "effektiv" olduğunu görənlər üçün şirin bir nöqtəyə vurmaq lazımdır (və konteyner şablonu sinifinin şaşırtıcı bir şəkildə şəffaf bir əlavə olduğunu düşünürəm):

 template < class ContainerT > void tokenize(const std::string str, ContainerT tokens, const std::string delimiters = " ", bool trimEmpty = false) { std::string::size_type pos, lastPos = 0, length = str.length(); using value_type = typename ContainerT::value_type; using size_type = typename ContainerT::size_type; while(lastPos < length + 1) { pos = str.find_first_of(delimiters, lastPos); if(pos == std::string::npos) { pos = length; } if(pos != lastPos || !trimEmpty) tokens.push_back(value_type(str.data()+lastPos, (size_type)pos-lastPos )); lastPos = pos + 1; } } 

Mən std::vector<std::string> tiplərini ikinci parametrim ( ContainerT ) kimi istifadə etmirəm ... lakin birbaşa çıxış lazım deyilsə, list<> vector<> daha sürətlidır və hətta öz dizgini yarada bilərsiniz sinif və std::list<subString> kimi bir şey istifadə edir, burada subString inanılmaz sürət üçün subString .

Bu səhifədə ən sürətli tokenized kimi iki dəfə daha sürətli və bəzi digərləri demək olar ki, 5 dəfə daha sürətli. Ayrıca, ideal parametr tipləri ilə, əlavə sürət artımı üçün simli və siyahıların bütün nüsxələrini aradan qaldıra bilərsiniz.

Bundan əlavə, nəticənin (yüksək səmərəsiz) qayıdışını yerinə yetirmir, əksinə bir nişan kimi istinad edir, bu isə istənilən bir neçə zəngdən istifadə edərək simvol yaratmağa imkan verir.

Son olaraq, son isteğe bağlı parametrdən istifadə edərək, nəticələrdən boş tokenlərin boşaldılmasını təyin etməyə imkan verir.

Bütün ehtiyacları std::string ... qalanları isteğe bağlıdır. Bu mövzuları və ya təkan kitabxanasını istifadə etmir, lakin bu xarici növlərin təbii şəkildə qəbul edilməsi üçün kifayət qədər çevikdir.

174
29 сент. Cavab Marius tərəfindən 29 sentyabrda verilir. 2009-09-29 18:12 '09 da 18:12 'də 2009-09-29 18:12

Burada başqa bir həll var. Bu, kifayət qədər yığcam və effektivdir:

 std::vector<std::string> split(const std::string  char sep) { std::vector<std::string> tokens; std::size_t start = 0, end = 0; while ((end = text.find(sep, start)) != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = end + 1; } tokens.push_back(text.substr(start)); return tokens; } 

Kolaylıqla sıra məhdudlaşdırıcıları, geniş strings və s idarə etmək üçün planlaşdırılır bilər.

Boş xətt "" parçalanma "" nəticələrinə bölünür "," (yəni, "sep") iki boş xətaya gətirib çıxarır.

Həm də asanlıqla boş tokens keçmək üçün yerləşdirilə bilər:

 std::vector<std::string> split(const std::string  char sep) { std::vector<std::string> tokens; std::size_t start = 0, end = 0; while ((end = text.find(sep, start)) != std::string::npos) { if (end != start) { tokens.push_back(text.substr(start, end - start)); } start = end + 1; } if (end != start) { tokens.push_back(text.substr(start)); } return tokens; } 

Boş məntəqələri atlayarkən bir neçə məhdudlaşdırıcıya bir xətt ayırmaq lazımdırsa, bu versiya istifadə edilə bilər:

 std::vector<std::string> split(const std::string text, const std::string delims) { std::vector<std::string> tokens; std::size_t start = text.find_first_not_of(delims), end = 0; while((end = text.find_first_of(delims, start)) != std::string::npos) { tokens.push_back(text.substr(start, end - start)); start = text.find_first_not_of(delims, end); } if(start != std::string::npos) tokens.push_back(text.substr(start)); return tokens; } 
155
13 сент. Alec Tomas tərəfindən 13 sentyabr cəzası verildi 2011-09-13 23:46 '11 at 11:46 PM 2011-09-13 23:46

Bu simli təkrarlamaq üçün mənim ən sevimli yolumdur. Hər söz üçün istədiyiniz hər şeyi edə bilərsiniz.

 string line = "a line of text to iterate through"; string word; istringstream iss(line, istringstream::in); while( iss >> word ) { // Do something on `word` here... } 
111
25 окт. Cavab 25 oktyabrda gnomed tərəfindən verilir . 2008-10-25 12:16 '08 at 12:16 2008-10-25 12:16

Bir yığın taşması sualına bənzəyir. C ++ simli bir simgeyi necə təyin etmək olar? .

 #include <iostream> #include <string> #include <boost/tokenizer.hpp> using namespace std; using namespace boost; int main(int argc, char** argv) { string text = "token test\tstring"; char_separator<char> sep(" \t"); tokenizer<char_separator<char>> tokens(text, sep); for (const string t : tokens) { cout << t << "." << endl; } } 
78
25 окт. Ferruccio 25 oct cavab verilir . 2008-10-25 13:58 '08 at 13:58 pm 2008-10-25 13:58

Aşağıdakıları xoşlayıram, çünki nəticələri bir vektorda qoyur, simli bir ayırıcı kimi dəstəkləyir və null dəyərlərin qorunmasına nəzarət verir. Amma yaxşı görünmür.

 #include <ostream> #include <string> #include <vector> #include <algorithm> #include <iterator> using namespace std; vector<string> split(const string s, const string delim, const bool keep_empty = true) { vector<string> result; if (delim.empty()) { result.push_back(s); return result; } string::const_iterator substart = s.begin(), subend; while (true) { subend = search(substart, s.end(), delim.begin(), delim.end()); string temp(substart, subend); if (keep_empty || !temp.empty()) { result.push_back(temp); } if (subend == s.end()) { break; } substart = subend + delim.size(); } return result; } int main() { const vector<string> words = split("So close no matter how far", " "); copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n")); } 

Əlbəttə, Boost split() , qismən bu kimi işləyir. Və, əgər ağ məkanla həqiqətən hər hansı bir ağ məkanı deməkdirsə, is_any_of() ilə Boost bölməsindən istifadə edərək gözəl işləyir.

65
25 окт. Cavab Shadow2531 25 oct verilir . 2008-10-25 13:01 '08 at 13:01 pm 2008-10-25 13:01

STL artıq belə bir üsula sahib deyil.

Lakin std::string::c_str() istifadə edərək, C strtok() istifadə edə bilərsiniz və ya öz std::string::c_str() yaza bilərsiniz. Tez bir Google axtarışından sonra tapdığım kodun bir nümunəsi ( "STL dizesinin parçalanması" ):

 void Tokenize(const string str, vector<string> tokens, const string delimiters = " ") { // Skip delimiters at beginning. string::size_type lastPos = str.find_first_not_of(delimiters, 0); // Find first "non-delimiter". string::size_type pos = str.find_first_of(delimiters, lastPos); while (string::npos != pos || string::npos != lastPos) { // Found a token, add it to the vector. tokens.push_back(str.substr(lastPos, pos - lastPos)); // Skip delimiters. Note the "not_of" lastPos = str.find_first_not_of(delimiters, pos); // Find next "non-delimiter" pos = str.find_first_of(delimiters, lastPos); } } 

Alınan: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

Əgər nümunə kodu haqqında suallarınız varsa, şərh verin və mən izah edəcəyəm.

Və yalnız bir iterator və ya yükləməyən bir typedef tətbiq etmir, çünki << operator bu pis kod deyil. C funksiyalarını tez-tez istifadə edirəm. Məsələn, printfscanf std::cinstd::cout (xeyli) olduğundan daha sürətlidır, fopen sözdizimi ikili növlər üçün çox daha münasibdir və onlar da daha kiçik EXE yaratmaq məcburiyyətindədirlər.

Bu "Elegance over performance" müqaviləsini satmayın.

50
25 окт. cavab nlaq 25 oct verilir . 2008-10-25 12:08 '08 at 12:08 2008-10-25 12:08

İşdə ayırma funksiyası:

  • ümumi
  • standart C ++ istifadə edir (heç bir genişlənmə)
  • bir çox məhdudiyyətçi qəbul edir
  • boş tapıntıları məhdudlaşdırır (asanlıqla dəyişə bilər)

     template<typename T> vector<T> split(const T  str, const T  delimiters) { vector<T> v; typename T::size_type start = 0; auto pos = str.find_first_of(delimiters, start); while(pos != T::npos) { if(pos != start) // ignore empty tokens v.emplace_back(str, start, pos - start); start = pos + 1; pos = str.find_first_of(delimiters, start); } if(start < str.length()) // ignore trailing delimiter v.emplace_back(str, start, str.length() - start); // add what left of the string return v; } 

İstifadə nümunəsi:

  vector<string> v = split<string>("Hello, there; World", ";,"); vector<wstring> v = split<wstring>(L"Hello, there; World", L";,"); 
39
13 марта '12 в 3:09 2012-03-13 03:09 Cavab Marco M. tərəfindən verilir 13 Mart '12, 3:09 2012-03-13 03:09

Digər çevik və sürətli yol

 template<typename Operator> void tokenize(Operator op, const char* input, const char* delimiters) { const char* s = input; const char* e = s; while (*e != 0) { e = s; while (*e != 0  strchr(delimiters, *e) == 0) ++e; if (e - s > 0) { op(s, e - s); } s = e + 1; } } 

Bir simli vektorla istifadə edin (Düzenle: Birinin STL dərslərini devralmadığını göstərdiyi üçün ... hrmf;)):

 template<class ContainerType> class Appender { public: Appender(ContainerType container) : container_(container) {;} void operator() (const char* s, unsigned length) { container_.push_back(std::string(s,length)); } private: ContainerType container_; }; std::vector<std::string> strVector; Appender v(strVector); tokenize(v, "A number of words to be tokenized", " \t"); 

Bu nədir? Və bu bir tokenizer istifadə etmək üçün yalnız bir yoldur, məsələn, sadəcə sözləri necə saymaq olar:

 class WordCounter { public: WordCounter() : noOfWords(0) {} void operator() (const char*, unsigned) { ++noOfWords; } unsigned noOfWords; }; WordCounter wc; tokenize(wc, "A number of words to be counted", " \t"); ASSERT( wc.noOfWords == 7 ); 

Təsəvvürlə məhdud;)

34
01 апр. Cavab Robert tərəfindən verilir 2010-04-01 17:16 '10 'da 17:16' da 2010-04-01 17:16

Bu problemə 2 xəttli bir həll var:

 char sep = ' '; std::string s="1 This is an example"; for(size_t p=0, q=0; p!=s.npos; p=q) std::cout << s.substr(p+(p!=0), (q=s.find(sep, p+1))-p-(p!=0)) << std::endl; 

Sonra çap etmək yerinə, bir vektorda qoyun.

34
16 сент. Cavab 16 sentyabr rhomu tərəfindən verilir 2012-09-16 17:06 '12 at 17:06 2012-09-16 17:06

Yalnız standart müntəzəm ifadə kitabxanasını istifadə edən sadə bir həlldir.

 #include <regex> #include <string> #include <vector> std::vector<string> Tokenize( const string str, const std::regex regex ) { using namespace std; std::vector<string> result; sregex_token_iterator it( str.begin(), str.end(), regex, -1 ); sregex_token_iterator reg_end; for ( ; it != reg_end; ++it ) { if ( !it->str().empty() ) //token could be empty:check result.emplace_back( it->str() ); } return result; } 

Regex argumenti bir çox arqumentlərin yoxlanılmasına imkan verir (boşluq, virgül, və s.)

Adətən, bölünməni boşluqlara və vergüllərə yoxlayıram, buna görə də bu default funksiyası var:

 std::vector<string> TokenizeDefault( const string str ) { using namespace std; regex re( "[\\s,]+" ); return Tokenize( str, re ); } 

"[\\s,]+" boşluqları ( \\s ) və virgül ( , ) üçün yoxlayır.

wstring yerinə wstring bölmək istəyirsinizsə,

  • Bütün std::regex std::wregex
  • Bütün sregex_token_iterator olaraq wsregex_token_iterator

Derivorunuza bağlı olaraq referenduma istinad edərək dize arqumentini də ala bilərsiniz.

30
06 мая '14 в 8:49 2014-05-06 08:49 Cavab verilir dk123 May 06 '14 da 8:49 2014-05-06 08:49

boost_split_iterator istifadə etmək istəyirsinizsə, lakin bütün simli məhdudlaşdırıcı kimi istifadə etmək istəyirsənsə (əvvəllər təklif olunan həllərdəki kimi bir simvol əvəzinə) boost_split_iterator istifadə edə bilərsiniz.

Uyğun bir şablonu olan kodu nümunə:

 #include <iostream> #include <vector> #include <boost/algorithm/string.hpp> template<typename _OutputIterator> inline void split( const std::string str, const std::string delim, _OutputIterator result) { using namespace boost::algorithm; typedef split_iterator<std::string::const_iterator> It; for(It iter=make_split_iterator(str, first_finder(delim, is_equal())); iter!=It(); ++iter) { *(result++) = boost::copy_range<std::string>(*iter); } } int main(int argc, char* argv[]) { using namespace std; vector<string> splitted; split("HelloFOOworldFOO!", "FOO", back_inserter(splitted)); // or directly to console, for example split("HelloFOOworldFOO!", "FOO", ostream_iterator<string>(cout, "\n")); return 0; } 
24
24 марта '11 в 15:47 2011-03-24 15:47 cavab 24 mart 2011- ci il saat 15 : 00-da zerm tərəfindən verilmişdir 2011-03-24 15:47

std::stringstream istifadə yaxşı iş və tam istədiyiniz nə. Yalnız bir şey etmək üçün başqa bir yol axtarırsınızsa, std::find() / std::find_first_of()std::string::substr() istifadə edə bilərsiniz.

Burada bir nümunə:

 #include <iostream> #include <string> int main() { std::string s("Somewhere down the road"); std::string::size_type prev_pos = 0, pos = 0; while( (pos = s.find(' ', pos)) != std::string::npos ) { std::string substring( s.substr(prev_pos, pos-prev_pos) ); std::cout << substring << '\n'; prev_pos = ++pos; } std::string substring( s.substr(prev_pos, pos-prev_pos) ); // Last word std::cout << substring << '\n'; return 0; } 
23
25 окт. 25 Oktyabrda KTC tərəfindən verilən cavab 2008-10-25 12:28 '08 at 12:28 2008-10-25 12:28

strtok adlı bir funksiya var.

 #include<string> using namespace std; vector<string> split(char* str,const char* delim) { char* saveptr; char* token = strtok_r(str,delim, vector<string> result; while(token != NULL) { result.push_back(token); token = strtok_r(NULL,delim, } return result; } 
18
14 июня '10 в 15:17 2010-06-14 15:17 Cavab Pratik Deoghare tərəfindən 14 iyun '10 'da 15:17' də verildi 2010-06-14 15:17

Burada yalnız standart müntəzəm ifadə kitabxanasını istifadə edən müntəzəm ifadə həllidir. (Bir az paslıyam, bir neçə sintaksis səhv ola bilər, amma bu ən azı ümumi bir fikirdir)

 #include <regex.h> #include <string.h> #include <vector.h> using namespace std; vector<string> split(string s){ regex r ("\\w+"); //regex matches whole words, (greedy, so no fragment words) regex_iterator<string::iterator> rit ( s.begin(), s.end(), r ); regex_iterator<string::iterator> rend; //iterators to iterate thru words vector<string> result<regex_iterator>(rit, rend); return result; //iterates through the matches to fill the vector } 
17
29 окт. Cavab 29 oktyabrda AJMansfield tərəfindən verilir 2012-10-29 19:15 '12 saat 19:15 'da 2012-10-29 19:15

Bir dize stream qeyri-məkan olmayan simvolları istifadə edərək, bir simvol analiz etmək lazımdırsa rahat ola bilər:

 string s = "Name:JAck; Spouse:Susan; ..."; string dummy, name, spouse; istringstream iss(s); getline(iss, dummy, ':'); getline(iss, name, ';'); getline(iss, dummy, ':'); getline(iss, spouse, ';') 
16
12 авг. lukmac tərəfindən verilmiş cavab 12 av . 2011-08-12 22:05 '11 saat 10:05 'da 2011-08-12 22:05

İndiyə qədər Boostda olan birini istifadə etdim, amma ona bağlı olmayan bir şeyə ehtiyacım vardı, buna görə də gəldim

 static void Split(std::vector<std::string> lst, const std::string input, const std::string separators, bool remove_empty = true) { std::ostringstream word; for (size_t n = 0; n < input.size(); ++n) { if (std::string::npos == separators.find(input[n])) word << input[n]; else { if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); word.str(""); } } if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); } 

separators birdən çox xarakter keçə separators yaxşıdır.

14
14 янв. cavab Goran 14 yanvar verilir . 2011-01-14 12:22 '11 at 12:22 2011-01-14 12:22

Qısa və zərif

 #include <vector> #include <string> using namespace std; vector<string> split(string data, string token) { vector<string> output; size_t pos = string::npos; // size_t to avoid improbable overflow do { pos = data.find(token); output.push_back(data.substr(0, pos)); if (string::npos != pos) data = data.substr(pos + token.size()); } while (string::npos != pos); return output; } 

hər hansı bir simli bir məhdudlaşdırıcı kimi istifadə edə bilər, ikili məlumatlarla da istifadə edilə bilər (std :: string, sıfırlar daxil olmaqla ikili məlumatları dəstəkləyir)

istifadə edərək:

 auto a = split("this!!is!!!example!string", "!!"); 

çıxış:

 this is !example!string 
14
02 нояб. Cavab istifadəçi1438233 02 Noyabr. 2015-11-02 17:39 '15 'də saat 17:39' də 2015-11-02 17:39

Mən strtok istifadə edərək özüm yayılmış və strings ayırmaq üçün təkan istifadə. Mən tapdığım ən yaxşı üsul C ++ String Toolkit Kitabxanasıdır . Bu olduqca çevik və sürətli.

 #include <iostream> #include <vector> #include <string> #include <strtk.hpp> const char *whitespace = " \t\r\n\f"; const char *whitespace_and_punctuation = " \t\r\n\f;,="; int main() { { // normal parsing of a string into a vector of strings std::string s("Somewhere down the road"); std::vector<std::string> result; if( strtk::parse( s, whitespace, result ) ) { for(size_t i = 0; i < result.size(); ++i ) std::cout << result[i] << std::endl; } } { // parsing a string into a vector of floats with other separators // besides spaces std::string s("3.0, 3.14; 4.0"); std::vector<float> values; if( strtk::parse( s, whitespace_and_punctuation, values ) ) { for(size_t i = 0; i < values.size(); ++i ) std::cout << values[i] << std::endl; } } { // parsing a string into specific variables std::string s("angle = 45; radius = 9.9"); std::string w1, w2; float v1, v2; if( strtk::parse( s, whitespace_and_punctuation, w1, v1, w2, v2) ) { std::cout << "word " << w1 << ", value " << v1 << std::endl; std::cout << "word " << w2 << ", value " << v2 << std::endl; } } return 0; } 

Toolkit bu sadə nümunədən daha çox rahatlıq göstərir, ancaq faydalı elementlərə bir simli ayrıştırmada faydalıdır.

13
07 янв. cavab DannyK 07 jan verildi . 2014-01-07 23:28 '14 at 23:28 2014-01-07 23:28

Bunu etmədim, çünki xəttlərdən xəttləri ayırmaq üçün sadə bir yola ehtiyacım vardı ... İnşallah başqasının faydalı olduğunu tapa bilərik. Ayrıca, bu notlara istinad etmir və sahələri məhdudlaşdırıcı kimi istifadə edə bilərsiniz, bu da mənə lazım olan başqa bir əsasdır.

Əminəm ki, zərifliyini daha da yaxşılaşdırmaq üçün yaxşılaşdırıla biləcək təkmilləşdirmələr var və hər cür yolla

StringSplitter.hpp:

 #include <vector> #include <iostream> #include <string.h> using namespace std; class StringSplit { private: void copy_fragment(char*, char*, char*); void copy_fragment(char*, char*, char); bool match_fragment(char*, char*, int); int untilnextdelim(char*, char); int untilnextdelim(char*, char*); void assimilate(char*, char); void assimilate(char*, char*); bool string_contains(char*, char*); long calc_string_size(char*); void copy_string(char*, char*); public: vector<char*> split_cstr(char); vector<char*> split_cstr(char*); vector<string> split_string(char); vector<string> split_string(char*); char* String; bool do_string; bool keep_empty; vector<char*> Container; vector<string> ContainerS; StringSplit(char * in) { String = in; } StringSplit(string in) { size_t len = calc_string_size((char*)in.c_str()); String = new char[len + 1]; memset(String, 0, len + 1); copy_string(String, (char*)in.c_str()); do_string = true; } ~StringSplit() { for (int i = 0; i < Container.size(); i++) { if (Container[i] != NULL) { delete[] Container[i]; } } if (do_string) { delete[] String; } } }; 

StringSplitter.cpp:

 #include <string.h> #include <iostream> #include <vector> #include "StringSplit.hpp" using namespace std; void StringSplit::assimilate(char*src, char delim) { int until = untilnextdelim(src, delim); if (until > 0) { char * temp = new char[until + 1]; memset(temp, 0, until + 1); copy_fragment(temp, src, delim); if (keep_empty || *temp != 0) { if (!do_string) { Container.push_back(temp); } else { string x = temp; ContainerS.push_back(x); } } else { delete[] temp; } } } void StringSplit::assimilate(char*src, char* delim) { int until = untilnextdelim(src, delim); if (until > 0) { char * temp = new char[until + 1]; memset(temp, 0, until + 1); copy_fragment(temp, src, delim); if (keep_empty || *temp != 0) { if (!do_string) { Container.push_back(temp); } else { string x = temp; ContainerS.push_back(x); } } else { delete[] temp; } } } long StringSplit::calc_string_size(char* _in) { long i = 0; while (*_in++) { i++; } return i; } bool StringSplit::string_contains(char* haystack, char* needle) { size_t len = calc_string_size(needle); size_t lenh = calc_string_size(haystack); while (lenh--) { if (match_fragment(haystack + lenh, needle, len)) { return true; } } return false; } bool StringSplit::match_fragment(char* _src, char* cmp, int len) { while (len--) { if (*(_src + len) != *(cmp + len)) { return false; } } return true; } int StringSplit::untilnextdelim(char* _in, char delim) { size_t len = calc_string_size(_in); if (*_in == delim) { _in += 1; return len - 1; } int c = 0; while (*(_in + c) != delim  c < len) { c++; } return c; } int StringSplit::untilnextdelim(char* _in, char* delim) { int s = calc_string_size(delim); int c = 1 + s; if (!string_contains(_in, delim)) { return calc_string_size(_in); } else if (match_fragment(_in, delim, s)) { _in += s; return calc_string_size(_in); } while (!match_fragment(_in + c, delim, s)) { c++; } return c; } void StringSplit::copy_fragment(char* dest, char* src, char delim) { if (*src == delim) { src++; } int c = 0; while (*(src + c) != delim  *(src + c)) { *(dest + c) = *(src + c); c++; } *(dest + c) = 0; } void StringSplit::copy_string(char* dest, char* src) { int i = 0; while (*(src + i)) { *(dest + i) = *(src + i); i++; } } void StringSplit::copy_fragment(char* dest, char* src, char* delim) { size_t len = calc_string_size(delim); size_t lens = calc_string_size(src); if (match_fragment(src, delim, len)) { src += len; lens -= len; } int c = 0; while (!match_fragment(src + c, delim, len)  (c < lens)) { *(dest + c) = *(src + c); c++; } *(dest + c) = 0; } vector<char*> StringSplit::split_cstr(char Delimiter) { int i = 0; while (*String) { if (*String != Delimiter  i == 0) { assimilate(String, Delimiter); } if (*String == Delimiter) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return Container; } vector<string> StringSplit::split_string(char Delimiter) { do_string = true; int i = 0; while (*String) { if (*String != Delimiter  i == 0) { assimilate(String, Delimiter); } if (*String == Delimiter) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return ContainerS; } vector<char*> StringSplit::split_cstr(char* Delimiter) { int i = 0; size_t LenDelim = calc_string_size(Delimiter); while(*String) { if (!match_fragment(String, Delimiter, LenDelim)  i == 0) { assimilate(String, Delimiter); } if (match_fragment(String, Delimiter, LenDelim)) { assimilate(String,Delimiter); } i++; String++; } String -= i; delete[] String; return Container; } vector<string> StringSplit::split_string(char* Delimiter) { do_string = true; int i = 0; size_t LenDelim = calc_string_size(Delimiter); while (*String) { if (!match_fragment(String, Delimiter, LenDelim)  i == 0) { assimilate(String, Delimiter); } if (match_fragment(String, Delimiter, LenDelim)) { assimilate(String, Delimiter); } i++; String++; } String -= i; delete[] String; return ContainerS; } 

Nümunələr:

 int main(int argc, char*argv[]) { StringSplit ss = "This:CUT:is:CUT:an:CUT:example:CUT:cstring"; vector<char*> Split = ss.split_cstr(":CUT:"); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } 

Göstəriləcək:

Odur
budur

bir nümunə
CString

 int main(int argc, char*argv[]) { StringSplit ss = "This:is:an:example:cstring"; vector<char*> Split = ss.split_cstr(':'); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } int main(int argc, char*argv[]) { string mystring = "This[SPLIT]is[SPLIT]an[SPLIT]example[SPLIT]string"; StringSplit ss = mystring; vector<string> Split = ss.split_string("[SPLIT]"); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } int main(int argc, char*argv[]) { string mystring = "This|is|an|example|string"; StringSplit ss = mystring; vector<string> Split = ss.split_string('|'); for (int i = 0; i < Split.size(); i++) { cout << Split[i] << endl; } return 0; } 

Boş girişləri saxlama (default olaraq boş qeydlər istisna olmaqla):

 StringSplit ss = mystring; ss.keep_empty = true; vector<string> Split = ss.split_string(":DELIM:"); 

Məqsəd, C # Split () metodu kimi görünmək idi, xətlərin bölünməsi isə sadədir:

 String[] Split = "Hey:cut:what's:cut:your:cut:name?".Split(new[]{":cut:"}, StringSplitOptions.None); foreach(String X in Split) { Console.Write(X); } 

İnşallah başqası mənim kimi faydalıdır.

11
31 авг. Cavab 31 Avqustda Steve Dell tərəfindən verilir . 2012-08-31 22:11 '12 at 10:11 pm 2012-08-31 22:11

Necə olar?

 #include <string> #include <vector> using namespace std; vector<string> split(string str, const char delim) { vector<string> v; string tmp; for(string::const_iterator i; i = str.begin(); i <= str.end(); ++i) { if(*i != delim  i != str.end()) { tmp += *i; } else { v.push_back(tmp); tmp = ""; } } return v; } 
10
ответ дан gibbz 24 июня '11 в 1:04 2011-06-24 01:04

Вот еще один способ сделать это.

 void split_string(string text,vector<string> words) { int i=0; char ch; string word; while(ch=text[i++]) { if (isspace(ch)) { if (!word.empty()) { words.push_back(word); } word = ""; } else { word += ch; } } if (!word.empty()) { words.push_back(word); } } 
9
ответ дан user246110 08 янв. '10 в 6:21 2010-01-08 06:21
 #include<iostream> #include<string> #include<sstream> #include<vector> using namespace std; vector<string> split(const string  char delim) { vector<string> elems; stringstream ss(s); string item; while (getline(ss, item, delim)) { elems.push_back(item); } return elems; } int main() { vector<string> x = split("thi is an sample test",' '); unsigned int i; for(i=0;i<x.size();i++) cout<<i<<":"<<x[i]<<endl; return 0; } 
9
ответ дан san45 03 окт. '13 в 11:41 2013-10-03 11:41

Этот ответ берет строку и помещает ее в вектор строк. Он использует библиотеку boost.

 #include <boost/algorithm/string.hpp> std::vector<std::string> strs; boost::split(strs, "string to split", boost::is_any_of("\t ")); 
9
ответ дан NL628 10 дек. '17 в 0:14 2017-12-10 00:14

Недавно мне пришлось разбить слово с верблюжьим словом на подслов. Нет разделителей, только верхние символы.

 #include <string> #include <list> #include <locale> // std::isupper template<class String> const std::list<String> split_camel_case_string(const String  { std::list<String> R; String w; for (String::const_iterator i = s.begin(); i < s.end(); ++i) { { if (std::isupper(*i)) { if (w.length()) { R.push_back(w); w.clear(); } } w += *i; } if (w.length()) R.push_back(w); return R; } 

Например, это разделяет "AQueryTrades" на "A", "Query" и "Trades". Функция работает с узкими и широкими строками. Поскольку он уважает нынешний язык, он разбивает "RaumfahrtÜberwachungsVerordnung" на "Raumfahrt", "Überwachungs" и "Verordnung".

Примечание std::upper должно быть действительно передано как аргумент шаблона функции. Тогда более обобщенная из этой функции может разбиваться на разделители типа "," , ";" или " " тоже.

9
ответ дан Andreas Spindler 14 сент. '11 в 12:42 2011-09-14 12:42

Мне нравится использовать методы boost/regex для этой задачи, поскольку они обеспечивают максимальную гибкость для задания критериев разделения.

 #include <iostream> #include <string> #include <boost/regex.hpp> int main() { std::string line("A:::line::to:split"); const boost::regex re(":+"); // one or more colons // -1 means find inverse matches aka split boost::sregex_token_iterator tokens(line.begin(),line.end(),re,-1); boost::sregex_token_iterator end; for (; tokens != end; ++tokens) std::cout << *tokens << std::endl; } 
9
ответ дан Marty B 12 июня '11 в 12:25 2011-06-12 12:25

В приведенном ниже коде используется strtok() , чтобы разбить строку на токены и сохранить токены в векторе.

 #include <iostream> #include <algorithm> #include <vector> #include <string> using namespace std; char one_line_string[] = "hello hi how are you nice weather we are having ok then bye"; char seps[] = " ,\t\n"; char *token; int main() { vector<string> vec_String_Lines; token = strtok( one_line_string, seps ); cout << "Extracting and storing data in a vector..\n\n\n"; while( token != NULL ) { vec_String_Lines.push_back(token); token = strtok( NULL, seps ); } cout << "Displaying end result in vector line storage..\n\n"; for ( int i = 0; i < vec_String_Lines.size(); ++i) cout << vec_String_Lines[i] << "\n"; cout << "\n\n\n"; return 0; } 
8
ответ дан Software_Designer 10 дек. '11 в 16:58 2011-12-10 16:58
  • 1
  • 2
  • 3

Другие вопросы по меткам или Задайте вопрос