By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,409 Members | 940 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,409 IT Pros & Developers. It's quick & easy.

Required string parser

P: n/a
Hello,

I am writing one application in which I am getting data as a string "
10 | 20 | 30 | 40 | 50" now my aim is to parse those string, split it
by pipe '|' and get integer outputs in some array or other data
structure.....

do anybody worked in the same functionality, then please let me know.

Thanks,
Rushik.

Oct 4 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a


? "rushik" <ru*************@gmail.com?????? ??? ??????
news:11**********************@c28g2000cwb.googlegr oups.com...
Hello,

I am writing one application in which I am getting data as a string "
10 | 20 | 30 | 40 | 50" now my aim is to parse those string, split it
by pipe '|' and get integer outputs in some array or other data
structure.....

do anybody worked in the same functionality, then please let me know.

Thanks,
Rushik.
You can use the strtok function:
http://www.cplusplus.com/ref/cstring/strtok.html

Be careful though, strtok works with char *.
--
Serafeim
Oct 4 '06 #2

P: n/a

Papastefanos Serafeim wrote:
? "rushik" <ru*************@gmail.com?????? ??? ??????
news:11**********************@c28g2000cwb.googlegr oups.com...
Hello,

I am writing one application in which I am getting data as a string "
10 | 20 | 30 | 40 | 50" now my aim is to parse those string, split it
by pipe '|' and get integer outputs in some array or other data
structure.....

do anybody worked in the same functionality, then please let me know.

Thanks,
Rushik.
Hi,

Seems simple. My suggestion...

Iterate till length of string
{
Iterate till '|' found
{
extract char at ctr and concatenate char to std::string
increment ctr
}
increment ctr
if(length of string 0)
{
convert temp string into number using atoi() and store in int vector
reset std::string
}
}

Convert the pseudo code into C++ :) If it is production code, then you
will obviously put in more checks.

Regards,
Abhishek Srivastava

Oct 4 '06 #3

P: n/a

rushik wrote:
Hello,

I am writing one application in which I am getting data as a string "
10 | 20 | 30 | 40 | 50" now my aim is to parse those string, split it
by pipe '|' and get integer outputs in some array or other data
structure.....

do anybody worked in the same functionality, then please let me know.

Thanks,
Rushik.
If however you prefer doing it yourself, the std::string is well
capable of pumping out a parser. Keep in mind that you should use
std::string::size_type to hold those values returned by find_first_of
-like member functions. You can then std::istringstream the substrings
to generate the numbers. The std::string class includes a panoply of
member functions and ctors that will let you substring at construction
time or using assign(...), etc.

Here is one nasty example that uses 2 functions, one to populate a
container of relevant substrings and another templated function to
convert the substrings into a container of numbers. It'll work with
any seperator including spaces, comma, colon, etc or any combination of
these. The error checking is rudimentary at best (you need to supply
the correct seperator).

Take note that t_track is used to prevent find_first_of from rolling up
to std::string::npos ( a costly operation on some implementations).
Also, there is most likely better ways of doing this.
check out boost's tokenizer, for example.

#include <iostream>
#include <ostream>
#include <string>
#include <vector>
#include <sstream>
#include <stdexcept>

void parser( std::vector<std::string>& r_v,
const std::string& s,
const std::string& r_sep )
{
std::string::size_type t_track = s.find_last_of(r_sep);
if ( t_track == std::string::npos )
{
throw std::exception(); // no sep found
}
std::string s_temp(s); // decapitating string
while ( t_track != std::string::npos )
{
std::string::size_type t_size = s_temp.find_first_of(r_sep);
std::string s_add(s_temp, 0, t_size);
std::cout << "s_add = " << s_add << std::endl;
r_v.push_back(s_add);
t_track = t_track - s_add.size() - r_sep.size(); // npos?
s_temp.assign(s_temp, t_size + r_sep.size(), s_temp.size());
std::cout << "s_temp = " << s_temp << std::endl;
}
r_v.push_back(s_temp); // push last one
}

template< typename T >
void converter( std::vector<std::string>& r_vs,
std::vector<T>& r_vt )
{
typedef std::vector<std::string>::iterator VIter;
VIter iter = r_vs.begin();
for (iter; iter != r_vs.end(); ++iter)
{
T t;
std::istringstream iss(*iter);
iss >t;
r_vt.push_back(t);
}
}

int main()
{
std::string s("10 | 20 | 30 | 40 | 50");
// std::string s("-11 20 -3 2 4 3 1 -6");
std::vector<std::stringvs;

try
{
parser(vs, s, " | ");
std::vector<intvn;
converter<int>(vs, vn);
for (size_t i = 0; i < vn.size(); ++i)
{
std::cout << "vn[ " << i << "] = ";
std::cout << vn.at(i) << std::endl;
}
}
catch ( const std::exception& e )
{
std::cout << "Error !" << std::endl;
}

return 0;
}

/*
s_add = 10
s_temp = 20 | 30 | 40 | 50
s_add = 20
s_temp = 30 | 40 | 50
s_add = 30
s_temp = 40 | 50
s_add = 40
s_temp = 50
vn[ 0] = 10
vn[ 1] = 20
vn[ 2] = 30
vn[ 3] = 40
vn[ 4] = 50
*/

Oct 4 '06 #4

P: n/a
On 4 Oct 2006 09:49:27 -0700, "Salt_Peter" <pj*****@yahoo.comwrote:
>
template< typename T >
void converter( std::vector<std::string>& r_vs,
std::vector<T>& r_vt )
{
typedef std::vector<std::string>::iterator VIter;
VIter iter = r_vs.begin();
for (iter; iter != r_vs.end(); ++iter)
{
T t;
std::istringstream iss(*iter);
iss >t;
r_vt.push_back(t);
}
}

int main()
{
std::string s("10 | 20 | 30 | 40 | 50");
// std::string s("-11 20 -3 2 4 3 1 -6");
std::vector<std::stringvs;

try
{
parser(vs, s, " | ");
std::vector<intvn;
converter<int>(vs, vn);
for (size_t i = 0; i < vn.size(); ++i)
{
std::cout << "vn[ " << i << "] = ";
std::cout << vn.at(i) << std::endl;
}
}
catch ( const std::exception& e )
{
std::cout << "Error !" std::endl;
}

return 0;
}
Your try/catch blocks seem to indicate sufficient error treatment. But
the most problematic part of the program, the conversion between sting
and int (with inefficient stringstream), omits any error handling.

Best wishes,
Roland Pibinger
Oct 4 '06 #5

P: n/a

rushik wrote:
Hello,

I am writing one application in which I am getting data as a string "
10 | 20 | 30 | 40 | 50" now my aim is to parse those string, split it
by pipe '|' and get integer outputs in some array or other data
structure.....

do anybody worked in the same functionality, then please let me know.

Thanks,
Rushik.
std::string data="10 | 20 | 30 | 40 | 50";
std::stringstream sstr(data); // include sstream
int i1, i2, i3,i4,i5;
char c;
sstr >i1>>c>>i2>>c>>i3>>c>>i4>>c>>i5;

or like this
int i;
char c;
std::vector<intvec;
while(sstr.rdbuf()->in_avail())
{
sstr>>i>>c;
vec.push_back(i) ;
}

There are many possibilities.
strtok and sscanf are the worst of them.

Best Regards,
Valentin Heinitz

http://heinitz-it.de

Oct 4 '06 #6

P: n/a

Roland Pibinger wrote:
On 4 Oct 2006 09:49:27 -0700, "Salt_Peter" <pj*****@yahoo.comwrote:

template< typename T >
void converter( std::vector<std::string>& r_vs,
std::vector<T>& r_vt )
{
typedef std::vector<std::string>::iterator VIter;
VIter iter = r_vs.begin();
for (iter; iter != r_vs.end(); ++iter)
{
T t;
std::istringstream iss(*iter);
iss >t;
r_vt.push_back(t);
}
}

int main()
{
std::string s("10 | 20 | 30 | 40 | 50");
// std::string s("-11 20 -3 2 4 3 1 -6");
std::vector<std::stringvs;

try
{
parser(vs, s, " | ");
std::vector<intvn;
converter<int>(vs, vn);
for (size_t i = 0; i < vn.size(); ++i)
{
std::cout << "vn[ " << i << "] = ";
std::cout << vn.at(i) << std::endl;
}
}
catch ( const std::exception& e )
{
std::cout << "Error !" std::endl;
}

return 0;
}

Your try/catch blocks seem to indicate sufficient error treatment. But
the most problematic part of the program, the conversion between sting
and int (with inefficient stringstream), omits any error handling.

Best wishes,
Roland Pibinger
I agree. i see that a simple if_conversion_test should provide a simple
solution:
http://www.parashift.com/c++-faq-lit...al-issues.html
[39.2] How do I convert a std::string to a number?

int n;
std::string s;
std::istringstream iss(s);
if ( !(i >n) ) // test
throw std::exception();
....

Have you a better proposal insofar as the std::stringstream is
concerned?
Did you mean inefficient as in the stream being regenerated over each
loop?
Or rdbuf() and clear() is what you had in mind?

Oct 5 '06 #7

P: n/a

Roland Pibinger wrote:
On 4 Oct 2006 09:49:27 -0700, "Salt_Peter" <pj*****@yahoo.comwrote:

template< typename T >
void converter( std::vector<std::string>& r_vs,
std::vector<T>& r_vt )
{
typedef std::vector<std::string>::iterator VIter;
VIter iter = r_vs.begin();
for (iter; iter != r_vs.end(); ++iter)
{
T t;
std::istringstream iss(*iter);
iss >t;
r_vt.push_back(t);
}
}

int main()
{
std::string s("10 | 20 | 30 | 40 | 50");
// std::string s("-11 20 -3 2 4 3 1 -6");
std::vector<std::stringvs;

try
{
parser(vs, s, " | ");
std::vector<intvn;
converter<int>(vs, vn);
for (size_t i = 0; i < vn.size(); ++i)
{
std::cout << "vn[ " << i << "] = ";
std::cout << vn.at(i) << std::endl;
}
}
catch ( const std::exception& e )
{
std::cout << "Error !" std::endl;
}

return 0;
}

Your try/catch blocks seem to indicate sufficient error treatment. But
the most problematic part of the program, the conversion between sting
and int (with inefficient stringstream), omits any error handling.

Best wishes,
Roland Pibinger
I agree. i see that a simple if_conversion_test should provide a simple
solution:
http://www.parashift.com/c++-faq-lit...al-issues.html
[39.2] How do I convert a std::string to a number?

int n;
std::string s;
std::istringstream iss(s);
if ( !(iss >n) ) // test
throw std::exception();
....

Have you a better proposal insofar as the std::stringstream is
concerned?
Did you mean inefficient as in the stream being regenerated over each
loop?
Or rdbuf() and clear() is what you had in mind?

Oct 5 '06 #8

P: n/a
On 4 Oct 2006 19:49:56 -0700, "Salt_Peter" <...@yahoo.comwrote:
>i see that a simple if_conversion_test should provide a simple
solution:
http://www.parashift.com/c++-faq-lit...al-issues.html
[39.2] How do I convert a std::string to a number?

int n;
std::string s;
std::istringstream iss(s);
if ( !(i >n) ) // test
throw std::exception();
...

Have you a better proposal insofar as the std::stringstream is
concerned?
Did you mean inefficient as in the stream being regenerated over each
loop?
At least move the stringstream out of the loop. Alternatively you may
consider to encapsulate strtol or similar functions (but those
functions are a little tricky).

Best wishes,
Roland Pibinger

Oct 5 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.