如何将std::vector的内容打印到屏幕上?


实现以下操作符<<的解决方案也很好:

template<container C, class T, String delim = ", ", String open = "[", String close = "]">
std::ostream & operator<<(std::ostream & o, const C<T> & x)
{
  // ... What can I write here?
}

以下是目前为止我所做的,没有单独的函数:

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;

int main()
{
    ifstream file("maze.txt");
    if (file) {
        vector<char> vec(istreambuf_iterator<char>(file), (istreambuf_iterator<char>()));
        vector<char> path;
        int x = 17;
        char entrance = vec.at(16);
        char firstsquare = vec.at(x);
        if (entrance == 'S') { 
            path.push_back(entrance); 
        }
        for (x = 17; isalpha(firstsquare); x++) {
            path.push_back(firstsquare);
        }
        for (int i = 0; i < path.size(); i++) {
            cout << path[i] << " ";
        }
        cout << endl;
        return 0;
    }
}

当前回答

从第一个BoostCon(现在叫CppCon)出来,我和另外两个人致力于一个库来实现这一点。主要的问题是需要扩展命名空间std。这对boost库来说是不可能的。

不幸的是,到代码的链接不再工作,但您可能会在讨论中发现一些有趣的花絮(至少那些没有讨论如何命名它!)

http://boost.2283326.n4.nabble.com/explore-Library-Proposal-Container-Streaming-td2619544.html

其他回答

您可以使用{fmt}库打印容器以及范围和元组。例如:

#include <vector>
#include <fmt/ranges.h>

int main() {
  auto v = std::vector<int>{1, 2, 3};
  fmt::print("{}", v);
}

打印

[1, 2, 3]

到标准输出(godbolt)。

我不建议对标准容器重载操作符<<,因为它可能会引入ODR违规。

声明:我是{fmt}的作者。

template <typename T>
std::ostream& operator<<( std::ostream& ostrm, const std::vector<T>& vec ){
    ostrm << "[";
    for( int j = 0, n = vec.size(); j < n; ++j ){
        ostrm << " " << vec[ j ] << " ,"[ j < n - 1 ];
    }
    return ostrm << "]";
}

[1, 2, 3, 4]

你可以使用std::experimental::make_ostream_joiner:

#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
 
int main()
{
    std::vector<int> vi(12);
    std::iota(vi.begin(), vi.end(), -5);
    std::cout << "Int vector:\n";
    std::copy(std::begin(vi),
              std::end(vi),
              std::experimental::make_ostream_joiner(std::cout, ", "));

    std::cout <<"\nString vector:\n[";
    std::vector<std::string> vs { "some", "string", "vector" };
    std::copy(std::begin(vs),
              std::end(vs),
              std::experimental::make_ostream_joiner(std::cout, "] - ["));
    std::cout << "]\n";
}

Godbolt演示

for_each + lambda表达式怎么样:

#include <vector>
#include <algorithm>
// ...
std::vector<char> vec;
// ...
std::for_each(
              vec.cbegin(),
              vec.cend(),
              [] (const char c) {std::cout << c << " ";} 
              );
// ...

当然,对于这个具体任务,基于范围的for是最优雅的解决方案,但它也提供了许多其他可能性。

解释

for_each算法接受一个输入范围和一个可调用对象,在范围的每个元素上调用该对象。输入范围由两个迭代器定义。可调用对象可以是一个函数、一个函数指针、一个重载()操作符的类的对象,或者在本例中是一个lambda表达式。此表达式的形参与vector中元素的类型匹配。

这个实现的美妙之处在于lambda表达式的强大功能——您可以使用这种方法做更多的事情,而不仅仅是打印向量。

我写了一个操作符<<,它输出任何可迭代对象,包括自定义容器、标准容器和具有已知边界的数组。需要c++ 11:

template<typename Container, typename = 
    std::enable_if_t<std::is_same_v<std::void_t<
        decltype(static_cast<typename Container::const_iterator (*)(const Container&)>(&std::cbegin)),
        decltype(static_cast<typename Container::const_iterator (*)(const Container&)>(&std::cend))>, void>
        && !std::is_same_v<std::string, Container>>>
std::ostream& operator<<(std::ostream& out, const Container &vec)
{
    std::cout << "[ ";
    for(const auto& t: vec){
        std::cout << t << " ";
    }
    std::cout << "] ";
    return out;
}