C++ 如何打印出向量的内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10750057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to print out the contents of a vector?
提问by forthewinwin
I want to print out the contents of a vector in C++, here is what I have:
我想在 C++ 中打印出向量的内容,这是我所拥有的:
#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;
}
}
How do I print the contents of the vector to the screen?
如何将矢量的内容打印到屏幕上?
回答by Zorawar
Purely to answer your question, you can use an iterator:
纯粹为了回答您的问题,您可以使用迭代器:
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
If you want to modify the vector's contents in the for loop, then use iterator
rather than const_iterator
.
如果要在 for 循环中修改向量的内容,请使用iterator
而不是const_iterator
。
But there's lots more that can be said about this. If you just want an answer you can use, then you can stop here; otherwise, read on.
但关于这一点还有很多可以说的。如果你只是想要一个你可以使用的答案,那么你可以停在这里;否则,请继续阅读。
auto (C++11)/typedef
自动 (C++11)/typedef
This is not another solution, but a supplement to the above iterator
solution. If you are using the C++11 standard (or later), then you can use the auto
keyword to help the readability:
这不是另一种解决方案,而是对上述iterator
解决方案的补充。如果您使用的是 C++11 标准(或更高版本),那么您可以使用auto
关键字来帮助提高可读性:
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
But the type of i
will be non-const (i.e., the compiler will use std::vector<char>::iterator
as the type of i
).
但是 的类型i
将是非常量的(即,编译器将std::vector<char>::iterator
用作 的类型i
)。
In this case, you might as well just use a typedef
(not restricted to C++11, and veryuseful to use anyway):
在这种情况下,您不妨只使用一个typedef
(不限于 C++11,而且无论如何使用都非常有用):
typedef std::vector<char> Path;
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
counter
柜台
You can, of course, use a integer type to record your position in the for
loop:
当然,您可以使用整数类型来记录您在for
循环中的位置:
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
If you are going to do this, it's better to use the container's member types, if they are available and appropriate. std::vector
has a member type called size_type
for this job: it is the type returned by the size
method.
如果您打算这样做,最好使用容器的成员类型(如果它们可用且合适)。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] << ' ';
Why not just use this over the iterator
solution? For simple cases you might as well, but the point is that the iterator
class is an object designed to do this job for more complicated objects where this solution is not going to be ideal.
为什么不直接在iterator
解决方案上使用它?对于简单的情况,您也可以,但重点是iterator
该类是一个对象,旨在为更复杂的对象完成这项工作,而这种解决方案并不理想。
range-based for loop (C++11)
基于范围的 for 循环 (C++11)
See Jefffrey's solution. In C++11 (and later) you can use the new range-based for
loop, which looks like this:
请参阅Jefffrey 的解决方案。在 C++11(及更高版本)中,您可以使用新的基于范围的for
循环,如下所示:
for (auto i: path)
std::cout << i << ' ';
Since path
is a vector of items (explicitly std::vector<char>
), the object i
is of type of the item of the vector (i.e., explicitly, it is of type char
). The object i
has a value that is a copy of the actual item in the path
object. Thus, all changes to i
in the loop are not preserved in path
itself. Additionally, if you would like to enforce the fact that you don't want to be able to change the copied value of i
in the loop, you can force the type of i
to be const char
like this:
由于path
是项的向量(明确地std::vector<char>
),因此对象i
是向量项的类型(即,明确地,它的类型是char
)。该对象i
具有一个值,该值是path
对象中实际项目的副本。因此,i
循环中的所有更改都不会保留在path
自身中。此外,如果您想强制执行,你不希望能够改变的复制价值的事实,i
在循环中,你可以强制的类型i
是const char
这样的:
for (const auto i: path)
std::cout << i << ' ';
If you would like to modify the items in path
, you can use a reference:
如果您想修改 中的项目path
,可以使用参考:
for (auto& i: path)
std::cout << i << ' ';
and even if you don't want to modify path
, if the copying of objects is expensive you should use a const reference instead of copying by value:
即使您不想修改path
,如果对象的复制成本很高,您也应该使用 const 引用而不是按值复制:
for (const auto& i: path)
std::cout << i << ' ';
std::copy
标准::复制
See Joshua's answer. You can use the STL algorithm std::copy
to copy the vector contents onto the output stream. This is an elegant solution if you are comfortable with it (and besides, it is veryuseful, not just in this case of printing the contents of a vector).
见约书亚的回答。您可以使用 STL 算法std::copy
将矢量内容复制到输出流上。如果您对它感到满意,这是一个优雅的解决方案(此外,它非常有用,不仅仅是在打印矢量内容的情况下)。
std::for_each
std::for_each
See Max's solution. Using std::for_each
is overkill for this simple scenario, but it is a very useful solution if you wanted to do more than just printing to screen: using std::for_each
allows you to do any(sensible) operation on the vector contents.
请参阅Max 的解决方案。std::for_each
对于这个简单的场景来说,使用是过度的,但如果你想做的不仅仅是打印到屏幕,它是一个非常有用的解决方案:使用std::for_each
允许你对矢量内容进行任何(合理的)操作。
overload ostream::operator<<
重载 ostream::operator<<
See Chris's answer, this is more a complement to the other answers since you will still need to implement one of the solutions above in the overloading. In his example he used a counter in a for
loop. For example, this is how you could quickly use Joshua's solution:
请参阅Chris 的回答,这更像是对其他答案的补充,因为您仍然需要在重载中实施上述解决方案之一。在他的例子中,他在for
循环中使用了一个计数器。例如,您可以通过以下方式快速使用Joshua 的解决方案:
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;
}
Usage of any of the other solutions should be straightforward.
使用任何其他解决方案应该很简单。
conclusion
结论
Any of the solutions presented here will work. It's up to you and the code on which one is the "best". Anything more detailed than this is probably best left for another question where the pros/cons can be properly evaluated; but as always user preference will always play a part: none of the solutions presented are wrong, but some will look nicer to each individual coder.
此处介绍的任何解决方案都将起作用。这取决于您和哪个代码是“最好的”。任何比这更详细的内容可能最好留给另一个可以正确评估利弊的问题;但与往常一样,用户偏好将始终发挥作用:所提供的解决方案没有一个是错误的,但对于每个编码员来说,有些解决方案看起来会更好。
addendum
附录
This is an expanded solution of an earlier one I posted. Since that post kept getting attention, I decided to expand on it and refer to the other excellent solutions that were posted here. My original post had a remark that mentioned that if you wereintending on modifying your vector inside a for
loop then there are two methods provided by std::vector
to access elements: std::vector::operator[]
which does not do bounds checking, and std::vector::at
which does perform bounds checking. In other words, at
will throw if you try to access an element outside the vector and operator[]
wouldn't. I only added this comment, originally, for the sake of mentioning something that it might be useful to know of if anyone already didn't. And I see no difference now. Hence this addendum.
这是我较早发布的解决方案的扩展解决方案。由于该帖子不断受到关注,我决定对其进行扩展并参考此处发布的其他优秀解决方案。我原来的职位有这样提到,如果此言是在修改里面的矢量打算for
环路,则有提供两种方法std::vector
来访问元素:std::vector::operator[]
不这样做边界检查,并且std::vector::at
其不执行边界检查。换句话说,at
如果您尝试访问向量之外的元素并且operator[]
不会,则会抛出。我最初只是添加了此评论,目的是为了提及如果有人还没有知道可能有用的东西。我现在看不出有什么区别。因此,本附录。
回答by Joshua Kravitz
A much easier way to do this is with the standard copy algorithm:
一个更简单的方法是使用标准复制算法:
#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;
}
The ostream_iterator is what's called an iterator adaptor. It is templatized over the type to print out to the stream (in this case, char
). cout
(aka console output) is the stream we want to write to, and the space character (" "
) is what we want printed between each element stored in the vector.
ostream_iterator 就是所谓的迭代器适配器。它在类型上进行了模板化以打印到流(在本例中为char
)。cout
(又名控制台输出)是我们想要写入的流,空格字符 ( " "
) 是我们想要在存储在向量中的每个元素之间打印的内容。
This standard algorithm is powerful and so are many others. The power and flexibility the standard library gives you are what make it so great. Just imagine: you can print a vector to the console with just oneline of code. You don't have to deal with special cases with the separator character. You don't need to worry about for-loops. The standard library does it all for you.
这个标准算法非常强大,许多其他算法也是如此。标准库为您提供的强大功能和灵活性使其如此出色。试想:你可以打印一个矢量到控制台只有一个行代码。您不必处理带有分隔符的特殊情况。您无需担心 for 循环。标准库为您完成这一切。
回答by Shoe
In C++11 you can now use a range-based for loop:
在 C++11 中,您现在可以使用基于范围的 for 循环:
for (auto const& c : path)
std::cout << c << ' ';
回答by Chris Redford
I think the best way to do this is to just overload operator<<
by adding this function to your program:
我认为最好的方法是operator<<
通过将此函数添加到您的程序来重载:
#include <vector>
using std::vector;
#include <iostream>
using std::ostream;
template<typename T>
ostream& operator<< (ostream& out, const vector<T>& v) {
out << "{";
size_t last = v.size() - 1;
for(size_t i = 0; i < v.size(); ++i) {
out << v[i];
if (i != last)
out << ", ";
}
out << "}";
return out;
}
Then you can use the <<
operator on any possible vector, assuming its elements also have ostream& operator<<
defined:
然后您可以<<
在任何可能的向量上使用该运算符,假设其元素也已ostream& operator<<
定义:
vector<string> s = {"first", "second", "third"};
vector<bool> b = {true, false, true, false, false};
vector<int> i = {1, 2, 3, 4};
cout << s << endl;
cout << b << endl;
cout << i << endl;
Outputs:
输出:
{first, second, third}
{1, 0, 1, 0, 0}
{1, 2, 3, 4}
回答by Maxim Chetrusca
How about for_each
+ lambda expression:
for_each
+ lambda 表达式怎么样:
#include <vector>
#include <algorithm>
...
std::vector<char> vec;
...
std::for_each(
vec.cbegin(),
vec.cend(),
[] (const char c) {std::cout << c << " ";}
);
...
Of course, a range-based foris the most elegant solution for this concrete task, but this one gives many other possibilities as well.
当然,基于范围的 for是这个具体任务的最优雅的解决方案,但是这个也提供了许多其他的可能性。
Explanation
解释
The for_each
algorithm takes an input rangeand a callable object, calling this object on every element of the range. An input rangeis defined by two iterators. A callable objectcan be a function, a pointer to function, an object of a class which overloads () operator
or as in this case, a lambda expression. The parameter for this expression matches the type of the elements from vector.
该for_each
算法采用输入范围和可调用对象,在范围的每个元素上调用此对象。的输入范围是由两个限定的迭代器。一个可调用对象可以是一个函数、一个函数指针、一个重载类的对象,() operator
或者在这种情况下,一个 lambda 表达式。此表达式的参数与 vector 中的元素类型匹配。
The beauty of this implementation is the power you get from lambda expressions - you can use this approach for a lot more things than just printing the vector.
这种实现的美妙之处在于你从 lambda 表达式中获得的力量——你可以使用这种方法来做更多的事情,而不仅仅是打印向量。
回答by g24l
Just copy the container to the console.
只需将容器复制到控制台即可。
std::vector<int> v{1,2,3,4};
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout, " " ));
Should output :
应该输出:
1 2 3 4
回答by MSalters
The problem is probably in the previous loop: (x = 17; isalpha(firstsquare); x++)
. This loop will run not at all (if firstsquare
is non-alpha) or will run forever (if it is alpha). The reason is that firstsquare
doesn't change as x
is incremented.
问题可能出在前面的循环中:(x = 17; isalpha(firstsquare); x++)
. 这个循环根本不会运行(如果firstsquare
是非 alpha)或将永远运行(如果它是 alpha)。原因是它firstsquare
不会随着x
增加而改变。
回答by stupidgoddamnjerk
In C++11, a range-based for loop might be a good solution:
在 C++11 中,基于范围的 for 循环可能是一个很好的解决方案:
vector<char> items = {'a','b','c'};
for (char n : items)
cout << n << ' ';
Output:
输出:
a b c
回答by dfri
Using std::copy
but without extra trailing separator
使用std::copy
但没有额外的尾随分隔符
An alternative/modified approach using std::copy
(as originally used in @JoshuaKravtiz answer) but without including an additional trailing separator after the last element:
使用std::copy
(最初在@JoshuaKravtiz answer 中使用)的替代/修改方法,但在最后一个元素之后不包括额外的尾随分隔符:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
template <typename T>
void print_contents(const std::vector<T>& v, const char * const separator = " ")
{
if(!v.empty())
{
std::copy(v.begin(),
--v.end(),
std::ostream_iterator<T>(std::cout, separator));
std::cout << v.back() << "\n";
}
}
// example usage
int main() {
std::vector<int> v{1, 2, 3, 4};
print_contents(v); // '1 2 3 4'
print_contents(v, ":"); // '1:2:3:4'
v = {};
print_contents(v); // ... no std::cout
v = {1};
print_contents(v); // '1'
return 0;
}
Example usage applied to container of a custom POD type:
应用于自定义 POD 类型容器的示例用法:
// includes and 'print_contents(...)' as above ...
class Foo
{
int i;
friend std::ostream& operator<<(std::ostream& out, const Foo& obj);
public:
Foo(const int i) : i(i) {}
};
std::ostream& operator<<(std::ostream& out, const Foo& obj)
{
return out << "foo_" << obj.i;
}
int main() {
std::vector<Foo> v{1, 2, 3, 4};
print_contents(v); // 'foo_1 foo_2 foo_3 foo_4'
print_contents(v, ":"); // 'foo_1:foo_2:foo_3:foo_4'
v = {};
print_contents(v); // ... no std::cout
v = {1};
print_contents(v); // 'foo_1'
return 0;
}
回答by miguelbernadi
I see two problems. As pointed out in for (x = 17; isalpha(firstsquare); x++)
there's either an infinite loop or never executed at all, and also in if (entrance == 'S')
if the entrance character is different than 'S' then nothing in pushed to the path vector, making it empty and thus printing nothing on screen. You can test the latter checking for path.empty()
or printing path.size()
.
我看到两个问题。正如其中所指出for (x = 17; isalpha(firstsquare); x++)
的,要么是无限循环,要么根本不执行,而且if (entrance == 'S')
如果入口字符与“S”不同,则不会将任何内容推送到路径向量,使其为空,从而在屏幕上不打印任何内容。您可以测试后者检查path.empty()
或打印path.size()
.
Either way, wouldn't it be better to use a string instead of a vector? You can access the string contents like an array as well, seek characters, extract substrings and print the string easily (without a loop).
无论哪种方式,使用字符串而不是向量不是更好吗?您也可以像数组一样访问字符串内容,查找字符,提取子字符串并轻松打印字符串(无需循环)。
Doing it all with strings might be the way to have it written in a less convoluted way and easier to spot the problem.
用字符串来做这一切可能是让它以不那么复杂的方式编写并且更容易发现问题的方式。