convert string into an array

S

Sudzzz

Hi,
I'm trying to convert a string something like this
"{201,23,240,56,23,45,34,23}" into an array in C++
Please help.
Thanks,
Sudzzz
 
V

Victor Bazarov

Sudzzz said:
I'm trying to convert a string something like this
"{201,23,240,56,23,45,34,23}" into an array in C++
Please help.

We're happy to help. What have you done so far and what
are the problems? Read the FAQ, especially section 5.

V
 
S

Sudzzz

We're happy to help. What have you done so far and what
are the problems? Read the FAQ, especially section 5.

V

Currently I have a string "{201,23,240,56,23,45,34,23}" which changes
frequently (possibly at 3Hz). The numbers can be any number having
less than 4 digits. I want to take this string and place it in an
array so that I can use for certain computational purposes. I've
looked through different possibilities one of which would involve an
extensive string comparison, atoi(), append to array sort of
algorithm. However I realized that when we input arrays c++ accepts it
in the same form as above and then I thought whether I could simulate c
++ input this string when asked for an array.
I don't know where to start.
Thanks,
Sudzzz

http://sudeeppillai.blogspot.com
 
V

Victor Bazarov

Sudzzz said:
Currently I have a string "{201,23,240,56,23,45,34,23}" which changes
frequently (possibly at 3Hz). The numbers can be any number having
less than 4 digits. I want to take this string and place it in an
array so that I can use for certain computational purposes. I've
looked through different possibilities one of which would involve an
extensive string comparison, atoi(), append to array sort of
algorithm. However I realized that when we input arrays c++ accepts it
in the same form as above and then I thought whether I could simulate
c ++ input this string when asked for an array.

Yes, you can simulate C++ input, and it will involve some character
comparison, atoi (or strtol, more like it), append to array, sort of
algorithm. How do you think the compiler does that?
I don't know where to start.

Start here:

#include <string>
#include <vector>
#include <cassert>

int main() {
std::string mystring("{201,23,240,56,23,45,34,23}");
std::vector<int> vint;

// write code to extract numbers from the 'mystring'
// and place them into 'vint'

assert(vint.size() == 8);
assert(vint[0] == 201);
assert(vint[1] == 23);
assert(vint[2] == 240);
assert(vint[3] == 56);
assert(vint[4] == 23);
assert(vint[5] == 45);
assert(vint[6] == 34);
assert(vint[7] == 23);
}

V
 
Z

Zachary Turner

Currently I have a string "{201,23,240,56,23,45,34,23}" which changes
frequently (possibly at 3Hz). The numbers can be any number having
less than 4 digits. I want to take this string and place it in an
array so that I can use for certain computational purposes. I've
looked through different possibilities one of which would involve an
extensive string comparison, atoi(), append to array sort of
algorithm. However I realized that when we input arrays c++ accepts it
in the same form as above and then I thought whether I could simulate c
++ input this string when asked for an array.
I don't know where to start.
Thanks,
Sudzzz

http://sudeeppillai.blogspot.com

You will have to tokenize the string, extracting characters between an
open curly brace '{', a comma ',' and a close curly brace '}'.

std::string str_array = "{201,23,240,56,23,45,34,23}";
std::string::size_type pos = 0;

std::vector<int> int_array;

while (pos != std::string::npos)
{
std::string::size_type pos2;

pos = str_array.find_first_not_of("{,}", pos);
if (pos == std::string::npos) break;
pos2 = str_array.find_first_of("{,}", pos);

std::string str_number = str_array.substr(pos, pos2-pos+1);
int number = atoi(str_number.c_str()); //Might use a stream here
instead
int_array.push_back(number);

pos2 = pos;
}


I'm sure this will have some off-by-one errors and other bugs, because
I am not familiar with the signature of all these functions from
memory, but the idea is the same.
 
J

Jim Langston

Sudzzz said:
Currently I have a string "{201,23,240,56,23,45,34,23}" which changes
frequently (possibly at 3Hz). The numbers can be any number having
less than 4 digits. I want to take this string and place it in an
array so that I can use for certain computational purposes. I've
looked through different possibilities one of which would involve an
extensive string comparison, atoi(), append to array sort of
algorithm. However I realized that when we input arrays c++ accepts it
in the same form as above and then I thought whether I could simulate c
++ input this string when asked for an array.
I don't know where to start.

I would use a stringstream. Output of following program is:

201 23 240 56 23 45 34 23

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

int main()
{
std::string str_array = "{201,23,240,56,23,45,34,23}";
std::stringstream Buffer;
Buffer << str_array;
char Trash;
Buffer >> Trash; // Throw away (
int Value;
std::vector<int> Data;
while ( Buffer >> Value )
{
Data.push_back( Value );
Buffer >> Trash; // Throw away , or )
}

// Display vector data
for ( std::vector<int>::iterator it = Data.begin(); it != Data.end();
++it )
std::cout << *it << " ";

}
 
J

James Kanze

We're happy to help. What have you done so far and what
are the problems? Read the FAQ, especially section 5.
[/QUOTE]
Currently I have a string "{201,23,240,56,23,45,34,23}" which changes
frequently (possibly at 3Hz). The numbers can be any number having
less than 4 digits. I want to take this string and place it in an
array so that I can use for certain computational purposes.

Is the number of elements constant, i.e. always 8. If so, use
boost::regex to validate the syntax and break the string down
into 8 substrings with just the numbers. Then use
istringstream, initialized with each of the substrings, to
convert. (This is definitly not the fastest solution, but it
should be adequate for three times a second, and it is certainly
the easiest to write.)

Otherwise, you'll have to write a simple parser yourself. Again,
you'll use istringstream. A couple of hints:

char ch ;
stream >> ch ;

gets the next non-blank character. (Attention: the character is
extracted from the stream, and is no longer available.) And

int i ;
stream >> i ;

to read an int.

So a priori, something like the following should do the trick:

char ch ;
stream >> ch ;
if ( ! stream || ch != '{' ) {
error...
}
do
{
int i ;
stream >> i >> ch ;
if ( stream ) {
result.push_back( i ) ;
}
} while ( stream && ch == ',' ) ;
if ( ! stream || ch != '}' ) {
error ...
}
 
J

James Kanze

I would use a stringstream.

Just curious, but why a stringstream, and not an istringstream?

[...]
std::string str_array = "{201,23,240,56,23,45,34,23}";
std::stringstream Buffer;
Buffer << str_array;

Why those two lines, instead of simply:

std::istringstream Buffer( str_array ) ;
char Trash;
Buffer >> Trash; // Throw away (

Throw away, or verify, as a syntax check? (In my experience,
you can never verify input too much.)
int Value;
std::vector<int> Data;
while ( Buffer >> Value )

while ( Buffer >> Value && Trash != '}' )

And

if ( Trash != (Data.empty() ? '{' : ',') ) {
Buffer.setstate( std::ios::failbit ) ;
}

here.
Data.push_back( Value );
Buffer >> Trash; // Throw away , or )
}

And a final error check:

if ( ! (Buffer >> std::ws && Buffer.get() == EOF ) {
error ...
}
// Display vector data
for ( std::vector<int>::iterator it = Data.begin(); it != Data.end();
++it )
std::cout << *it << " ";
}

(But I like your basic algorithm better than the one I
suggested.)
 
B

BobR

/* """

I would use a stringstream.

Just curious, but why a stringstream, and not an istringstream?

[...]
std::string str_array = "{201,23,240,56,23,45,34,23}";
std::stringstream Buffer;
Buffer << str_array;

Why those two lines, instead of simply:

std::istringstream Buffer( str_array ) ;

""" */

Aww, c'mon James, we can do better than that. :-}

My original code, revised.
{
std::string stin( "{201,23,240,56,23,45,34,23}" );

std::istringstream in( stin.substr( 1, stin.size()-2 ) ); // <---- :-}
// assumes the strings are always *that* format, "{....}".

// now use this, or Jim's code from here ( with 'Trash' removed! [1]).
std::vector<int> array;
for( std::string line; std::getline( in, line, ',' ); ){
std::istringstream conv( line );
int num(0);
conv >> num;
if( not conv ){ break;}
array.push_back( num );
// conv.clear(); conv.str("");
}
for( std::size_t i(0); i < array.size(); ++i ){
std::cout<< array.at( i ) <<" ";
}
}
// output:201 23 240 56 23 45 34 23

[1]
// > Buffer >> Trash; // Throw away (
char tst = Buffer.peek();
if( tst == '{' || tst == ',' || tst == '}' ){ Buffer.ignore(1); }
 
J

Jim Langston

Just curious, but why a stringstream, and not an istringstream?

I don't know. I use stringstream for all types of conversion and it works.
What real advantage would istringstream give me?
[...]
std::string str_array = "{201,23,240,56,23,45,34,23}";
std::stringstream Buffer;
Buffer << str_array;

Why those two lines, instead of simply:

std::istringstream Buffer( str_array ) ;

Becuase I normally use stringstring in one of my templates:

template<typename T, typename F > T StrmConvert( const F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

If I change this to

std::string temp( from );

then I get compiler warnings at times depending on F.

warning C4244: 'argument' : conversion from 'const float' to
'std::_Iosb<_Dummy>::eek:penmode', possible loss of data

and I go for 0% warnings in my code. I know that the form I use doesn't
give any warnings.
Throw away, or verify, as a syntax check? (In my experience,
you can never verify input too much.)

Agreed, but in most instances where I'm using stringstream for conversion
I've verified the data before I try to convert it, or the output makes it
obvious there was a problem. With user input data I would definately do
syntax checking of the string before/during/after the conversion.
while ( Buffer >> Value && Trash != '}' )

This is really not needed though, unless there is extraneous data after
the ) such as

{201,23,240,56,23,45,34,23}75

etc... (not going to comment on the rest)
 
J

James Kanze

I don't know. I use stringstream for all types of conversion
and it works. What real advantage would istringstream give
me?

It seems clearer to me if you're only going to be reading. I
use istringstream for input conversions (from text to whatever),
and ostringstream for output conversions (to text from
whatever). Somehow, it just seems clearer to say up front what
I'm going to do.
[...]
std::string str_array = "{201,23,240,56,23,45,34,23}";
std::stringstream Buffer;
Buffer << str_array;
Why those two lines, instead of simply:
std::istringstream Buffer( str_array ) ;
Becuase I normally use stringstring in one of my templates:
template<typename T, typename F > T StrmConvert( const F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

Sort of boost::lexical_cast, in sum. That's a different
context. (I'm not totally convinced that boost::lexical_cast is
a good idea. I'm not too hot on the idea that you can convert
anything to anything else, and never get a compiler error.)
If I change this to
std::string temp( from );
then I get compiler warnings at times depending on F.
warning C4244: 'argument' : conversion from 'const float' to
'std::_Iosb<_Dummy>::eek:penmode', possible loss of data
and I go for 0% warnings in my code. I know that the form I
use doesn't give any warnings.

One could argue that since you're doing two conversions, you
should have two conversion objects, i.g.:

std::istringstream in ;
in << from ;
std::eek:stringstream out( in.str() ) ;
T to ;
out >> to ;
return to ;

I'm not sure. As I said, I'm not too hot on this idea to begin
with. (If I were doing it, I'd certainly add a lot of error
handling. But I presume you've just stripped it out to make it
shorter for posting.)
Agreed, but in most instances where I'm using stringstream for
conversion I've verified the data before I try to convert it,
or the output makes it obvious there was a problem.

In most cases, I have too. Nothing like boost::regex
beforehand, to know what I'm dealing with. (But I thought I'd
mentionned that.) If you don't know the length in advance,
however, it's probably easier to do the checking dynamically.

I don't know the full context either. It might be worth
considering creating a decorator type for which you define an
operator>>, and use that, something like:

source >> ArrayReader( array ) ;
With user input data I would definately do syntax checking of
the string before/during/after the conversion.
This is really not needed though, unless there is extraneous data after
the ) such as

etc...

Yes. The real question is whether the string has been format
checked before hand, or not. If it has, then no further
checking should be necessary. If it hasn't, you probably want
to verify everything.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,291
Messages
2,571,476
Members
48,143
Latest member
Manuelevimb

Latest Threads

Top