简体   繁体   中英

vector of string to istringstream

I want to populate a istringstream object with content from vector of strings. Is there an elegant way to do this? I am doing the following now, which is not nice:

vector<string> vec = {"apple", "banana", "dog", "cat"};
string one_str;
for (string s: vec) {
    one_str += s + " ";
}
istringstream iss(one_str);

Note that I want to populate istringstream and not stringstream or ostringstream

You can't make an istringstream read from any external source: it always makes a copy, even of a single string. You can, however, make a stream that reads from any data source by making your own streambuf class and making an istream from a pointer to an instance of it. A minimal version needs only one method overridden:

#include<streambuf>
#include<string>
#include<vector>

struct stringsbuf : std::streambuf {
  stringsbuf(const std::string *b,const std::string *e) : ss(b),se(e) {}
  stringsbuf(const std::vector<std::string> *v) : // pointer vs. temporaries
    ss(&v->front()),se(ss+v->size()) {}

  int_type underflow() override {
    while(ss!=se) {
      auto &s=*ss++;
      if(s.empty()) continue;
      char *p=const_cast<char*>(s.data());
      setg(p,p,p+s.size());
      return *p;
    }
    return traits_type::eof();
  }

private:
  const std::string *ss,*se;   // next string to load, and past-the-end string
};

This could of course be made more efficient and featureful by adding one or more of xsgetn , seekoff , seekpos , and showmanyc . It could also be made generic (not only on character type, but also by accepting any string -valued iterators).

The elegance here lies in the fact that no concatenated string is ever constructed (except perhaps by the client that reads from an istream based on a stringsbuf ).

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