Problem with std::istream_iterator

D

dragoncoder

Hi,

I am just a newbie in STL and trying to learn istream_iterator. My
problem is I want a program which will take a comma separated string
from the command line, tokenize it and copies into a vector. Then I am
printing the vector. Here is the code I tried.

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <functional>
#include <cassert>

int main(int argc, char* argv[])
{
assert ( argv[1] );
std::vector <std::string> v;
std::istringstream iss_st ( argv[2] );
std::istringstream iss_en ( "\n" );
std::istream_iterator < std::string > st ( iss_st );
std::istream_iterator < std::string > en ( iss_en );

std::copy ( st, en, std::back_inserter ( v ) );
std::copy ( v.begin(), v.end(), std::eek:stream_iterator <std::string> (
std::cout, "-" ) );
return 0;
}

But this code is aborting while running. I know I am missing something
very silly but not sure what.

Is there a better way of achieving the same thing though a different
way ?

Please help.

Thanks
 
J

Jerry Coffin

Hi,

I am just a newbie in STL and trying to learn istream_iterator. My
problem is I want a program which will take a comma separated string
from the command line, tokenize it and copies into a vector. Then I am
printing the vector.

One possible method: http://tinyurl.com/j63pz
 
D

dragoncoder

Jerry said:

I looked into the link, but that method seems to assume I know how many
fields are going to be there in the string. But in my case, there can
be any number to comma separated fields and I am not able to understand
why it can't be done using the istream_iterator in the right way.
 
D

Davlet Panech

dragoncoder said:
Hi,

I am just a newbie in STL and trying to learn istream_iterator. My
problem is I want a program which will take a comma separated string
from the command line, tokenize it and copies into a vector. Then I am
printing the vector. Here is the code I tried.

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <functional>
#include <cassert>

int main(int argc, char* argv[])
{
assert ( argv[1] );

I think you mean something like "assert (argc > 1)". You can only access
members of argv between 0 and argc - 1. Argv contains the command line
arguments with argv[0] being the name of your program, argv[1] is the
first argument, etc. Argc is the number of elements in argv.

Also assert() is probably not a good idea here, because it may expand to
nothing depending on the compilation options you use.


std::vector <std::string> v;
std::istringstream iss_st ( argv[2] );

You mean "argv[1]".
std::istringstream iss_en ( "\n" );
std::istream_iterator < std::string > st ( iss_st );
std::istream_iterator < std::string > en ( iss_en );

std::copy ( st, en, std::back_inserter ( v ) );

The right way to construct an end iterator is by using its default
constructor -- you don't need iss_en at all, just don't pass anything to
"en".
std::copy ( v.begin(), v.end(), std::eek:stream_iterator <std::string> (
std::cout, "-" ) );

You might want to print out a newline at the end:

std::cout << std::endl;
return 0;
}

Now this of course will split the input on white space, *not* on commas.
There are several ways to deal with commas, with or without
istream_iterator. For example you can define a wrapper class with an
overloaded "operator >>" that skips over commas (somebody posted a
similar example here recently, in the "Locating partially matched
strings in a file" thread).

D.
 
R

red floyd

Davlet said:
dragoncoder said:
assert ( argv[1] );

I think you mean something like "assert (argc > 1)". You can only access
members of argv between 0 and argc - 1. Argv contains the command line
arguments with argv[0] being the name of your program, argv[1] is the
first argument, etc. Argc is the number of elements in argv.

I don't have a copy of ISO 9899 around, but isn't argv[argc] guaranteed
to be NULL?
 
J

Jerry Coffin

[ ... ]
I looked into the link, but that method seems to assume I know how many
fields are going to be there in the string.

I'm not sure what gave you that impression, but it's incorrect.
 
R

red floyd

red said:
Davlet said:
dragoncoder said:
assert ( argv[1] );

I think you mean something like "assert (argc > 1)". You can only
access members of argv between 0 and argc - 1. Argv contains the
command line arguments with argv[0] being the name of your program,
argv[1] is the first argument, etc. Argc is the number of elements in
argv.

I don't have a copy of ISO 9899 around, but isn't argv[argc] guaranteed
to be NULL?

Note: I mentioned 9899 because I'm assuming argv behavior is inherited
from C. My copy of 14882 is at work, alas.
 
D

Davlet Panech

red said:
Davlet said:
dragoncoder said:
assert ( argv[1] );

I think you mean something like "assert (argc > 1)". You can only
access members of argv between 0 and argc - 1. Argv contains the
command line arguments with argv[0] being the name of your program,
argv[1] is the first argument, etc. Argc is the number of elements in
argv.

I don't have a copy of ISO 9899 around, but isn't argv[argc] guaranteed
to be NULL?

Yes you are right, argv[argc] is required to be 0 in ISO 14882, section
3.6.1-2.

But its wrong either way since the OP was looking to extract the first
argument from the command line.

D.
 
J

Jerry Coffin

[ ... ]
I don't have a copy of ISO 9899 around, but isn't argv[argc] guaranteed
to be NULL?

Yes -- section 5.1.2.2.1/2, bullet 2. The same is true in C++ (section
3.6.1/2).
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top