converting a string to an array of words

  • Thread starter Frederik Van Bogaert
  • Start date
F

Frederik Van Bogaert

Hi! I've taken my first steps into the world of c++ by trying to write a
text adventure game. Things are proceeding fine, but there's some code
in there that isn't very well coded. More specifically, I use the
following code:

...
string word [4];
size_t pos = action.find(" ");
word[0] = action.substr (0,pos);
if (pos < action.size() - 2)
{
word[1] = action.substr(pos + 1);
}
string word1 [2];

for (int i=1;i<3;i++)
{
pos = word.find(" ");
if (pos == string::npos) goto skippy;
word1[i-1] = word.substr (0,pos);
if (pos < word.size() - 2)
{
word[i+1] = word.substr(pos + 1);
}
word = word1[i-1];
}

skippy:
...

To convert a string called 'action' into the array word[4]. Is there a
way to do this more efficiently?
Thanks
 
V

Victor Bazarov

Frederik said:
[..]

To convert a string called 'action' into the array word[4]. Is there a
way to do this more efficiently?

Not sure about efficiency. But elegance is relatively easy to come by.
All you need to do is take your string, construct a stringstream out of
it and then read all the words from it until end-of-file.

V
 
J

Jim Langston

Frederik Van Bogaert said:
Hi! I've taken my first steps into the world of c++ by trying to write a
text adventure game. Things are proceeding fine, but there's some code in
there that isn't very well coded. More specifically, I use the following
code:

...
string word [4];
size_t pos = action.find(" ");
word[0] = action.substr (0,pos);
if (pos < action.size() - 2)
{
word[1] = action.substr(pos + 1);
}
string word1 [2];

for (int i=1;i<3;i++)
{
pos = word.find(" ");
if (pos == string::npos) goto skippy;
word1[i-1] = word.substr (0,pos);
if (pos < word.size() - 2)
{
word[i+1] = word.substr(pos + 1);
}
word = word1[i-1];
}

skippy:
...

To convert a string called 'action' into the array word[4]. Is there a way
to do this more efficiently?
Thanks


Use. std::stringstream. stringstream will read using >> like std::cin,
stopping on spaces.

Output of following program is:

look
at
the
clock
on
the
wall

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

// typedef is not required, just makes it a little eaiser.
typedef std::vector<std::string> WordVec;

int main()
{
std::string action = "look at the clock on the wall";

WordVec Words;
// Following declares a stringstream Parse and initializes it to the
contents of action
std::stringstream Parse( action );

// Now we read each word out one by one til there's no more and stuff
them into our vector
std::string word;
while ( Parse >> word )
Words.push_back( word );

// At this point each word is in the vector.

for ( WordVec::iterator it = Words.begin(); it != Words.end(); ++it )
std::cout << (*it) << "\n";

std::string wait;
std::getline( std::cin, wait );
}
 
F

Frederik Van Bogaert

Jim said:
Frederik Van Bogaert said:
Hi! I've taken my first steps into the world of c++ by trying to write a
text adventure game. Things are proceeding fine, but there's some code in
there that isn't very well coded. More specifically, I use the following
code:

...
string word [4];
size_t pos = action.find(" ");
word[0] = action.substr (0,pos);
if (pos < action.size() - 2)
{
word[1] = action.substr(pos + 1);
}
string word1 [2];

for (int i=1;i<3;i++)
{
pos = word.find(" ");
if (pos == string::npos) goto skippy;
word1[i-1] = word.substr (0,pos);
if (pos < word.size() - 2)
{
word[i+1] = word.substr(pos + 1);
}
word = word1[i-1];
}

skippy:
...

To convert a string called 'action' into the array word[4]. Is there a way
to do this more efficiently?
Thanks


Use. std::stringstream. stringstream will read using >> like std::cin,
stopping on spaces.

Output of following program is:

look
at
the
clock
on
the
wall

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

// typedef is not required, just makes it a little eaiser.
typedef std::vector<std::string> WordVec;

int main()
{
std::string action = "look at the clock on the wall";

WordVec Words;
// Following declares a stringstream Parse and initializes it to the
contents of action
std::stringstream Parse( action );

// Now we read each word out one by one til there's no more and stuff
them into our vector
std::string word;
while ( Parse >> word )
Words.push_back( word );

// At this point each word is in the vector.

for ( WordVec::iterator it = Words.begin(); it != Words.end(); ++it )
std::cout << (*it) << "\n";

std::string wait;
std::getline( std::cin, wait );
}

Thanks! That's exactly what I was looking for :)

PS: Is there some reason you're using "std::" all the time instead of
specifying "using namespace std;" in the beginning of the file as I've
been told to do?
 
V

Victor Bazarov

Jim said:
[..]
// Now we read each word out one by one til there's no more and
stuff them into our vector
std::string word;
while ( Parse >> word )
Words.push_back( word );

Replace the three lines above with this:

std::copy(std::istream_iterator<std::string>(Parse),
// At this point each word is in the vector.

for ( WordVec::iterator it = Words.begin(); it != Words.end();
++it ) std::cout << (*it) << "\n";

Replace the loop with this:

std::copy(Words.begin(), Words.end(),
std::ostream_iterator said:
std::string wait;
std::getline( std::cin, wait );
}

And you get an even more radical standard-library based program!

V
 
J

Jim Langston

Frederik Van Bogaert said:
Jim said:
Frederik Van Bogaert said:
Hi! I've taken my first steps into the world of c++ by trying to write a
text adventure game. Things are proceeding fine, but there's some code
in there that isn't very well coded. More specifically, I use the
following code:

...
string word [4];
size_t pos = action.find(" ");
word[0] = action.substr (0,pos);
if (pos < action.size() - 2)
{
word[1] = action.substr(pos + 1);
}
string word1 [2];

for (int i=1;i<3;i++)
{
pos = word.find(" ");
if (pos == string::npos) goto skippy;
word1[i-1] = word.substr (0,pos);
if (pos < word.size() - 2)
{
word[i+1] = word.substr(pos + 1);
}
word = word1[i-1];
}

skippy:
...

To convert a string called 'action' into the array word[4]. Is there a
way to do this more efficiently?
Thanks


Use. std::stringstream. stringstream will read using >> like std::cin,
stopping on spaces.

Output of following program is:

look
at
the
clock
on
the
wall

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

// typedef is not required, just makes it a little eaiser.
typedef std::vector<std::string> WordVec;

int main()
{
std::string action = "look at the clock on the wall";

WordVec Words;
// Following declares a stringstream Parse and initializes it to the
contents of action
std::stringstream Parse( action );

// Now we read each word out one by one til there's no more and stuff
them into our vector
std::string word;
while ( Parse >> word )
Words.push_back( word );

// At this point each word is in the vector.

for ( WordVec::iterator it = Words.begin(); it != Words.end(); ++it )
std::cout << (*it) << "\n";

std::string wait;
std::getline( std::cin, wait );
}

Thanks! That's exactly what I was looking for :)

PS: Is there some reason you're using "std::" all the time instead of
specifying "using namespace std;" in the beginning of the file as I've
been told to do?


Because I feel that "using namespace std;" defeats the purpose of namespaces
to begin win. Check out the FAQ:

http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
 

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
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top