【问题标题】:How to convert from std::vector<float> to std::istream?如何从 std::vector<float> 转换为 std::istream?
【发布时间】:2021-04-12 14:36:48
【问题描述】:

我有一个 std::vector 并且该函数需要一个 std::istream:

callMe(std::istream& is)

进行转换的最佳方法是什么?还有比这更聪明的吗?

std::stringstream sstr;
for(int i = 0; i < myVector.size(); ++i) {
    sstr << myVector[i] << " ";
}
std::istringstream istr{sstr.str()};
callMe(istr);

编辑:感谢到目前为止的建议! 更新代码:

std::stringstream sstr;
for(const float& val : myVector) {
    sstr << val << " ";
}
callMe(sstr);

【问题讨论】:

  • 不应该需要std::istringstream istr{sstr.str()};std::stringstreamis-astd::istream。不过,可能不得不倒带。
  • for(int i = 0; i &lt; myVector.size(); ++i) 是一个基于范围的好地方。 for(const auto &amp; val: myVector.size() { sstr &lt;&lt; val &lt;&lt; " "; } 也可以使用 中的 for_each,但我认为不会更快或更清晰。
  • 如果不知道为什么callMe()istream 开头,以及它如何从istream 实际读取值(格式化读取与二进制读取),真的很难回答这个问题。将 vector 转换为 string 包裹在 (i)stringstream可能会或可能不会正常工作。我们需要更多关于 callMe() 实际期望输入的详细信息,然后才能明确回答。
  • 您可能想尝试修复它,以便在最后一个元素之后没有不必要的空间。
  • @Remy Lebeau: callMe() 使用运算符>>再次提取值,例如float a0, a1, a2; is &gt;&gt; a0 &gt;&gt; a1 &gt;&gt; a2;。但是,值的数量(a0、a1、...)可能会有所不同。

标签: c++ istream


【解决方案1】:

问题在于std::istream 本质上是基于字符的。如果您想继续使用callMe(std::istream&amp; is) 作为接口,您必须将myVector 的每个元素转换为字符,然后再转换回来。如果您想坚持使用此选项,我个人认为ostream_iterator 是一个优雅的解决方案:

copy(begin(data), end(data), std::ostream_iterator<float>(sstr));

完整示例:

void callMeStream(std::istream &is)
{
  float f1;
  is >> f1;
  std::cout << "Stream: " << f1 << std::endl;
}

// ...

std::vector<float> data = {3.5, 1.5, 2.5 /* ... */};

std::stringstream sstr;
copy(begin(data), end(data), std::ostream_iterator<float>(sstr));
callMeStream(sstr); // Output: "Stream: 3.51"

如果您愿意更改callMe的签名,则可以避免这种转换:

template <class T>
void callMeTemplate(T &is)
{
  float f1;
  is >> f1;
  std::cout << "Template: " << f1 << std::endl;
}

#define NO_ELEMENT -1.0;

class data_wrapper
{
  std::vector<float>::const_iterator current;
  const std::vector<float>::const_iterator last;

public:
  data_wrapper(const std::vector<float> &data) : current(begin(data)), last(end(data)) {}

  data_wrapper &operator>>(float &value)
  {
    if (last == current)
    {
      value = NO_ELEMENT;
    }
    else
    {
      value = *current++;
    }
    return *this;
  }
};

// ...
data_wrapper wrapper(data);
callMeTemplate(wrapper); // Output: "Template: 3.5"

在第二个示例中,float 值永远不会转换为字符序列,并且可以同时接受 data_wrapperstd::istream 类型。当然,如果您愿意完全更改callMe 的签名,您不妨将其更改为直接接受开始/结束迭代器范围或vector

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 2019-02-28
    • 1970-01-01
    相关资源
    最近更新 更多