0

Possible Duplicate:
Splitting a string in C++

I have this vector function from one of the answers I got on my question

vector<string> split(const string& s, char delim)
{
  vector<string> elems(2);
  string::size_type pos = s.find(delim);
  elems[0] = s.substr(0, pos);
  elems[1] = s.substr(pos + 1);
  return elems;
}

However, it only accept 2 elements. How do I modify it to accept based on how many delimiter s exist in the string s?

e.g if I have this:

user#password#name#fullname#telephone

sometime the size might differ.

How can I make this function flexible to work no matter how many elements, and able to split like this function above?

Just to further explain my problem:

What i wanna achieve is the capability to split using this vector function, of the same delimiter to N size instead of fixed at size 2.

This function can only split maximum 2 element in a string, more than that result in Segmentation core dump

as previously i only have needs for usage like

user:pass

now i added more attribute so i need to be able to split

user:pass:name:department

which x[2] and x[3] will return respectively name and department

they all will be using same delimiter.

Further Update:

I tried using this function provided by 1 of the answer below

vector<string> split(const string& s, char delim)
{
bool found;
vector<string> elems;
  while(1){
   string::size_type pos = s.find(delim);
   if (found==string::npos)break;
   elems.push_back(s.substr(0, pos));
   s=s.substr(pos + 1);
  }
  return elems;
}

and i get some error

server.cpp: In function ‘std::vector<std::basic_string<char> > split(const string&, char)’:
server.cpp:57:22: error: passing ‘const string {aka const std::basic_string<char>}’ as ‘this’ argument of ‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>]’ discards qualifiers [-fpermissive]
Community
  • 1
  • 1
user1587149
  • 87
  • 2
  • 7
  • no, it's not a duplicate of *that* question. no doubt someone else has asked the same question. but until such a question is found, please refrain from voting to close on the basis of "i don't understand the question" – Cheers and hth. - Alf Aug 12 '12 at 08:05
  • 1
    @close-voters: what's the hurry? do something positive instead! – Cheers and hth. - Alf Aug 12 '12 at 08:06
  • Not sure what you want to do. Do you want to have a collection of admissible delimiters so splitting `user#password@name@fullname` with the delimiter set `{#@}` would result in 4 elements? Please clarify. – bitmask Aug 12 '12 at 08:14
  • Well you want to do something 'n' times, so that means you write a loop. You want to add items to a vector, for that you use vector::push_back. You already have the method to find characters in a string and to split a string. It's just matter of putting these together in the right way. This is normal programming. Have a go yourself, and if you get stuck post your attempt and someone will help. You'll learn more this way. – jahhaj Aug 12 '12 at 08:15
  • duplication... read this article: http://stackoverflow.com/questions/236129/splitting-a-string-in-c – kain64b Aug 12 '12 at 08:17
  • @bitmask, as you can see in my sample function above, i can split with that function, but it can only accept maximum 2 element size. I want to make the function flexible to accept N size of same delimiter. – user1587149 Aug 12 '12 at 08:17
  • Oh, sorry. Now I get it: You simply want to it to produce the correct number of elements altogether, for a given (fixed) delimiter. – bitmask Aug 12 '12 at 08:18
  • @user1587149 but you have to find `N` first, for which you probably have to loop over the string, and use `push_back` to add elements to the vector each time. – juanchopanza Aug 12 '12 at 08:19
  • @kain64b: No, as Alf has noted, that question asks for splitting with white space, which allows for more tricky things than splitting with arbitrary delimiters. – bitmask Aug 12 '12 at 08:20
  • I know that I need to use push back, but where could i find a code of similar situation, I not sure how to find N size in the string using loop. – user1587149 Aug 12 '12 at 08:22
  • @user1587149 You don't need to find N, this is not a for loop it's a while loop. You just keep going until you find no more delimiters. If string::find fails, it returns a special value called string::npos. That's when you stop your loop. – jahhaj Aug 12 '12 at 08:26

3 Answers3

1

something like this %)

  vector<string> elems;
  while(1){
   string::size_type pos = s.find(delim);
   if (found==string::npos)break;
   elems.push_back(s.substr(0, pos));
   s=s.substr(pos + 1);
  }
  if(s.size())elems.push_back(s);
  return elems;
kain64b
  • 2,258
  • 2
  • 15
  • 27
  • How do i use it in a function? – user1587149 Aug 12 '12 at 08:24
  • I think this algorithm misses the last token. – juanchopanza Aug 12 '12 at 08:37
  • 3
    Good grief you really want it on a plate don't you. Are you incapable of wrapping that code in a function? Compare the code above with the function you were given earlier. It's not so hard, you might just learn something. – jahhaj Aug 12 '12 at 08:37
  • 1
    @juanchopanza I predict another question in a few days time. 'I was given this function in an earlier question but ...'. Sorry user1587149 but at some point, if you want to learn programming, you are going to have to start at least trying to do things for yourself. – jahhaj Aug 12 '12 at 08:41
  • @jahhaj yeah, I can see this question coming back to haunt us :-) – juanchopanza Aug 12 '12 at 08:43
  • I tried, but i got some issues here . Some error, I see the 2 codes are similar , as in this function here and the function I provide above, but I not sure why it result in some error. – user1587149 Aug 12 '12 at 08:44
0

well, you know, check out the push_back member function…

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

There is one answer to the almost-duplicate that provides a generic split functionality:

std::vector<std::string> split(std::string const& str, std::string const& delimiters = "#") {
  std::vector<std::string> tokens;

  // 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);
  }
  return tokens;
}

which can be easily wrapped to:

std::vector<std::string> split(std::string const& str, char const delimiter) {
  return split(str,std::string(1,delimiter));
}
Community
  • 1
  • 1
bitmask
  • 32,434
  • 14
  • 99
  • 159
  • server.cpp: In function ‘int main()’: server.cpp:152:46: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive] – user1587149 Aug 12 '12 at 08:30
  • server.cpp: In function ‘std::vector > split(const string&, char)’: server.cpp:50:44: error: cannot convert ‘std::string {aka std::basic_string}’ to ‘char’ for argument ‘2’ to ‘std::vector > split(const string&, char)’ – user1587149 Aug 12 '12 at 08:45
  • @user1587149: You *did* paste *both* functions into your file, right? – bitmask Aug 12 '12 at 08:49
  • @user1587149: Just a hint; You may want to try to understand what's going on there, instead of just copy/pasting everything that's presented to you here. – bitmask Aug 12 '12 at 08:54
  • how can i change the code so the delimiter won't be fix to '#' , I might use other delimiter sometime. – user1587149 Aug 12 '12 at 09:30
  • @user1587149: What are you talking about? The delimiter is not fixed at all. – bitmask Aug 12 '12 at 10:12