2012-02-24 19 views
37

का उपयोग कर स्ट्रिंग को विभाजित करें C++ 11 का उपयोग करके स्ट्रिंग को विभाजित करने का सबसे आसान तरीका क्या होगा?सी ++ 11

मैंने इस post द्वारा उपयोग की गई विधि को देखा है, लेकिन मुझे लगता है कि नए मानक का उपयोग करके इसे करने का कम वर्बोज़ तरीका होना चाहिए।

संपादित करें: परिणामस्वरूप मैं vector<string> रखना चाहता हूं और एक ही चरित्र पर सीमित हो सकता हूं।

+1

विभाजन? और मुझे नहीं लगता कि सी ++ 11 ने कुछ भी जोड़ा है, सोचें [स्वीकृत उत्तर] (http://stackoverflow.com/a/237280/845092) अभी भी सबसे अच्छा तरीका है। –

+0

आप विभाजन के बाद क्या करना चाहते हैं? कोउट प्रिंट करें? या substrings का एक वेक्टर मिलता है? – balki

+0

क्या यह नियमित अभिव्यक्ति पार्सिंग के लिए नहीं है? –

उत्तर

4

मुझे नहीं पता कि यह कम वर्बोज़ है, लेकिन जावास्क्रिप्ट जैसे गतिशील भाषाओं में उन अधिक अनुभवी लोगों के लिए ग्रोक करना आसान हो सकता है। इसका उपयोग करने वाली एकमात्र सी ++ 11 सुविधा लैम्बडास है।

#include <algorithm> 
#include <string> 
#include <cctype> 
#include <iostream> 
#include <vector> 

int main() 
{ 
    using namespace std; 
    string s = "hello how are you won't you tell me your name"; 
    vector<string> tokens; 
    string token; 

    for_each(s.begin(), s.end(), [&](char c) { 
    if (!isspace(c)) 
     token += c; 
    else 
    { 
     if (token.length()) tokens.push_back(token); 
     token.clear(); 
    } 
    }); 
    if (token.length()) tokens.push_back(token); 

    return 0; 
} 
+14

क्यों है (ऑटो कॉन्स सी: एस) {...} '? –

51

std::regex_token_iterator एक regex के आधार पर सामान्य tokenization प्रदर्शन करती है। यह या overkill एक भी चरित्र पर सरल बंटवारे करने के लिए नहीं हो सकता है, लेकिन यह काम करता है और भी वर्बोज़ नहीं है:

std::vector<std::string> split(const string& input, const string& regex) { 
    // passing -1 as the submatch index parameter performs splitting 
    std::regex re(regex); 
    std::sregex_token_iterator 
     first{input.begin(), input.end(), re, -1}, 
     last; 
    return {first, last}; 
} 
+24

ग्रेट विचार, पढ़ने के लिए बहुत मुश्किल है। –

+2

का उल्लेख करना चाहिए कि यह एमएसएफटी-विशिष्ट है। POSIX सिस्टम पर मौजूद नहीं है। – jackyalcine

+0

ऐसा लगता है कि यह [बूस्ट।] में भी उपलब्ध है (http://www.boost.org/doc/libs/1_56_0/libs/regex/doc/html/boost_regex/ref/regex_token_iterator.html) – phs

4

मेरे चुनाव boost::tokenizer है, लेकिन मैं बहुत बड़ा डेटा के साथ किसी भी भारी कार्यों और परीक्षण नहीं था । बढ़ावा दस्तावेज़ से लैम्ब्डा संशोधन के साथ उदाहरण:

#include <iostream> 
#include <boost/tokenizer.hpp> 
#include <string> 
#include <vector> 

int main() 
{ 
    using namespace std; 
    using namespace boost; 

    string s = "This is, a test"; 
    vector<string> v; 
    tokenizer<> tok(s); 
    for_each (tok.begin(), tok.end(), [&v](const string & s) { v.push_back(s); }); 
    // result 4 items: 1)This 2)is 3)a 4)test 
    return 0; 
} 
+2

क्यों एक सीमा के लिए आधारित नहीं है? –

+5

सी ++ 11 में, 'के लिए (ऑटो और एस: टोक़) {v.push_back (ओं); } '। –

3
#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <string> 


using namespace std; 

vector<string> split(const string& str, int delimiter(int) = ::isspace){ 
    vector<string> result; 
    auto e=str.end(); 
    auto i=str.begin(); 
    while(i!=e){ 
    i=find_if_not(i,e, delimiter); 
    if(i==e) break; 
    auto j=find_if(i,e, delimiter); 
    result.push_back(string(i,j)); 
    i=j; 
    } 
    return result; 
} 

int main(){ 
    string line; 
    getline(cin,line); 
    vector<string> result = split(line); 
    for(auto s: result){ 
    cout<<s<<endl; 
    } 
} 
+0

क्यों 'int' delimiter के रूप में, और क्यों' int delimiter (int) '' (int) '? – Ela782

+1

@ Ela782 यह एक फ़ंक्शन पॉइंटर तर्क है, एक फ़ंक्शन जो एक int पैरामीटर स्वीकार करता है और int देता है। डिफॉल्ट इन्सपेस फ़ंक्शन है। – Fsmv

13

यहाँ एक (शायद कम शब्द) रास्ता स्ट्रिंग (post आप का उल्लेख के आधार पर) विभाजित करने के लिए है।

#include <string> 
#include <sstream> 
#include <vector> 
std::vector<std::string> split(const std::string &s, char delim) { 
    std::stringstream ss(s); 
    std::string item; 
    std::vector<std::string> elems; 
    while (std::getline(ss, item, delim)) { 
    elems.push_back(item); 
    // elems.push_back(std::move(item)); // if C++11 (based on comment from @mchiasson) 
    } 
    return elems; 
} 
+4

यदि आप सी ++ 11 का उपयोग कर रहे हैं, तो आप अपने वेक्टर में डालने पर स्ट्रिंग प्रतियों से बचने के लिए भी ऐसा कर सकते हैं: elems.push_back (std :: move (item)); – mchiasson

2

यह मेरा जवाब है। Verbose, पठनीय और कुशल।

std::vector<std::string> tokenize(const std::string& s, char c) { 
    auto end = s.cend(); 
    auto start = end; 

    std::vector<std::string> v; 
    for(auto it = s.cbegin(); it != end; ++it) { 
     if(*it != c) { 
      if(start == end) 
       start = it; 
      continue; 
     } 
     if(start != end) { 
      v.emplace_back(start, it); 
      start = end; 
     } 
    } 
    if(start != end) 
     v.emplace_back(start, end); 
    return v; 
} 
+0

जब तक कोई यूटीएफ 8 या कई पात्रों का उपयोग नहीं करना चाहता। – v010dya

+0

http://www.cplusplus.com/reference/cstring/strchr/ यदि इसे strchr का उपयोग करने की अनुमति है, तो यह आपके कार्यान्वयन में सहायता कर सकता है। – phoad

5

यहाँ एक स्ट्रिंग बंटवारे और boost का उपयोग कर निकाला तत्वों के साथ एक सदिश को आबाद करने का एक उदाहरण है।

#include <boost/algorithm/string.hpp> 

std::string my_input("A,B,EE"); 
std::vector<std::string> results; 

boost::algorithm::split(results, my_input, is_any_of(",")); 

assert(results[0] == "A"); 
assert(results[1] == "B"); 
assert(results[2] == "EE"); 
1

एक और regex समाधान inspired by other answers लेकिन उम्मीद है कि छोटा और आसान को पढ़ने के लिए:

std::string s{"String to split here, and here, and here,..."}; 
std::regex regex{R"([\s,]+)"}; // split on space and comma 
std::sregex_token_iterator it{s.begin(), s.end(), regex, -1}; 
std::vector<std::string> words{it, {}}; 
1

यहाँ एक सी ++ 11 समाधान खोजने :: केवल std :: स्ट्रिंग का उपयोग करता है()। डेलीमीटर लंबे अक्षरों की संख्या हो सकती है। पार्सड टोकन आउटपुट इटरेटर के माध्यम से आउटपुट होते हैं, जो आमतौर पर मेरे कोड में std :: back_inserter होता है।

मैंने यूटीएफ -8 के साथ इसका परीक्षण नहीं किया है, लेकिन मुझे उम्मीद है कि इसे तब तक काम करना चाहिए जब तक इनपुट और डिलीमीटर दोनों मान्य यूटीएफ -8 स्ट्रिंग्स हों।

#include <string> 

template<class Iter> 
Iter splitStrings(const std::string &s, const std::string &delim, Iter out) 
{ 
    if (delim.empty()) { 
     *out++ = s; 
     return out; 
    } 
    size_t a = 0, b = s.find(delim); 
    for (; b != std::string::npos; 
      a = b + delim.length(), b = s.find(delim, a)) 
    { 
     *out++ = std::move(s.substr(a, b - a)); 
    } 
    *out++ = std::move(s.substr(a, s.length() - a)); 
    return out; 
} 

कुछ परीक्षण मामलों:

void test() 
{ 
    std::vector<std::string> out; 
    size_t counter; 

    std::cout << "Empty input:" << std::endl;   
    out.clear(); 
    splitStrings("", ",", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 

    std::cout << "Non-empty input, empty delimiter:" << std::endl;   
    out.clear(); 
    splitStrings("Hello, world!", "", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 

    std::cout << "Non-empty input, non-empty delimiter" 
       ", no delimiter in string:" << std::endl;   
    out.clear(); 
    splitStrings("abxycdxyxydefxya", "xyz", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 

    std::cout << "Non-empty input, non-empty delimiter" 
       ", delimiter exists string:" << std::endl;   
    out.clear(); 
    splitStrings("abxycdxy!!xydefxya", "xy", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 

    std::cout << "Non-empty input, non-empty delimiter" 
       ", delimiter exists string" 
       ", input contains blank token:" << std::endl;   
    out.clear(); 
    splitStrings("abxycdxyxydefxya", "xy", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 

    std::cout << "Non-empty input, non-empty delimiter" 
       ", delimiter exists string" 
       ", nothing after last delimiter:" << std::endl;   
    out.clear(); 
    splitStrings("abxycdxyxydefxy", "xy", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 

    std::cout << "Non-empty input, non-empty delimiter" 
       ", only delimiter exists string:" << std::endl;   
    out.clear(); 
    splitStrings("xy", "xy", std::back_inserter(out)); 
    counter = 0;   
    for (auto i = out.begin(); i != out.end(); ++i, ++counter) { 
     std::cout << counter << ": " << *i << std::endl; 
    } 
} 

अपेक्षित उत्पादन: रिक्त स्थान पर

 
Empty input: 
0: 
Non-empty input, empty delimiter: 
0: Hello, world! 
Non-empty input, non-empty delimiter, no delimiter in string: 
0: abxycdxyxydefxya 
Non-empty input, non-empty delimiter, delimiter exists string: 
0: ab 
1: cd 
2: !! 
3: def 
4: a 
Non-empty input, non-empty delimiter, delimiter exists string, input contains blank token: 
0: ab 
1: cd 
2: 
3: def 
4: a 
Non-empty input, non-empty delimiter, delimiter exists string, nothing after last delimiter: 
0: ab 
1: cd 
2: 
3: def 
4: 
Non-empty input, non-empty delimiter, only delimiter exists string: 
0: 
1: