如何打印出vector的内容?

我想用C ++打印一个vector的内容,这里是我的:

#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; } } 

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

纯粹为了回答你的问题,你可以使用一个迭代器:

 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

这不是另一个解决scheme,而是上述iterator解决scheme的补充。 如果您使用的是C ++ 11标准(或更高版本),那么您可以使用auto关键字来提高可读性:

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

但是, i的types将是非常量(即编译器将使用std::vector<char>::iterator作为i的types)。

在这种情况下,你可能只需要使用typedef (不限于C ++ 11,而且非常有用)。

 typedef std::vector<char> Path; Path path; // ... for (Path::const_iterator i = path.begin(); i != path.end(); ++i) std::cout << *i << ' '; 

计数器

当然,您可以使用整数types在for循环中logging您的位置:

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

如果要这样做,最好使用容器的成员types(如果可用且合适的话)。 std::vector有一个名为size_type的成员types用于这个作业:它是size方法返回的types。

 // Path typedef'd to std::vector<char> for( Path::size_type i=0; i<path.size(); ++i) std::cout << path[i] << ' '; 

为什么不使用iterator解决scheme呢? 对于简单的情况你可能也是如此,但重点是iterator类是一个对象,旨在做这个工作的更复杂的对象,这个解决scheme不会是理想的。

基于范围的循环(C ++ 11)

见Jefffrey的解决scheme 。 在C ++ 11(及更高版本)中,可以使用新的基于范围的for循环,如下所示:

 for (auto i: path) std::cout << i << ' '; 

由于path是项目的向量(明确地说是std::vector<char> ),所以对象i是向量项目的types(也就是显式地是chartypes)。 对象i有一个值是path对象中的实际项目的副本。 因此,循环中对i所有更改都不会保留在path本身中。 另外,如果你想强制实现你不想在循环中改变i的复制值,你可以强制i的types为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 << ' '; 

性病::复制

见约书亚的回答 。 您可以使用STLalgorithmstd::copy将vector内容复制到输出stream。 如果你对此感到满意,这是一个很好的解决scheme(此外,这非常有用,不仅仅是在这种情况下打印vector的内容)。

的std :: for_each的

请参阅Max的解决scheme 。 使用std::for_each对于这个简单的场景来说是矫枉过正的,但是如果你想要做的不仅仅是打印到屏幕上,它是一个非常有用的解决scheme:使用std::for_each允许你对vector内容进行任何 (明智的)操作。

超载ostream :: operator <<

请参阅克里斯的答案 ,这是对其他答案的补充,因为您仍然需要在重载中实现上述解决scheme之一。 在他的例子中,他在for循环中使用了一个计数器。 例如,这就是你如何快速使用Joshua的解决scheme :

 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; } 

任何其他解决scheme的使用应该是直接的。

结论

任何在这里提出的解决scheme将工作。 这取决于你和哪一个是最好的代码。 比这更详细的任何事情可能是最好留下的另一个问题,正反评估可以得到适当的评估; 但是一如既往地用户偏好将始终扮演一个angular色:所提供的解决scheme都不是错误的,但是对于每个单独的编码器,一些解决scheme看起来会更好。

附录

这是我发布的早期版本的扩展解决scheme。 既然这个post一直受到关注,我决定扩展它,并参考其他在这里发布的优秀解决scheme。 我原来的post有一句话提到,如果你打算在for循环中修改你的vector for那么std::vector提供了两个访问元素的方法: std::vector::operator[] ,它不会做边界检查和std::vector::at哪个执行边界检查。 换句话说,如果你试图访问vector之外的一个元素, operator[]就不会这样做。 原来,我只是为了提到某些事情,如果有人不知道,可能是有用的。 而我现在看到没有区别。 因此,这个附录。

更简单的方法是使用标准的复制algorithm :

 #include <iostream> #include <algorithm> // for copy #include <iterator> // for ostream_iterator #include <vector> int main() { /* Set up vector to hold chars az */ 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就是所谓的迭代器适配器 。 它是模板化的types打印出来的stream(在这种情况下, char )。 cout (又名控制台输出)是我们要写入的stream,而空格字符( " " )就是我们想要在存储在向量中的每个元素之间打印的内容。

这个标准algorithmfunction强大,其他许多function也是如此。 标准库为您提供的强大function和灵活性使得它非常棒。 试想一下:只需一行代码就可以将vector打印到控制台。 您不必使用分隔符处理特殊情况。 你不需要担心for循环。 标准的库为你做的一切。

在C ++ 11中,您现在可以使用基于范围的for循环 :

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

我认为最好的办法就是通过在程序中join这个函数来重载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; } 

那么你可以在任何可能的向量上使用<<运算符,假设它的元素也有ostream& operator<< defined:

 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; 

输出:

 [first, second, third] [1, 0, 1, 0, 0] [1, 2, 3, 4] 

如何for_each + lambdaexpression式

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

当然,以范围为基础是这个具体任务最优雅的解决scheme,但是这个也给了很多其他的可能性。

说明

for_eachalgorithm接受一个input范围和一个可调用的对象 ,在该范围的每个元素上调用该对象。 input范围由两个迭代器定义。 可调用对象可以是函数,指向函数的指针,也可以是重载() operator的类的对象,也可以是lambdaexpression式 。 该expression式的参数与来自向量的元素的types相匹配。

这种实现的优点是你从lambdaexpression式获得的力量 – 你可以使用这种方法比打印vector更多的东西。

问题可能在前面的循环中: (x = 17; isalpha(firstsquare); x++) 。 这个循环将不会运行(如果firstsquare是非alpha)或者将永远运行(如果它是alpha)。 原因在于x是递增的, firstsquare不会改变。

在C ++ 11中,基于范围的for循环可能是一个很好的解决scheme:

 vector<char> items = {'a','b','c'}; for (char n : items) cout << n << ' '; 

输出:a b c

我看到两个问题。 正如在for (x = 17; isalpha(firstsquare); x++)指出的那样,如果入口字符不是'S', if (entrance == 'S')有一个无限循环或从不执行, if (entrance == 'S') 'S'然后没有任何东西推到path向量,使其为空,因此在屏幕上什么都不打印。 您可以testing后者检查path.empty()或打印path.size()

无论哪种方式,使用string代替vector不是更好吗? 您也可以像访问数组一样访问string内容,查找字符,提取子string并轻松打印string(无循环)。

用string做所有事情可能是以不太复杂的方式写出来的,更容易发现问题。

只需将容器复制到输出

 std::vector<int> v{1,2,3,4}; std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout<< " " )); 

应该输出:

1 2 3 4

超载运算符<<:

 template<typename OutStream, typename T> OutStream& operator<< (OutStream& out, const vector<T>& v) { for (auto const& tmp : v) out << tmp << " "; out << endl; return out; } 

用法:

 vector <int> test {1,2,3}; wcout << test; // or any output stream 

这个答案是基于Zorawar的答案,但我不能在那里留言。

你可以使用cbegin和cend来改变auto(C ++ 11)/ typedef的版本

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

使用std::copy但没有额外的尾随分隔符

一个替代/修改的方法使用std::copy (最初在@JoshuaKravtiz答案中使用 ),但不包括最后一个元素后面的附加尾随分隔符:

 #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; } 

应用于自定义PODtypes的容器的示例用法:

 // 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; } 
Interesting Posts