0

I have to split a sample string using strok function using C++. The sample string is: "This|is||a||sample||string|", while split this using strok normally.

#include <stdio.h>
#include <string>
#include <string.h>
using namespace std;

int main()
{   
string  str="This||a||sample||string|";

string a;

str=strtok ((char *)str.c_str(),"|");

while (str.c_str() != NULL)
{
    printf ("str:%s\n",str.c_str());

    str = strtok (NULL, "|");

}

return 0;
}

Result:

str:This

str:a
str:sample

str:string

While changing the same string into "This| |a| |sample| |string|" gives the expected result:

str:This

str: 

str:a

str: 

str:sample

str: 

str:string

How can I get the expect result without changing the string?

Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61
Duraisamy
  • 27
  • 2
  • 7
  • according to [ideone](http://ideone.com/vV91gD) your example results in a runtime error. are you sure that you posting the correct code? the `str=strtok ((char *)str.c_str(),"|");` looks a bit weird for me.. – default Oct 26 '13 at 10:58
  • int main() { char str[]="This| |a| |sample| |string|"; char *ptr; ptr=strtok ((char *)str,"|"); while (ptr != NULL) { printf ("str:%s\n",ptr); ptr = strtok (NULL, "|"); } return 0; } use this code – Duraisamy Oct 26 '13 at 11:01
  • you can `edit` your question with the edit button directly under the question. I suggest that you add your code there. – default Oct 26 '13 at 11:01
  • note that [c_str](http://en.cppreference.com/w/cpp/string/basic_string/c_str) is a `const` value. You shouldn't manipulate it the way you do. Have you tried copying it over to a `char` buffer (or tried searching for a method that can split a `std::string` instead)? – default Oct 26 '13 at 11:04
  • possible duplicate of [How do I tokenize a string in C++?](http://stackoverflow.com/questions/53849/how-do-i-tokenize-a-string-in-c) – Ivan Aksamentov - Drop Oct 26 '13 at 16:24

3 Answers3

4

Using std::strtok on std::string will yield undefined behaviour, since std::strtok is destructive (hint: std::string::c_str() returns const char*).

Instead, use std::string::find and std::string::substr multiple times:

#include <iostream>
#include <string>
#include <iterator>

template <class OutputIt>
OutputIt safe_tokenizer(const std::string & s, char token, OutputIt out){
  std::string::size_type pos = 0, f;  
  while((f = s.find(token, pos)) != std::string::npos){    
    *out++ = s.substr(pos, f - pos);
    pos = f + 1;
  }
  if(pos < s.size())
    *out++ = s.substr(pos);
  return out;
}

int main(){
  const std::string str = "Hello|World|How|Are|You";
  safe_tokenizer(str, '|', std::ostream_iterator<std::string>(std::cout, "\n"));
  return 0;
}
Zeta
  • 103,620
  • 13
  • 194
  • 236
1

printf? strtok? You still coding in C. And C library is not really a good way (most times) to do things in C++.

In C++ we tend to avoid operating with naked pointers, C arrays and C strings, but use STL or Boost facilities.

Check this thread for a complete examples "in real C++"

Edit: here is another thread, even better.

Edit2: And if you look at right side of this page, you can find column "Related", with many useful links on your topic =)

Community
  • 1
  • 1
Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61
  • If this question feels like a duplicate, flag it as duplicate. Note that your "answer" doesn't really answer the question. – Zeta Oct 26 '13 at 11:14
  • @Zeta, unfortunately, my rep isn't so high yet, to mark as duplicate. Do you think it is better to copy-paste code snippets from those topics? – Ivan Aksamentov - Drop Oct 26 '13 at 11:17
  • 1
    You have enough reputation to [flag it](http://stackoverflow.com/help/privileges/flag-posts), even if you cannot cast close votes yet. If you have no flags/close votes left it's better to comment on the question. – Zeta Oct 26 '13 at 11:20
0

try at strtok function

char * TOKEN;
char * mystrtok( char * string,
    const char * control)
{
    char * str=NULL;
    if(string == NULL)
    {
        str = TOKEN;
        if(*str == 0)
        return NULL;
    }
    else
        str = string;

    string = str;
    for ( ; *str ; str++ )
    {
        if(*str == *control)
        {   
            *str++ = '\0';
            break;
        }

    }

    TOKEN = str;
    return string;

}
kunal
  • 956
  • 9
  • 16