Jump to content
  • Advertisement
Sign in to follow this  
squimmy

Splitting a string

This topic is 4335 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm reading in a text file which is in the format of 1,0,0,1,0, etc.... each line I read is stored in a string. I am new to c++ and am really not sure how to split each the string so that each number is an entry in an array. What I'm trying to accomplish would be that for the string "1,0,0,1,0" I would have an array like this: nums[0] would be 1 nums[1] would be 0 nums[2] would be 0 nums[3] would be 1 nums[4] would be 0 Something like the c# string.split function would be good. Thanks for any help.

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
not a very efficient way but it should work (haven't tested out)

vector SplitString(const string& str,char separator){
string::size_type lastpos=0,pos=0;
vector ret;
do{
pos=str.find(separator,lastpos+1);
ret.push_back(str.substr(lastpos,pos-lastpos));
lastpos=pos;
}while(pos!=string::npos);
return ret;
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
sorry slight problem

vector<string> SplitString(const string& str,char separator){
string::size_type lastpos=0,pos=0;
vector ret;
do{
pos=str.find(separator,lastpos+1);
ret.push_back(str.substr(lastpos,pos-lastpos));
lastpos=pos;
}while(pos!=string::npos);
return ret;
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
forgot the other one now :P
vector<string> SplitString(const string& str,char separator){
string::size_type lastpos=0,pos=0;
vector<string> ret;
do{
pos=str.find(separator,lastpos+1);
ret.push_back(str.substr(lastpos,pos-lastpos));
lastpos=pos;
}while(pos!=string::npos);
return ret;
}

Share this post


Link to post
Share on other sites
Thank you, but I must be doing something wrong because it isn't working.


vector<string> v;
v = SplitString(line,',');
for(int u = 0;u < v.size();u++){
cout << v.at(u) ;
}
cout << endl;


Surely what is printed should have no commas in it, but I get it with commas

"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
..."


Shouldn't each entry in v not have a comma, but just a number?

Share this post


Link to post
Share on other sites
Try changing the line
lastpos = pos;
to
lastpos = pos + 1;

May be then you'll have to check for 'lastpos' non going greater or equal than 'str.size()' inside the loop. It depends on the way 'find' method handles the situation.

Share this post


Link to post
Share on other sites
If it's always going to be numbers this should work:


#include <vector>
#include <iostream>

void readNumbers(std::istream& in, std::vector<int>& numbers)
{
int num;
in >> num;
while(in.good())
{
numbers.push_back(num);
int >> "," >> num;
}
}




And if not, give boost::tokenizer a try


#include <vector>
#include <string>
#include <iterator>
#include <boost/tokenizer.hpp>

void parseNumbers(const std::string& str, std::vector<std::string>& numbers)
{
boost::char_separator<char> sep(",");
boost::tokenizer< boost::char_separator<char> > tok(str, sep);
std::copy(tok.begin(), tok.end(), std::back_inserter(numbers));
}


Share this post


Link to post
Share on other sites

int counter = 0;
for(int i = 0; i < reader.size(); i++)
{
if(reader != ",")
{
Nums[counter] = reader;
counter++;
}
}

that will work if you only plan on 1 digit numbers

Share this post


Link to post
Share on other sites
Wow, lots of strange ideas here.

OP, you probably want to do the parsing directly as you read the file, instead. The code I will show does handle errors, by reading comma-delimited items into strings (which should always succeed until EOF) and then extracting integers out of those. Trying to parse out commas after the fact is probably more complex than is needed.

That said, if this is a file format you control, and you don't need error checking, then *don't use commas to separate the numbers*. Use whitespace instead. The C++ library streams are highly oriented towards reading whitespace-delimited things.

AP, whywhat got the problem :) This is still pretty ugly stuff to do by hand though. I assume Boost provides something... (in StringAlgo perhaps?)

joanusdmentia, I assume reading from "int" rather than "in" is a typo, but regardless, reading into a string literal like that definitely doesn't do what you want. Also, please get over the silly fear of returning container objects. The pass-non-const-reference approach really only makes sense when you need to return something else anyway, because:

- You can really only get a performance advantage when the caller already had a container sitting around for some reason
- Otherwise, the caller has to jump through more hoops in order to use the function
- And if the caller *did* have that vector, you have to decide if its contents should be cleared first, and if so, on which side.

raptorstrike, you need to compare to ',' rather than "," since you're iterating over characters, and anyway, the ascii value != the numeric value.


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

std::vector<int> readNumbers(std::istream& in) {
std::string token;
std::vector<int> result;
while (std::getline(in, token, ',')) {
int x;
char garbage;
std::stringstream parser(in);
if ((parser >> x) && (parser >> std::ws) && !(parser >> garbage)) {
// if you don't care if there's extra stuff after the number in that
// field, just use 'parser >> x'.
result.push_back(x);
} else {
// error handling here as desired
}
}
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
joanusdmentia, I assume reading from "int" rather than "in" is a typo, but regardless, reading into a string literal like that definitely doesn't do what you want.


Yep, typo. I probably should've tried that code out before posting it, admittadly I haven't really iostreams for parsing before. I was *expecting* the istream to try and read the literal and if the stream contents doesn't match to fail, I guess that that's not the case though [smile]

Quote:
Original post by Zahlman
Also, please get over the silly fear of returning container objects. The pass-non-const-reference approach really only makes sense when you need to return something else anyway, because:

- You can really only get a performance advantage when the caller already had a container sitting around for some reason
- Otherwise, the caller has to jump through more hoops in order to use the function
- And if the caller *did* have that vector, you have to decide if its contents should be cleared first, and if so, on which side.


Good points, it's more a habit than anything else. Would NVRO work with a complex object such as std::vector? Not that performance matters in this case, but there are situations where you really don't want a temporary std::vector of several 1000 objects being constructed.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!