2013-05-25 44 views
10

Tôi muốn chia std::string bởi regex.C++ - Tách chuỗi bằng regex

Tôi đã tìm thấy một số giải pháp trên Stackoverflow, nhưng hầu hết trong số đó là tách chuỗi bằng không gian đơn hoặc sử dụng thư viện bên ngoài như tăng cường.

Tôi không thể sử dụng tăng.

Tôi muốn chia chuỗi theo regex - "\\s+".

Tôi đang sử dụng phiên bản g ++ g++ (Debian 4.4.5-8) 4.4.5 và tôi không thể nâng cấp.

+0

bạn đã thử '+' – Anirudha

+0

Phải biết tôi đang sử dụng dấu phẩy này các ion để tách chuỗi: http://stackoverflow.com/a/236803/418518 nó chỉ hoạt động bằng __single char__. Định dạng regex là chính xác, tôi đã sử dụng nó trong một dự án java. Hoạt động rực rỡ. –

+0

Vấn đề là tôi không biết C++ nhiều ... và tôi chỉ muốn biết cách tách 'std :: string' bằng cách sử dụng chuẩn C++ cũ (' C++ 03' có lẽ). Nếu bạn có một số liên kết/mã chỉ cần dán nó. :) Cảm ơn! –

Trả lời

8

Bạn không cần sử dụng cụm từ thông dụng nếu bạn chỉ muốn tách một chuỗi theo nhiều khoảng trắng. Viết thư viện regex của riêng bạn là quá mức cần thiết cho một cái gì đó đơn giản.

Câu trả lời bạn đã liên kết trong nhận xét, Split a string in C++?, có thể dễ dàng thay đổi để không bao gồm bất kỳ phần tử trống nào nếu có nhiều khoảng trắng.

std::vector<std::string> &split(const std::string &s, char delim,std::vector<std::string> &elems) { 
    std::stringstream ss(s); 
    std::string item; 
    while (std::getline(ss, item, delim)) { 
     if (item.length() > 0) { 
      elems.push_back(item); 
     } 
    } 
    return elems; 
} 


std::vector<std::string> split(const std::string &s, char delim) { 
    std::vector<std::string> elems; 
    split(s, delim, elems); 
    return elems; 
} 

Bằng cách kiểm tra item.length() > 0 trước khi đẩy item sang elems vector bạn sẽ không còn nhận được các yếu tố thêm nếu đầu vào của bạn chứa nhiều delimiters (khoảng trống trong trường hợp của bạn)

+0

Vâng, chúng tôi đã tìm ra cách tương tự trong cùng một thời điểm. :) Nhưng bạn đã thực sự nhanh hơn (~ 10 phút) trong việc dán câu trả lời trên SO. +1 và chấp nhận. –

+2

Bạn cũng nên đồng ý rằng việc sử dụng C++ để chia chuỗi trông giống như quá mức cần thiết lớn hơn, trong C# bạn chỉ cần 'str.split (...)';) – Lu4

31
std::regex rgx("\\s+"); 
std::sregex_token_iterator iter(string_to_split.begin(), 
    string_to_split.end(), 
    rgx, 
    -1); 
std::sregex_token_iterator end; 
for (; iter != end; ++iter) 
    std::cout << *iter << '\n'; 

Các -1 là chìa khóa ở đây: khi trình vòng lặp được xây dựng, các điểm vòng lặp tại văn bản đứng trước kết quả trùng khớp và sau mỗi lần gia tăng, các điểm vòng lặp tại văn bản theo sau kết quả phù hợp trước đó.

Nếu bạn không có C++ 11, điều tương tự sẽ hoạt động với TR1 hoặc (có thể có sửa đổi nhỏ) với Boost.

+0

Bạn cần sử dụng 'sregex_token_iterator', phải không? – Narek

+1

@Narek - hoặc là, hoặc thêm đối số mẫu rõ ràng: 'regex_token_iterator '. 'sregex_token_iterator' dễ dàng hơn. Đã sửa. Cảm ơn. –

+0

ví dụ cuối cùng về [tài liệu tham khảo cplusplus.com] (http://www.cplusplus.com/reference/regex/regex_token_iterator/regex_token_iterator/) tương tự như câu trả lời này – solstice333

6

Để mở rộng câu trả lời bằng cách @Pete Becker tôi cung cấp một ví dụ về chức năng resplit có thể được sử dụng để chia văn bản sử dụng regexp:

std::vector<std::string> 
    resplit(const std::string & s, std::string rgx_str = "\\s+") { 


     std::vector<std::string> elems; 

     std::regex rgx (rgx_str); 

     std::sregex_token_iterator iter(s.begin(), s.end(), rgx, -1); 
     std::sregex_token_iterator end; 

     while (iter != end) { 
      //std::cout << "S43:" << *iter << std::endl; 
      elems.push_back(*iter); 
      ++iter; 
     } 

     return elems; 

    } 

này hoạt động như sau:

string s1 = "first second third "; 
    vector<string> v22 = my::resplit(s1); 

    for (const auto & e: v22) { 
     cout <<"Token:" << e << endl; 
    } 


    //Token:first 
    //Token:second 
    //Token:third 


    string s222 = "first|second:third,forth"; 
    vector<string> v222 = my::resplit(s222, "[|:,]"); 

    for (const auto & e: v222) { 
     cout <<"Token:" << e << endl; 
    } 


    //Token:first 
    //Token:second 
    //Token:third 
    //Token:forth 
0
string s = "foo bar baz"; 
regex e("\\s+"); 
regex_token_iterator<string::iterator> i(s.begin(), s.end(), e, -1); 
regex_token_iterator<string::iterator> end; 
while (i != end) 
    cout << " [" << *i++ << "]"; 

in [foo] [bar] [baz]

Các vấn đề liên quan