如何将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;
    }
}

当前回答

一个更简单的方法是使用标准复制算法:

#include <iostream>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator
#include <vector>

int main() {
    /* Set up vector to hold chars a-z */
    std::vector<char> path;
    for (int ch = 'a'; ch <= 'z'; ++ch)
        path.push_back(ch);

    /* Print path vector to console */
    std::copy(path.begin(), path.end(), std::ostream_iterator<char>(std::cout, " "));

    return 0;
}

ostream_iterator被称为迭代器适配器。它被模板化在要打印到流的类型上(在本例中为char)。Cout(又名控制台输出)是我们想要写入的流,空格字符(" ")是我们想要打印在存储在vector中的每个元素之间的内容。

这个标准算法非常强大,其他算法也是如此。标准库提供的强大功能和灵活性使它如此出色。想象一下:您可以用一行代码将一个向量打印到控制台。您不必处理分隔符的特殊情况。您不需要担心for循环。标准库为您完成了这一切。

其他回答

c++ 11

for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';

for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';

对于想要没有循环的一行程序的人:

我不敢相信没有人知道这一点,但也许是因为更像c的方法。不管怎样,在没有循环的情况下,假设std::vector<char>是空终止的,在一行程序中是完全安全的:

std::vector<char> test { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0' };
std::cout << test.data() << std::endl;

但为了安全起见,我会把它包装在ostream操作符中,就像@Zorawar建议的那样:

template <typename T>std::ostream& operator<< (std::ostream& out, std::vector<T>& v)
{
    v.push_back('\0'); // safety-check!
    out << v.data();
    return out;
}

std::cout << test << std::endl; // will print 'Hello, world!'

我们可以通过使用printf来实现类似的行为:

fprintf(stdout, "%s\n", &test[0]); // will also print 'Hello, world!'

注意:

重载的ostream操作符需要接受非const的vector。这可能会使程序不安全或引入不可用的代码。此外,由于添加了空字符,可能会发生std::vector的重新分配。因此,使用带有迭代器的for循环可能会更快。

在c++ 11中,你现在可以使用一个基于范围的for循环:

for (auto const& c : path)
    std::cout << c << ' ';

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表达式的强大功能——您可以使用这种方法做更多的事情,而不仅仅是打印向量。

如果boost是一个选项,那么你可以使用boost::algorithm::join。例如,打印std::string的向量:

#include <boost/algorithm/string/join.hpp>

std::vector<std::string> vs { "some", "string", "vector" };
std::cout << boost::algorithm::join(vs, " | ") << '\n';

对于其他类型的向量,首先需要转换为字符串

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>

int main()
{
    using boost::adaptors::transformed;
    using boost::algorithm::join;

    // Generate the vector
    std::vector<int> vi(10);
    std::iota(vi.begin(), vi.end(), -3);

    // Print out the vector
    std::cout << join(vi |
                 transformed(static_cast<std::string(*)(int)>(std::to_string)),
                 ", ")
              << '\n';
}

Godbolt演示