简体   繁体   中英

Split a string of positive/negative integers by space

I have the following string:

1 -2 -8 4 51

I would like to get a vector with 5 elements, each of them corresponding to the 5 numbers in the string. Basically, I'd like to split the above string by space as a delimiter.

I've found a lot of questions like this on Stack Overflow but so far any of them is able to get neither the first "1" nor the last one (from 51 ). My code is the following:

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

using namespace std;

std::vector<std::string> split(std::string str)
{
    std::string buf; 
    std::stringstream ss(str); 
    vector<std::string> tokens; 

    while (ss >> buf)
        tokens.push_back(buf);
    return tokens;
}

int main()
{

    std::string temps = "1 -2 -8 4 51";

    std::vector<std::string> x = split(temps);
    for (int j = 0; j < x.size(); j++){
        cout << x[j] << endl;    
    }
}

My output is the following:

-2
-8
4
5

As you can see, the first and the last 1 are skipped. I'm very new to C++ (I've been maybe too much used to the built-in functions .split() of other languages) but I can't see anything wrong on my above code. Can anyone please help me understanding what I'm doing wrong?

The code you showed works fine in general. The output is as expected, so the problem has to be outside of the code you showed.

However, note that your vector will contain std::string values, not int values. Also, you should consider using std::istringstream for input instead of using std::stringstream .

If you want a vector of integers, try this instead:

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

std::vector<int> split(const std::string &str)
{
    int num; 
    std::istringstream iss(str); 
    std::vector<int> tokens; 

    while (iss >> num)
        tokens.push_back(num);

    return tokens;
}

int main()
{
    std::string temps = "1 -2 -8 4 51";

    std::vector<int> x = split(temps);
    for (int j = 0; j < x.size(); j++) {
        std::cout << x[j] << std::endl;
    }

    return 0;
}

You could then make split() use std::istream_iterator and std::back_inserter instead of a manual loop, eg:

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

std::vector<int> split(const std::string &str)
{
    std::istringstream iss(str); 
    std::vector<int> tokens; 

    std::copy(
        std::istream_iterator<int>(iss),
        std::istream_iterator<int>(),
        std::back_inserter(tokens)
    );

    return tokens;
}

int main()
{
    std::string temps = "1 -2 -8 4 51";

    std::vector<int> x = split(temps);
    for (int j = 0; j < x.size(); j++) {
        std::cout << x[j] << std::endl;
    }

    return 0;
}

And then you could make `split() be a template function so it can return a vector of different types depending on what you want from the input string, eg:

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

template<typename T>
std::vector<T> split(const std::string &str)
{
    std::istringstream iss(str); 
    std::vector<T> tokens; 

    std::copy(
        std::istream_iterator<T>(iss),
        std::istream_iterator<T>(),
        std::back_inserter(tokens)
    );

    return tokens;
}

int main()
{
    std::string temps = "1 -2 -8 4 51";

    std::vector<int> x = split<int>(temps);
    for (int j = 0; j < x.size(); j++) {
        std::cout << x[j] << std::endl;
    }

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM