Splitting String

I am trying to split a string like "8573656.5465467.5435325.3253255" into separate int variables each containing the group of numbers between the dots. Someone told me this would work but I have no clue what it is. Could someone explain it maybe or give a better methord.
1
2
3
4
5
6
7
8
9
10
istringstream ins(YourStringName); 
std::vector<long> vectorLong;  
char dot; // A character to retrieve the '.'. 
long temp;   
while(ins >> temp) {    
ins >> dot; // Retrieve the dot and throw it away.   
 vectorLong.push_back(temp); // Store the number in the vector. } 


Last edited on
What part is it that you have problem with? std::istringstream is a stream class that can be used to extract data from a file. You can use it the same way as other input streams like std::ifstream and std::cin. YourStringName is the string with the numbers and the dots. ins >> temp reads the next integer value and stores it into temp. The loop will continue loop until it fails to read an integer value. ins >> dot; reads the next char that is not a whitespace char and stores it in dot. The code doesn't check if dot == '.' so any other char that is not a digit and not a whitespace will work as a separator. vectorLong.push_back(temp); adds the value of temp to the end of vectorLong.
Last edited on
It works fine, although it would be nice to test if dot == '.' before throwing it away so you could spot errors.

Other ways to do this:

1. tell istringstream that '.' is whitespace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <sstream>
#include <locale>
#include <vector>
#include <iterator>
struct dot_ws : std::ctype<char> {
    static const mask* make_table() {
        static std::vector<mask> v(classic_table(), classic_table() + table_size);
        v['.'] |= space;  // dot will be classified as whitespace
        return &v[0];
    }
    dot_ws(std::size_t refs = 0) : ctype(make_table(), false, refs) {}
};
int main()
{
    std::string YourStringName = "8573656.5465467.5435325.3253255";

    std::istringstream ins(YourStringName);
    ins.imbue(std::locale(ins.getloc(), new dot_ws())); // now dots are whitespace

    std::istream_iterator<long> beg(ins), end; // so you can range-construct
    std::vector<long> vectorLong(beg, end);
}

demo: http://ideone.com/Zeisc

2. use boost

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <sstream>
#include <vector>
#include <boost/tokenizer.hpp>
#include <string>
int main()
{
    std::string YourStringName = "8573656.5465467.5435325.3253255";
    std::vector<long> vectorLong;
    boost::tokenizer<> tok(YourStringName);
    for(auto i = tok.begin(); i != tok.end(); ++i)
        vectorLong.push_back(std::stol(*i));
}

demo: http://ideone.com/MPWwb

or in many other ways, depending on what do you consider "better"
getline takes an optional delimiter to tokenize a stream. Just feed the string into a stringstream first. Once again, there are many ways but this one is pretty clear and it is standard.

1
2
3
4
5
6
7
8
#include <iostream>
#include <sstream>
//...
stringstream ss( "8573656.5465467.5435325.3253255" );
string token;
while( getline( ss, token, '.' ) ) {
    cout << token << endl;
}


http://cplusplus.com/reference/iostream/stringstream/
http://cplusplus.com/reference/string/getline/
Topic archived. No new replies allowed.