Right Way to Split an Std::String into a Vector≪String≫

Right way to split an std::string into a vector<string>

For space separated strings, then you can do this:

std::string s = "What is the right way to split a string into a vector of strings";
std::stringstream ss(s);
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> vstrings(begin, end);
std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

Output:

What
is
the
right
way
to
split
a
string
into
a
vector
of
strings


string that have both comma and space

struct tokens: std::ctype<char> 
{
tokens(): std::ctype<char>(get_table()) {}

static std::ctype_base::mask const* get_table()
{
typedef std::ctype<char> cctype;
static const cctype::mask *const_rc= cctype::classic_table();

static cctype::mask rc[cctype::table_size];
std::memcpy(rc, const_rc, cctype::table_size * sizeof(cctype::mask));

rc[','] = std::ctype_base::space;
rc[' '] = std::ctype_base::space;
return &rc[0];
}
};

std::string s = "right way, wrong way, correct way";
std::stringstream ss(s);
ss.imbue(std::locale(std::locale(), new tokens()));
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> vstrings(begin, end);
std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

Output:

right
way
wrong
way
correct
way

how can i split a vector <string > and acces what i need in it?

As user31264 suggested you could write a split function and split every line you got into its words.

IMHO this is a better and more flexible split function though:

#include <vector>
#include <string>
#include <sstream>
std::vector<std::string> split(const std::string& str, char delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(str);
while(std::getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}

What that function does is creating a stringstream out of your string (your line) and extracting words delimited by char delimiter by using getline() on that stream.

So while reading your file with getline() you could pass every line into that split function with

auto words = split(line, ' ');

and iterate over all words that line contains.

String into vector

Your code won't work; it'll store the string ss.size() times in the vector.

You might want to use a string stream to split the string:

std::stringstream stream(ss);
std::string line;
while (std::getline(stream, line)) {
test1.push_back(line);
}

Note that the newline character will be discarded. If you want to keep it, push_back(line + "\n");.

Splitting a string withisalnum and store into a vector of strings

The std::replace_if trick I commented on turned out to not be quite as trivial as I thought it was because std::isalnum doesn't return bool.

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

int main()
{
std::vector<std::string> result;
std::string something = "bob-michael !#mi%@pa hi3llary-tru1mp";
// I expected replace_if(something.begin(), something.end(), &isalnum, " ");
// would work, but then I did a bit of reading and found is alnum returned int,
// not bool. resolving this by wrapping isalnum in a lambda
std::replace_if(something.begin(),
something.end(),
[](char val)->bool {
return std::isalnum(val) == 0;
},
' ');
std::stringstream pie(something);

// read stream into vector
std::copy(std::istream_iterator<std::string>(pie),
std::istream_iterator<std::string>(),
std::back_inserter<std::vector<std::string>>(result));

// prove it works
for(const std::string & str: result)
{
std::cout << str << std::endl;
}
}

How to find out if a std::vector in a string in cpp?

Initialize bool status = true; and remove status = true;. You start with the assumption that the string contains all words. Then, you iterate over the list of words and check each word. If a word doesn't exist, set status = false;.

Store the position of the last result and start the next search at that position.

#include <iostream>
#include <vector>

int main()
{
std::string input_str1 = "Good morning, hello, a beautiful world";//true
std::string input_str2 = "what a wonderful world, hello!"; //false, but I only can return true
//item = "...hello...world..."
std::vector<std::string> item;
item.push_back("hello");
item.push_back("world");
bool status = true;
std::string::size_type pos = 0;
for (auto sub_item : item)
{
std::cout << sub_item << ' ';
pos = input_str2.find(sub_item, pos);
if (pos == std::string::npos)
{
status = false;
break;
}
}
std::cout << status;
}

Output

hello world 0

Parse (split) a string in C++ using string delimiter (standard C++)

You can use the std::string::find() function to find the position of your string delimiter, then use std::string::substr() to get a token.

Example:

std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
  • The find(const string& str, size_t pos = 0) function returns the position of the first occurrence of str in the string, or npos if the string is not found.

  • The substr(size_t pos = 0, size_t n = npos) function returns a substring of the object, starting at position pos and of length npos.


If you have multiple delimiters, after you have extracted one token, you can remove it (delimiter included) to proceed with subsequent extractions (if you want to preserve the original string, just use s = s.substr(pos + delimiter.length());):

s.erase(0, s.find(delimiter) + delimiter.length());

This way you can easily loop to get each token.

Complete Example

std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";

size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;

Output:

scott
tiger
mushroom


Related Topics



Leave a reply



Submit