如何在c++中迭代数字列表
How to iterate through a list of numbers in c++
如何遍历数字列表,有多少种不同的方法?
我认为可行的方法:
#include <cstdlib>
#include <iostream>
#include <list>
using namespace std;
int main()
{
int numbers[] = {2, 4, 6, 8};
int i = 0;
for(i=0; i< numbers.size();i++)
cout << "the current number is " << numbers[i];
system("pause");
return 0;
}
我在for循环行得到一个错误:
对
'numbers'
中非'int[4]'
类成员'size'
的请求
与许多现代语言不同,普通c++数组没有.size()
函数。根据存储类型的不同,有许多遍历列表的选项。
常用的存储选项包括:
// used for fixed size storage. Requires #include <array>
std::array<type, size> collection;
// used for dynamic sized storage. Requires #include <vector>
std::vector<type> collection;
// Dynamic storage. In general: slower iteration, faster insert
// Requires #include <list>
std::list<type> collection;
// Old style C arrays
int myarray[size];
您的迭代选项将取决于您使用的类型。如果使用的是普通的旧式C数组,则可以将大小存储在其他地方,也可以根据数组类型的大小计算数组的大小。计算数组的大小有一些缺点概述了这个答案由DevSolar
// Store the value as a constant
int oldschool[10];
for(int i = 0; i < 10; ++i) {
oldschool[i]; // Get
oldschool[i] = 5; // Set
}
// Calculate the size of the array
int size = sizeof(oldschool)/sizeof(int);
for(int i = 0; i < size; ++i) {
oldschool[i]; // Get
oldschool[i] = 5; // Set
}
如果你使用任何类型提供.begin()
和.end()
函数,你可以使用它们来获得迭代器,与基于索引的迭代相比,这在c++中被认为是很好的风格:
// Could also be an array, list, or anything with begin()/end()
std::vector<int> newschool;
// Regular iterator, non-C++11
for(std::vector<int>::iterator num = newschool.begin(); num != newschool.end(); ++num) {
int current = *num; // * gets the number out of the iterator
*num = 5; // Sets the number.
}
// Better syntax, use auto! automatically gets the right iterator type (C++11)
for(auto num = newschool.begin(); num != newschool.end(); ++num) {
int current = *num; // As above
*num = 5;
}
// std::for_each also available
std::for_each(newschool.begin(), newschool.end(), function_taking_int);
// std::for_each with lambdas (C++11)
std::for_each(newschool.begin(), newschool.end(), [](int i) {
// Just use i, can't modify though.
});
vector也很特殊,因为它们被设计为数组的直接替代品。您可以像使用.size()
函数遍历数组一样遍历向量。然而,这在c++中被认为是不好的做法,你应该尽可能使用迭代器:
std::vector<int> badpractice;
for(int i = 0; i < badpractice.size(); ++i) {
badpractice[i]; // Get
badpractice[i] = 5; // Set
}
c++ 11(新标准)还带来了新的和奇特的基于范围,它应该适用于任何提供.begin()
和.end()
的类型。但是,编译器对该特性的支持可能有所不同。您也可以使用begin(type)
和end(type)
作为替代。
std::array<int, 10> fancy;
for(int i : fancy) {
// Just use i, can't modify though.
}
// begin/end requires #include <iterator> also included in most container headers.
for(auto num = std::begin(fancy); num != std::end(fancy); ++num) {
int current = *num; // Get
*num = 131; // Set
}
std::begin
还有另一个有趣的属性:它适用于原始数组。这意味着您可以在数组和非数组之间使用相同的迭代语义(您仍然应该更喜欢标准类型而不是原始数组):
int raw[10];
for(auto num = std::begin(raw); num != std::end(raw); ++num) {
int current = *num; // Get
*num = 131; // Set
}
如果你想在循环中从集合中删除项,你也需要小心,因为调用container.erase()
会使所有现有的迭代器无效:
std::vector<int> numbers;
for(auto num = numbers.begin(); num != numbers.end(); /* Intentionally empty */) {
...
if(someDeleteCondition) {
num = numbers.erase(num);
} else {
// No deletition, no problem
++num;
}
}
这个列表还远远不够全面,但是正如你所看到的,在一个集合上有很多迭代的方法。一般来说,除非有很好的理由,否则更倾向于使用迭代器。
将for循环改为
for(i=0; i< sizeof(numbers)/sizeof(int);i++){
简单来说,sizeof(numbers)
表示数组中元素的数量*基本类型int的大小,所以除以sizeof(int)
得到元素的数量
如果你把它修改成list<int> numbers = {1,2,3,4}
:
使用迭代器进行遍历:
#include <iterator>
for(auto it = std::begin(numbers); it != std::end(numbers); ++it) { ... }
使用std::for_each
:
#include <algorithm>
#include <iterator>
std::for_each(numbers.begin(), numbers.end(), some_func);
使用for-each循环(c++ 11):
for(int i : numbers) { ... }
我没有在答案中看到它,但这是我最好的方法:基于范围的for循环
使用演绎来转发引用是安全的,实际上,在泛型代码中更可取:
(auto&和;Var: sequence).
极简和工作示例:
#include <list>
#include <iostream>
int main()
{
std::list<int> numbers = {2, 4, 6, 8};
for (const int & num : numbers)
std::cout << num << " ";
std::cout << 'n';
return 0;
}
如果您的数字列表是固定的,请注意您可以简单地写:
#include <iostream>
#include <initializer_list>
int main()
{
for (int i : {2, 4, 6, 8})
std::cout << i << std::endl;
return 0;
}
在"plain" c风格数组上没有size
函数。如果您想使用size
,则需要使用std::vector
,或者通过sizeof
计算大小。
在c++ 11中,你可以使用数组初始化语法来初始化向量,如下所示:
vector<int> numbers = {2, 4, 6, 8};
其他内容保持不变(参见此处的演示)
也可以使用普通的C容器和使用迭代器语法进行循环:
#include <iostream>
int main()
{
int numbers[] = {2, 4, 6, 8};
int *numbers_end = numbers + sizeof(numbers)/sizeof(numbers[0]);
for (int *it = numbers; it != numbers_end; ++it)
std::cout << "the current number is " << *it << std::endl;
return 0;
}
没有成员函数"size",因为"numbers"不是一个类。你不能通过这种方式得到数组的大小,你必须知道它(或计算它)或使用一些类来存储你的数字。
在我看来,最简单的方法是使用span。
#include <cstdlib>
#include <iostream>
#include <gsl/span>
int main() {
int numbers[] = {2, 4, 6, 8};
for(auto& num : gsl::span(numbers)) {
cout << "the current number is " << num;
}
system("pause");
}
指出:
- span是GSL库的一部分。要使用它们,从这里下载库,并将下载路径添加到编译命令中,例如
g++ -o foo foo.cpp -I/path/to/gsl
。 - 在c++ 20中,
span
将成为标准的一部分,因此您只需使用std::span
和#include <span>
。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 迭代时从向量和内存中删除对象
- 如何在c++迭代器类型中包装std::chrono
- 带过滤器的现代迭代c++集合
- 在c++中检查长方体是否尽可能快地重叠(无迭代)
- C++矢量迭代
- 集合上的输出迭代器:assign和increment迭代器
- 顺时针迭代旋转 3 位数字
- 如何将 UTF-8 文本从文件转换为某个可以迭代的容器,并检查每个符号是否为C++字母数字?
- 从迭代器中提取数字
- 毫无疑问显示迭代数字
- 是否有适用于迭代器的数字解析函数
- C :优雅地迭代一组数字
- 迭代排序列表并计算不同的数字
- 我可以读取向量<string>::迭代器的数字位置吗?
- 迭代器应该读取整个数字,但它只读取第一位数字
- c++:std::map数字id的迭代排序-交叉编译器
- 如何在c++中迭代数字列表