如何将输入从输入流直接插入到集合容器中?
这就是我需要的
while(n--)
{
cin>>s.emplace();
}
假设,我需要获取 n 个输入并将容器名称设置为“s”
while(n--)
{
int x;
cin>>x;
s.emplace(x);
}
这工作正常,但我需要削减这一步。
最佳答案
从 C++20 开始,您可以使用 std::ranges::copy
, std::counted_iterator
, std::istream_iterator
, std::default_sentinel
和 std::inserter
去做吧。 counted_iterator
+ default_sentinel
使其从流中复制 n
个元素。
例子:
#include <algorithm> // ranges::copy
#include <iostream>
#include <iterator> // counted_iterator, default_sentinel, istream_iterator, inserter
#include <set>
#include <sstream> // istringstream - only used for the example
int main() {
// just an example istream:
std::istringstream cin("1 1 2 2 3 3 4 4 5 5");
int n = 5;
std::set<int> s;
std::ranges::copy(
std::counted_iterator(std::istream_iterator<int>(cin), n),
std::default_sentinel,
std::inserter(s, s.end())
);
for(auto v : s) std::cout << v << ' ';
}
输出将只包含 3 个元素,因为流中的前 5 个元素只有 3 个唯一元素:
1 2 3
在 C++20 之前,您可以使用 copy_n
以类似的方式:
std::copy_n(std::istream_iterator<int>(cin), n, std::inserter(s, s.begin()));
警告:如果流中的元素实际上少于 n
个,则两个版本都将具有 undefined behavior .在交付您想要的内容时,流是出了名的不可预测,而 copy_n
使得错误检查变得非常困难。
为了安全起见,您可以创建一个counting_istream_iterator
以使用std::copy
从流中复制最多n
个元素|像这样:
std::copy(counting_istream_iterator<foo>(cin, n),
counting_istream_iterator<foo>{},
std::inserter(s, s.end()));
基于 std::istream_iterator
,这样的迭代器可能看起来像这样:
template<class T,
class CharT = char,
class Traits = std::char_traits<CharT>,
class Distance = std::ptrdiff_t>
struct counting_istream_iterator {
using difference_type = Distance;
using value_type = T;
using pointer = const T*;
using reference = const T&;
using iterator_category = std::input_iterator_tag;
using char_type = CharT;
using traits_type = Traits;
using istream_type = std::basic_istream<CharT, Traits>;
counting_istream_iterator() : // end iterator
isp(nullptr), count(0) {}
counting_istream_iterator(std::basic_istream<CharT, Traits>& is, size_t n) :
isp(&is), count(n + 1)
{
++*this; // read first value from stream
}
counting_istream_iterator(const counting_istream_iterator&) = default;
~counting_istream_iterator() = default;
reference operator*() const { return value; }
pointer operator->() const { return &value; }
counting_istream_iterator& operator++() {
if(count > 1 && *isp >> value) --count;
else count = 0; // we read the number we should, or extraction failed
return *this;
}
counting_istream_iterator operator++(int) {
counting_istream_iterator cpy(*this);
++*this;
return cpy;
}
bool operator==(const counting_istream_iterator& rhs) const {
return count == rhs.count;
}
bool operator!=(const counting_istream_iterator& rhs) const {
return !(*this == rhs);
}
private:
std::basic_istream<CharT, Traits>* isp;
size_t count;
T value;
};
https://stackoverflow.com/questions/69900996/