12

I'm trying to figure out how could I parse this string using "sstream" and C++

The format of it is: "string,int,int".

I need to be able to assign the first part of the string which contains an IP address to a std::string.

Here is an example of this string:

std::string("127.0.0.1,12,324");

I would then need to obtain

string someString = "127.0.0.1";
int aNumber = 12;
int bNumber = 324;

I will mention again that I can't use boost library, just sstream :-)

Thanks

Goles
  • 11,599
  • 22
  • 79
  • 140
  • 2
    Smells like homework :) Or is there some other reason to why you can't use boost? – larsmoa Jan 15 '10 at 16:46
  • 2
    Why is it unusual he can't use boost? In a corporate environment you are not usually allowed to randomly add new library dependencies, it can take months to get permission or it may simply be rejected. – Mr. Boy Jan 15 '10 at 17:23
  • 1
    Or you can use Boost... but be stuck with an early version. I still have to use "1-33-x" thanks to oldish dependency that has not evolved :/ – Matthieu M. Jan 15 '10 at 19:24
  • 1
    @larsm: I have to port some stuff for embedded devices, not homework at all. :-), trying to avoid external stuff like boost for example. – Goles Jan 16 '10 at 12:40

4 Answers4

13

The C++ String Toolkit Library (Strtk) has the following solution to your problem:

int main()
{
   std::string data("127.0.0.1,12,324");
   string someString;
   int aNumber;
   int bNumber;
   strtk::parse(data,",",someString,aNumber,bNumber);
   return 0;
}

More examples can be found Here

6

It isn't fancy but you can use std::getline to split the string:

std::string example("127.0.0.1,12,324");
std::string temp;
std::vector<std::string> tokens;
std::istringstream buffer(example);

while (std::getline(buffer, temp, ','))
{
    tokens.push_back(temp);
}

Then you can extract the necessary information from each of the separated strings.

Ryan
  • 7,835
  • 2
  • 29
  • 36
  • It's much easier not to mess up than Eli's example, though limited to only one delimiter (which covers this case) it really does the trick pretty neatly. – Matthieu M. Jan 15 '10 at 19:27
3

Here's a useful tokenization function. It doesn't use streams, but can easily perform the task you require by splitting the string on commas. Then you can do whatever you want with the resulting vector of tokens.

/// String tokenizer.
///
/// A simple tokenizer - extracts a vector of tokens from a 
/// string, delimited by any character in delims.
///
vector<string> tokenize(const string& str, const string& delims)
{
    string::size_type start_index, end_index;
    vector<string> ret;

    // Skip leading delimiters, to get to the first token
    start_index = str.find_first_not_of(delims);

    // While found a beginning of a new token
    //
    while (start_index != string::npos)
    {
        // Find the end of this token
        end_index = str.find_first_of(delims, start_index);

        // If this is the end of the string
        if (end_index == string::npos)
            end_index = str.length();

        ret.push_back(str.substr(start_index, end_index - start_index));

        // Find beginning of the next token
        start_index = str.find_first_not_of(delims, end_index);
    }

    return ret;
}
Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • `if (end_index == string::npos)` is not really necessary, `std::string::substr` copies chars up until the end of string if the number spans past it's end. http://www.cplusplus.com/reference/string/string/substr/ – Dmitry Jan 15 '10 at 16:51
  • Made this the correct answer since it's a more general approach, thank you for this Eli. – Goles Jan 16 '10 at 12:42
2

You could do something like this as well I believe (Totally off the top of my head so apologies if i made some mistakes in there) ...

stringstream myStringStream( "127.0.0.1,12,324" );
int ipa, ipb, ipc, ipd;
char ch;
int aNumber;
int bNumber;
myStringStream >> ipa >> ch >> ipb >> ch >> ipc >> ch >> ipd >> ch >> aNumber >> ch >> bNumber;

stringstream someStringStream;
someStringStream << ipa << "." << ipb << "." << ipc << "." << ipd;
string someString( someStringStream.str() );
Goz
  • 61,365
  • 24
  • 124
  • 204
  • If you replace istrstream and ontrstream with stringstream and init it the correct way this works perfectly. – Goles Jan 15 '10 at 16:46
  • The first part is a string followed by a comman. You should not split that into its constituant parts unless sombody tells you its the IP4 address (or somthing specific). – Martin York Jan 15 '10 at 18:17
  • 1
    This is very fragile, and will fail on any input that does not precisely match the input structure (without allowing any sane form of error detection or recovery). This problem would be better solved with a tokeniser such as the post by @Eli Bendersky. – gavinb Jan 16 '10 at 10:47
  • indeed .. but the OP never stated that the format WOULDN'T always be like that ... – Goz Jan 16 '10 at 13:34