Connecting Tech Pros Worldwide Forums | Help | Site Map

Required string parser

rushik
Guest
 
Posts: n/a
#1: Oct 4 '06
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.


Papastefanos Serafeim
Guest
 
Posts: n/a
#2: Oct 4 '06

re: Required string parser




? "rushik" <rushik.upadhyay@gmail.com?????? ??? ??????
news:1159953521.521679.175770@c28g2000cwb.googlegr oups.com...
Quote:
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


Abhishek Srivastava
Guest
 
Posts: n/a
#3: Oct 4 '06

re: Required string parser



Papastefanos Serafeim wrote:
Quote:
? "rushik" <rushik.upadhyay@gmail.com?????? ??? ??????
news:1159953521.521679.175770@c28g2000cwb.googlegr oups.com...
Quote:
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

Salt_Peter
Guest
 
Posts: n/a
#4: Oct 4 '06

re: Required string parser



rushik wrote:
Quote:
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
*/

Roland Pibinger
Guest
 
Posts: n/a
#5: Oct 4 '06

re: Required string parser


On 4 Oct 2006 09:49:27 -0700, "Salt_Peter" <pj_hern@yahoo.comwrote:
Quote:
>
>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
vheinitz
Guest
 
Posts: n/a
#6: Oct 4 '06

re: Required string parser



rushik wrote:
Quote:
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

Salt_Peter
Guest
 
Posts: n/a
#7: Oct 5 '06

re: Required string parser



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

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?

Salt_Peter
Guest
 
Posts: n/a
#8: Oct 5 '06

re: Required string parser



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

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?

Roland Pibinger
Guest
 
Posts: n/a
#9: Oct 5 '06

re: Required string parser


On 4 Oct 2006 19:49:56 -0700, "Salt_Peter" <...@yahoo.comwrote:
Quote:
>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

Closed Thread