如何打印 std::vector
的内容到屏幕?
实现以下 operator<<
的解决方案也会很好:
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;
}
}
您可以使用迭代器:
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
如果要在 for 循环中修改 vector 的内容,请使用
iterator
而不是
const_iterator
.
但关于这一点还有很多可以说的。如果你只是想要一个你可以使用的答案,那么你可以停在这里;否则,请继续阅读。
自动 (C++11)/typedef/类型别名 (C++11)
这不是另一种解决方案,而是对上述
iterator
的补充解决方案。如果您使用的是 C++11 标准(或更高版本),那么您可以使用
auto
提高可读性的关键字:
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
但是
i
的类型将是非常量的(即,编译器将使用
std::vector<char>::iterator
作为
i
的类型)。
在这种情况下,您不妨使用
typedef
,这也带来了它自己的好处(我不会在这里详述):
typedef std::vector<char> Path; // 'Path' now a synonym for the vector
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
C++11 还引入了一个类型别名,它与 typedef 做同样的工作,你可能会发现比使用 typedef 更具可读性:
using Path = std::vector<char>; // C++11 onwards only
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
柜台
当然,您可以使用整数类型来记录您在
for
中的位置。环形:
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
如果您打算这样做,最好使用容器的成员类型(如果它们可用且合适)。
std::vector
有一个名为
size_type
的成员类型对于此作业:它是
size
返回的类型方法。
// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
为什么不直接在
iterator
上使用它解决方案?对于简单的情况,您也可以,但重点是
iterator
是一个对象,旨在为更复杂的对象完成这项工作,而该解决方案并不理想。
基于范围的 for 循环 (C++11)
见
Jefffrey's solution .在 C++11(及更高版本)中,您可以使用新的基于范围的
for
循环,看起来像这样:
for (auto i: path)
std::cout << i << ' ';
自
path
是项的 vector (明确表示
std::vector<char>
),对象
i
是 vector 项的类型(即,明确地,它是类型
char
)。对象
i
有一个值是
path
中实际项目的拷贝目的。因此,对
i
的所有更改在循环中不保留在
path
中本身。此外,如果您想强制执行您不想更改
i
的复制值的事实。在循环中,你可以强制类型为
i
成为
const char
像这样:
for (const auto i: path)
std::cout << i << ' ';
如果您想修改
path
中的项目,您可以使用引用:
for (auto& i: path)
std::cout << i << ' ';
即使你不想修改
path
, 如果对象的复制成本很高,则应使用 const 引用而不是按值复制:
for (const auto& i: path)
std::cout << i << ' ';
std::copy (C++11)
见
Joshua's answer .您可以使用 STL 算法
std::copy
将 vector 内容复制到输出流上。如果您对它感到满意,这是一个优雅的解决方案。应该鼓励更多地熟悉 STL 算法,它们提供了许多初学者可能会陷入自我改造的功能。阅读 Joshua 的帖子了解更多信息。
重载 std::ostream::operator<<
见
Chris's answer ,这更像是对其他答案的补充,因为您仍然需要在重载中实现上述解决方案之一。在他的例子中,他在
for
中使用了一个计数器。环形。例如,这就是您可以快速使用
Joshua's solution 的方法。 :
#include <iterator> // needed for std::ostram_iterator
template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
if ( !v.empty() ) {
out << '[';
std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
out << "\b\b]";
}
return out;
}
使用任何其他解决方案应该同样简单。
结论
此处介绍的任何解决方案都将起作用。这取决于您和哪个代码是“最好的”。任何比这更详细的内容可能最好留给另一个可以正确评估利弊的问题;但与往常一样,用户偏好将始终发挥作用:所提供的解决方案没有一个是错误的,但对于每个编码员来说,有些解决方案看起来会更好。
附录
这是我较早发布的解决方案的扩展解决方案。由于该帖子不断受到关注,我决定对其进行扩展并引用此处发布的其他优秀解决方案。我原来的帖子有一句话提到,如果你打算在
for
中修改你的 vector 。循环然后
std::vector
提供了两种方法访问元素:
std::vector::operator[]
不做边界检查,和
std::vector::at
它确实执行边界检查。换句话说,
at
如果您尝试访问 vector 之外的元素,则会抛出
operator[]
不会。我最初只是添加了这条评论,目的是为了提及如果有人还没有知道可能有用的东西。我现在看不出有什么区别。因此,本附录。
我是一名优秀的程序员,十分优秀!