1

I have the following struct:

 struct msg_latency{
        double time;
        string data;
    };

I have a vector of strings which contains strings like: "2344.5435345 hello world\n:"

I have to iterate the vector of the strings and convert each string to msg_latency struct.

 vector<msg_latency> vec_msg

    convert_str2struct(vector<string> str_vec, vector<msg_latency> msg_vec)
    {
        vector<string>::iterator msg_it;

        for(msg_it=str_vec.begin(); msg_it!= str_vec.end(); ++msg_it)
        {
            ///TODO
        }
    }

While in the todo I want to write something like:

msg_vec[i].time= *msg_it.substr(0, *msg_it.find(" "));
msg_vec[i].data= *msg_it;

How can I initialize the msg_vec as I describred above?

Can I do something like (in the TODO): msg_vec.push_back({*msg_it.substr(0, *msg_it.find(" ")), *msg_it})?

sara8d
  • 403
  • 4
  • 17
  • 32
  • 2
    Use a `std::istringstream` to parse numbers from a `std::string`. – πάντα ῥεῖ Jun 19 '16 at 16:13
  • 4
    So you want to [*transform*](http://en.cppreference.com/w/cpp/algorithm/transform) one vector into another? – Some programmer dude Jun 19 '16 at 16:14
  • @Joachim Pileborg- yes. – sara8d Jun 19 '16 at 16:33
  • 2
    Then the [`std::transform`](http://en.cppreference.com/w/cpp/algorithm/transform) function would be a good start. Another would be to figure out how to split the string in the source vector into a `double` and a `string` (where @πάνταῥεῖ suggestion about [`std::istringstream`](http://en.cppreference.com/w/cpp/io/basic_istringstream) is a good start). – Some programmer dude Jun 19 '16 at 18:15

1 Answers1

1

As suggested in comments, this is an ideal application for std::transform and std::istringstream.

If I understand your string format you can use std::getline to read the remaining part of string after reading the double:

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

msg_latency
convert(const std::string& str) {
    msg_latency msg;
    std::istringstream ss(str);
    ss >> msg.time >> std::ws;  // read double and whitespace separator         
    getline(ss, msg.data);      // read the rest of the string
    return msg;
}

std::vector<msg_latency>
convert_str2struct(const std::vector<std::string>& str_vec) {
     std::vector<msg_latency> ret(str_vec.size());
     std::transform(str_vec.begin(), str_vec.end(), ret.begin(), convert);
     return ret;
}

int main() {
    auto vec_str = std::vector<std::string>{"2344.5435345 hello world\n", "42.0 foo\n"};

    auto vec_msg = convert_str2struct(vec_str);

    for (const auto& msg : vec_msg) {
        std::cout << msg.time << "\n";
        std::cout << msg.data << "\n";
        std::cout << "\n";
    }
}

Live demo.

Community
  • 1
  • 1
Chris Drew
  • 14,926
  • 3
  • 34
  • 54
  • There must be something simple than this. Can't I just do the following (in the TODO): msg_vec.push_back({*msg_it.substr(0, *msg_it.find(" ")), *msg_it})? – sara8d Jun 21 '16 at 08:15
  • @sara8d If you have your own solution I suggest you post it as an answer and let people evaluate it but I don't see how that is going to work. It doesn't look that simple either. – Chris Drew Jun 21 '16 at 08:19
  • @sara8d Note you could use my `convert` function in the "TODO" like: `msg_vec.push_back(convert(*msg_it));` It is just that I think using `std::transform` is clearer and could be faster. – Chris Drew Jun 21 '16 at 10:09
  • Note that this solution requires first creating the `ret` vector with `str_vec.size()` default constructed `msg_latency` objects only to have them overwritten by the `std::transform` on the next line. Thus a total of 2 * `str_vec.size()` objects are constructed. Instead, you could initialize `ret` empty, do a `ret.reserve(str_vec.size())`, and use `std::back_inserter(ret.begin())` as iterator to `std::transform` instead. – AVH Jun 21 '16 at 11:50
  • 1
    @Darhuuk I [measured it](http://melpon.org/wandbox/permlink/jgOrFG9HCk9OYlQL) and I couldn't see a measurable difference in performance. I think computers are pretty fast at zeroing out vectors of PODs, the compiler may even be smart enough to optimize that step out (see [this](http://stackoverflow.com/a/26278335/3422652) answer). Also, although `back_inserter` doesn't have to reallocate it might still need to check if it *should* reallocate. – Chris Drew Jun 21 '16 at 15:22
  • 1
    @Chris Drew Fair enough. Just figured I'd mention it in case the technique you proposed is used with "heavy" objects. – AVH Jun 21 '16 at 15:30