[C++] تحليل (تقسيم) سلسلة في C ++ باستخدام محدد السلسلة (القياسي C ++)


Answers

يستخدم هذا الأسلوب std::string::find دون تحوير السلسلة الأصلية عن طريق تذكر بداية ونهاية رمز السلسلة الفرعية السابقة.

#include <iostream>
#include <string>

int main()
{
    std::string s = "scott>=tiger";
    std::string delim = ">=";

    auto start = 0U;
    auto end = s.find(delim);
    while (end != std::string::npos)
    {
        std::cout << s.substr(start, end - start) << std::endl;
        start = end + delim.length();
        end = s.find(delim, start);
    }

    std::cout << s.substr(start, end);
}
Question

هذا السؤال لديه بالفعل إجابة هنا:

ممكن تكرار:
تقسيم سلسلة في C ++

أنا تحليل سلسلة في C ++ باستخدام ما يلي:

string parsed,input="text to be parsed";
stringstream input_stringstream(input);

if(getline(input_stringstream,parsed,' '))
{
     // do some processing.
}

تحليل مع محدد حرف واحد على ما يرام. ولكن ماذا لو كنت أريد استخدام سلسلة كمحدد.

مثال: أرغب في التقسيم:

scott>=tiger

مع> = كمحدد بحيث يمكنني الحصول على سكوت ونمر.




#include<iostream>
#include<algorithm>
using namespace std;

int split_count(string str,char delimit){
return count(str.begin(),str.end(),delimit);
}

void split(string str,char delimit,string res[]){
int a=0,i=0;
while(a<str.size()){
res[i]=str.substr(a,str.find(delimit));
a+=res[i].size()+1;
i++;
}
}

int main(){

string a="abc.xyz.mno.def";
int x=split_count(a,'.')+1;
string res[x];
split(a,'.',res);

for(int i=0;i<x;i++)
cout<<res[i]<<endl;
  return 0;
}

PS: يعمل فقط إذا كانت أطوال السلاسل بعد الفصل متساوية




strtok يسمح لك بالمرور في أحرف متعددة كمحددات. أراهن إذا قمت بالتمرير في "> =" سيتم تقسيم سلسلة المثال الخاصة بك بشكل صحيح (على الرغم من أن يتم حساب> و = كمحددات فردية).

EDIT إذا كنت لا تريد استخدام c_str() للتحويل من سلسلة إلى char * ، يمكنك استخدام substr و find_first_of to find_first_of .

string token, mystring("scott>=tiger");
while(token != mystring){
  token = mystring.substr(0,mystring.find_first_of(">="));
  mystring = mystring.substr(mystring.find_first_of(">=") + 1);
  printf("%s ",token.c_str());
}



أود استخدام boost::tokenizer . في ما يلي وثائق توضح كيفية إنشاء وظيفة tokenizer مناسبة: http://www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htm

هنا واحد يعمل لقضيتك.

struct my_tokenizer_func
{
    template<typename It>
    bool operator()(It& next, It end, std::string & tok)
    {
        if (next == end)
            return false;
        char const * del = ">=";
        auto pos = std::search(next, end, del, del + 2);
        tok.assign(next, pos);
        next = pos;
        if (next != end)
            std::advance(next, 2);
        return true;
    }

    void reset() {}
};

int main()
{
    std::string to_be_parsed = "1) one>=2) two>=3) three>=4) four";
    for (auto i : boost::tokenizer<my_tokenizer_func>(to_be_parsed))
        std::cout << i << '\n';
}



إذا كنت لا ترغب في تعديل السلسلة (كما هو الحال في إجابة Vincenzo Pii) وتريد إخراج آخر رمز مميز أيضًا ، فقد ترغب في استخدام هذا الأسلوب:

inline std::vector<std::string> splitString( const std::string &s, const std::string &delimiter ){
    std::vector<std::string> ret;
    size_t start = 0;
    size_t end = 0;
    size_t len = 0;
    std::string token;
    do{ end = s.find(delimiter,start); 
        len = end - start;
        token = s.substr(start, len);
        ret.emplace_back( token );
        start += len + delimiter.length();
        std::cout << token << std::endl;
    }while ( end != std::string::npos );
    return ret;
}



Links