0

What is the fastest way to seperate these into 3 ints? I feel like this should be possible in one line but the closest I can find is this:

#include <ostream> 
#include <iostream> 
#include <string> 
#include <sstream> 
#include <vector> 
 
std::vector<int> extract_ints(std::string const& input_str) 
{ 
    std::vector<int> ints; 
    std::istringstream input(input_str); 
 
    std::string number; 
    while (std::getline(input, number, ':')) 
    { 
        std::istringstream iss(number); 
        int i; 
        iss >> i; 
        ints.push_back(i); 
    } 
 
    return ints; 
} 
int main() 
{ 
    typedef std::vector<int> ints_t; 
 
    ints_t const& ints = extract_ints("3254:23-45"); 
    for (ints_t::const_iterator i = ints.begin(), i_end = ints.end(); i != i_end; ++i) 
        std::cout << *i << std::endl; 
 
    return 0; 
} 

Found here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/411271cd-5e8a-46f9-a78b-a49a347741c0/comma-delimited-string-to-integer-array?forum=vcgeneral

And the link to that in action is here: https://godbolt.org/z/8sP9vvqfv but first of all it will only seperate between ':'s so far, not sure how to expand to ':'s and '-'s also. But secondly, this just seems overly complicated... Is this really the best method to do this?

Thanks

twoface
  • 51
  • 7
  • 2
    Expanding on that: `int a, b, c; char colon, dash; if (iss >> a >> colon >> b >> dash >> c && colon == ':' && dash == '-') return {a, b, c}; else return {};` – paddy May 10 '21 at 11:19
  • Asking for "best way" is asking for an opinion, which is off-topic for stackoverflow. Can you reframe your question based on facts and technical terms, instead? – Sam Varshavchik May 10 '21 at 11:25

1 Answers1

0

how to expand to ':'s

You read a char from input and check if it's a :. For example:

#include <iostream>
#include <exception>
#include <vector>
#include <sstream>
#include <exception>
std::vector<int> extract_ints(std::string const& input_str) 
{ 
    std::vector<int> r(3); 
    std::istringstream iss(input_str); 
    char c1;
    char c2;
    if (!(
         iss >> r.at(0) >> c1 >> r.at(1) >> c2 >> r.at(2) &&
         c1 == ':' && c2 == '-' &&
         !(iss >> c1)  // test if we are at EOF
    )) {
        throw std::runtime_error("Och och, invalid string");
    }
    return r;
}
int main() {
    for (auto&& i : extract_ints("3254:23-45")) {
        std::cout << i << '\n';
    }
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Nice, this works exactly as intended, and it even a little cleaner than the given code. I am very tempted to mark this as the answer straight away now, are there any issues with speed here you can think of? I imagine this is the quickest way to perform this operation? – twoface May 10 '21 at 11:29
  • I follow first rule of [rules of optimization](https://wiki.c2.com/?RulesOfOptimizationClub). I do not care about speed of this code, because I have not profiled it. Ie. I very much doubt there is any point in optimizing it. Anyway - `are there any issues with speed` - yes, it's C++, you are using `vector` and `istringstream`, both are allocating dynamic memory. Do not use them at all (_if_ this function has been profiled to be bottleneck...), `istringstream` is (I think) also locale dependent. If you want speed, I would go with writing all scanning functions yourself. – KamilCuk May 10 '21 at 11:32