c++ সফটওয আমি কিভাবে একটি স্ট্রিং এর শব্দ উপর পুনরাবৃত্তি করবেন?




সি ল্যাংগুয়েজ (24)

এটির মূল্যের জন্য, এখানে ইনপুট স্ট্রিং থেকে টোকেনগুলি সরাতে আরেকটি উপায় রয়েছে, এটি শুধুমাত্র স্ট্যান্ডার্ড লাইব্রেরির সুবিধাগুলির উপর নির্ভর করে। এটি এসটিএলের নকশা পিছনে শক্তি এবং সুদর্শন একটি উদাহরণ।

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

আউটপুট প্রবাহে নিষ্কাশিত টোকেনগুলি অনুলিপি করার পরিবর্তে, একই জেনেরিক copy অ্যালগরিদমটি ব্যবহার করে, সেগুলি একটি ধারকতে ঢোকাতে পারে।

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

... অথবা সরাসরি vector তৈরি করুন:

vector<string> tokens{istream_iterator<string>{iss},
                      istream_iterator<string>{}};

আমি একটি স্ট্রিং এর শব্দ উপর পুনরাবৃত্তি করার চেষ্টা করছি।

স্ট্রিং হোয়াইটস্পেস দ্বারা আলাদা শব্দ গঠিত হতে অনুমিত হতে পারে।

উল্লেখ্য যে আমি সি স্ট্রিং ফাংশন বা চরিত্র ম্যানিপুলেশন / অ্যাক্সেসের যে ধরনের আগ্রহী নই। এছাড়াও, আপনার উত্তর দক্ষতা উপর কমনীয়তা অগ্রাধিকার দিতে দয়া করে।

এখন আমার সবচেয়ে ভাল সমাধান হল:

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

এটা করার জন্য আরো মার্জিত উপায় আছে?


নীচের কোডটি 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;
}

এসটিএল ইতিমধ্যে যেমন একটি পদ্ধতি উপলব্ধ নেই।

যাইহোক, আপনি std::string::c_str() সদস্য ব্যবহার করে সি এর strtok() ফাংশনটি ব্যবহার করতে পারেন, অথবা আপনি নিজের লিখতে পারেন। এখানে একটি দ্রুত Google অনুসন্ধানের পরে পাওয়া একটি কোড নমুনা ( "STL স্ট্রিং বিভক্ত" ):

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

থেকে নেওয়া হয়েছে: http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html

যদি আপনার কোড নমুনা সম্পর্কে প্রশ্ন থাকে তবে একটি মন্তব্য করুন এবং আমি ব্যাখ্যা করব।

এবং এটি কারণ এটি typedef নামে টাইপডফ প্রয়োগ না করে বা << লোড করা << অপারেটরের মানে এটি খারাপ কোড নয়। আমি বেশ ঘন ঘন সি ফাংশন ব্যবহার। উদাহরণস্বরূপ, printf এবং scanf উভয় std::cin এবং std::cout (উল্লেখযোগ্য) এর চেয়ে দ্রুততর, fopen সিনট্যাক্স বাইনারি ধরনের জন্য অনেক বেশি বন্ধুত্বপূর্ণ এবং তারা ছোট EXEs উত্পাদন করতে থাকে।

এই "কর্মক্ষমতা উপর লক্ষণ" চুক্তি বিক্রি করবেন না।


এখানে একটি বিভক্ত ফাংশন যে:

  • জেনেরিক
  • স্ট্যান্ডার্ড সি ++ ব্যবহার করে (কোন বুস্ট)
  • একাধিক delimiters গ্রহণ
  • খালি টোকেন উপেক্ষা করে (সহজেই পরিবর্তন করা যেতে পারে)

    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's left of the string
        return v;
    }
    

উদাহরণ ব্যবহার:

    vector<string> v = split<string>("Hello, there; World", ";,");
    vector<wstring> v = split<wstring>(L"Hello, there; World", L";,");

এটা করার অন্য উপায় এখানে ..

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

এই সম্পর্কে কি:

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

বুস্ট ব্যবহার করে একটি সম্ভাব্য সমাধান হতে পারে:

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

এই পদ্ধতির stringstream পদ্ধতির চেয়ে আরও দ্রুত হতে পারে। এবং যেহেতু এটি একটি জেনারিক টেমপ্লেট ফাংশন, তাই এটি অন্যান্য ধরণের সীমাবদ্ধতা ব্যবহার করে অন্যান্য ধরণের স্ট্রিং (ওয়াচার, ইত্যাদি বা UTF-8) বিভক্ত করতে ব্যবহার করা যেতে পারে।

বিস্তারিত জানার জন্য documentation দেখুন।


এখানে একটি সাধারণ সমাধান যা শুধুমাত্র স্ট্যান্ডার্ড রেজেক্স লাইব্রেরি ব্যবহার করে

#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 যুক্তি একাধিক আর্গুমেন্ট (স্থান, কমা, ইত্যাদি) জন্য পরীক্ষা করতে পারবেন

আমি সাধারণত স্পেস এবং কমাতে বিভক্ত চেক করি, তাই আমারও এই ডিফল্ট ফাংশন রয়েছে:

std::vector<string> TokenizeDefault( const string str )
{
    using namespace std;

    regex re( "[\\s,]+" );

    return Tokenize( str, re );
}

"[\\s,]+" স্পেস ( \\s ) এবং কমা ( , ) জন্য চেক করে।

নোট, আপনি string পরিবর্তে wstring বিভক্ত করতে চান,

  • সব std::regex std::wregex
  • সব sregex_token_iterator পরিবর্তন করুন

দ্রষ্টব্য, আপনি আপনার কম্পাইলারের উপর নির্ভর করে, রেফারেন্স দ্বারা স্ট্রিং যুক্তি নিতে চাইতে পারেন।


আপনি যদি বুস্ট ব্যবহার করতে চান তবে ডিলিমিটার হিসাবে একটি সম্পূর্ণ স্ট্রিং ব্যবহার করতে চান (পূর্বের প্রস্তাবিত সমাধানগুলি সর্বাধিক হিসাবে একক অক্ষরের পরিবর্তে), আপনি boost_split_iterator ব্যবহার করতে পারেন।

সুবিধাজনক টেমপ্লেট সহ উদাহরণ কোড:

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

এটি স্ট্যাক ওভারফ্লো প্রশ্নটির অনুরূপ আমি কিভাবে C ++ এ একটি স্ট্রিংকে টোকেনাইজ করব?

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

সংক্ষিপ্ত এবং মার্জিত

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

ডিলিমিটার হিসাবে যেকোনো স্ট্রিং ব্যবহার করতে পারেন, বাইনারি ডেটা দিয়েও এটি ব্যবহার করা যেতে পারে (std :: string বাইনারি ডেটা সমর্থন করে, নুল সহ)

ব্যবহার:

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

আউটপুট:

this
is
!example!string

Heres একটি regex সমাধান যা শুধুমাত্র স্ট্যান্ডার্ড regex লাইব্রেরি ব্যবহার করে। (আমি একটু ক্ষতিকারক, তাই কিছু সিনট্যাক্স ত্রুটি হতে পারে, কিন্তু এটি অন্তত সাধারণ ধারণা)

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

strtok নামে একটি ফাংশন আছে।

#include<string>
using namespace std;

vector<string> split(char* str,const char* delim)
{
    char* saveptr;
    char* token = strtok_r(str,delim,&saveptr);

    vector<string> result;

    while(token != NULL)
    {
        result.push_back(token);
        token = strtok_r(NULL,delim,&saveptr);
    }
    return result;
}

Boost পান ! : -)

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <vector>

using namespace std;
using namespace boost;

int main(int argc, char**argv) {
    typedef vector < string > list_type;

    list_type list;
    string line;

    line = "Somewhere down the road";
    split(list, line, is_any_of(" "));

    for(int i = 0; i < list.size(); i++)
    {
        cout << list[i] << endl;
    }

    return 0;
}

এই উদাহরণ আউটপুট দেয় -

Somewhere
down
the
road

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

আমি এটি তৈরি করেছি কারণ আমার স্ট্রিং এবং সি-ভিত্তিক স্ট্রিংগুলি বিভক্ত করার একটি সহজ উপায় দরকার ... আশা করছি অন্য কেউ এটিও দরকারী হিসাবে খুঁজে পেতে পারে। এছাড়াও এটি টোকেনগুলির উপর নির্ভর করে না এবং আপনি ক্ষেত্রগুলিকে delimiters হিসাবে ব্যবহার করতে পারেন, যা আমার প্রয়োজনীয় অন্য একটি কী।

আমি নিশ্চিত যে তার উন্নতির আরও উন্নতির জন্য এমন উন্নতি রয়েছে যা দয়া করে সব উপায়ে করুন

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

উদাহরণ:

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

আউটপুট হবে:

এই
হল
একটি
উদাহরণ
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;
}

খালি এন্ট্রি রাখতে (ডিফল্ট খালিগুলি বাদ দেওয়া হবে):

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

লক্ষ্যটি সি # এর স্প্লিট () পদ্ধতির মতো তৈরি করা যেখানে একটি স্ট্রিং বিভক্ত করা এত সহজ:

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

foreach(String X in Split)
{
    Console.Write(X);
}

আমি আশা করি অন্য কেউ এটি হিসাবে দরকারী হিসাবে আমার খুঁজে পেতে পারেন।


আমার এই সমস্যার একটি 2 লাইন সমাধান আছে:

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;

তারপর মুদ্রণ করার পরিবর্তে আপনি এটি একটি ভেক্টর রাখতে পারেন।


আমি নিম্নলিখিতটিকে পছন্দ করি কারণ এটি একটি ভেক্টরের ফলাফল রাখে, একটি স্ট্রিংকে একটি ডেলিম হিসাবে সমর্থন করে এবং খালি মানগুলি ধরে রাখতে নিয়ন্ত্রণ দেয়। কিন্তু, এটি ভাল হিসাবে তাকান না।

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

অবশ্যই, বুস্ট একটি split() যা আংশিকভাবে এটির মতো কাজ করে। এবং, 'হোয়াইট-স্পেস' দ্বারা, আপনি সত্যিই কোনও হোয়াইট-স্পেস মানে, বুস্টের split ব্যবহার করে is_any_of() দুর্দান্ত কাজ করে।


এই উত্তর স্ট্রিং লাগে এবং এটি স্ট্রিং একটি ভেক্টর মধ্যে রাখে। এটি বুস্ট লাইব্রেরি ব্যবহার করে।

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

সম্প্রতি আমি একটি উট-cased শব্দ subwords মধ্যে বিভক্ত ছিল। কোন delimiters, শুধু উপরের অক্ষর আছে।

#include <string>
#include <list>
#include <locale> // std::isupper

template<class String>
const std::list<String> split_camel_case_string(const String &s)
{
    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" কে "এ", "কোয়েরি" এবং "ব্যবসায়" তে বিভক্ত করে। ফাংশন সংকীর্ণ এবং প্রশস্ত স্ট্রিং সঙ্গে কাজ করে। কারন এটি বর্তমান লোকেলকে সম্মান করে কারণ "রুমফাহার্টুবারউচুং ভেরর্ডনং" "রুমফাহার্ট", ​​"Überwachungs" এবং "Verordnung" তে বিভক্ত।

নোট std::upperসত্যিই ফাংশন টেমপ্লেট যুক্তি হিসাবে পাস করা উচিত। তারপর এই ফাংশন থেকে আরো সাধারণকরণ delimiters মত বিভক্ত ",", ";"বা " "খুব।


এখনো আরেকটি নমনীয় এবং দ্রুত উপায়

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

স্ট্রিংগুলির একটি ভেক্টর দিয়ে এটি ব্যবহার করতে (সম্পাদনা: যেহেতু কেউ এসটিএল ক্লাসের উত্তরাধিকারী না হওয়ার নির্দেশ দেয় ...) এইচআরএমএফ;):

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");

এটাই! এবং টোকেনাইজার ব্যবহার করার একমাত্র উপায়, যেমন শব্দগুলি কীভাবে গণনা করা যায়:

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

কল্পনা দ্বারা সীমিত;)


আমি strtok ব্যবহার করে আমার নিজের ঘূর্ণিত করেছি এবং একটি স্ট্রিং বিভক্ত ব্যবহার boost। আমার সবচেয়ে ভাল পদ্ধতি হল সি ++ স্ট্রিং টুলকিট লাইব্রেরি । এটা অবিশ্বাস্যভাবে নমনীয় এবং দ্রুত।

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

টুলকিটটিতে এই সহজ উদাহরণটি দেখানোর চেয়ে অনেক বেশি নমনীয়তা রয়েছে তবে দরকারী উপাদানের মধ্যে একটি স্ট্রিং বিশ্লেষণে এর উপযোগিতা অবিশ্বাস্য।


আমি এই টাস্কের জন্য বুস্ট / রেজেক্স পদ্ধতিগুলি ব্যবহার করতে চাই কারণ তারা বিভাজন মানদণ্ডের জন্য সর্বাধিক নমনীয়তা সরবরাহ করে।

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

std::stringstream ব্যবহার করে যেমন আপনি পুরোপুরি সূক্ষ্ম কাজ করেছেন, এবং আপনি যা চান তা ঠিক করুন। যদিও আপনি শুধু কিছু করার জন্য ভিন্ন উপায় খুঁজছেন, আপনি std::find_first_of() / std::find_first_of() এবং std::string::substr() ব্যবহার করতে পারেন।

এখানে একটি উদাহরণ:

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




split