如何迭代通过c ++中的数字列表 [英] How to iterate through a list of numbers in c++

查看:139
本文介绍了如何迭代通过c ++中的数字列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何迭代一个数字列表,有多少种不同的方法呢?



我认为会有效:

  #include< cstdlib> 
#include< iostream>
#include< list>


使用namespace std;


int main()

{
int numbers [] = {2,4,6,8}
int i = 0;
for(i = 0; i< numbers.size(); i ++)
cout< 当前数字是<数字[i];


系统(暂停);

return 0;

}

我在for循环行上遇到错误:'numbers'中为成员'size'请求






与许多现代语言不同,纯C ++数组没有 .size()函数。



一些常见的存储选项包括:

  //用于固定大小的存储。需要#include< array> 
std :: array< type,size>采集;

//用于动态大小的存储。需要#include< vector>
std :: vector< type>采集;

//动态存储。一般来说:更慢的迭代,更快的插入
//需要#include< list>
std :: list< type>采集;

//旧式C数组
int myarray [size];

您的迭代选项将取决于您使用的类型。如果你使用一个普通的老C数组,你可以存储其他地方的大小或计算数组的大小基于它的类型的大小。 计算数组的大小具有DevSolar在此答案中概述的许多缺点

  //将值存储为常量
int oldschool [10];
for(int i = 0; i <10; ++ i){
oldschool [i]; // Get
oldschool [i] = 5; // set
}

//计算数组的大小
int size = sizeof(oldschool)/ sizeof(int);
for(int i = 0; i oldschool [i]; // Get
oldschool [i] = 5; // Set
}

如果您使用任何类型提供 .begin() .end()函数可以使用这些函数来获得一个迭代器,基于索引的迭代:

  //也可以是一个数组,列表或任何与begin $ b std :: vector< int>新学校; 

//定期迭代器,非C ++ 11
for(std :: vector< int> :: iterator num = newschool.begin(); num!= newschool.end ); ++ num){
int current = * num; // *获取迭代器的数字
* num = 5; //设置数字。
}

//更好的语法,使用auto!自动获取正确的迭代器类型(C ++ 11)
for(auto num = newschool.begin(); num!= newschool.end(); ++ num){
int current = ; // As above above
* num = 5;
}

// std :: for_each也可用
std :: for_each(newschool.begin(),newschool.end(),function_taking_int);

// std :: for_each with lambdas(C ++ 11)
std :: for_each(newschool.begin(),newschool.end(),[]
//只需使用i,不能修改
});

向量也是特殊的,因为它们被设计为数组的替换。你可以用一个 .size()函数来完成一个向量的迭代。但是这在C ++中被认为是不好的做法,你应该更喜欢在可能的地方使用迭代器:

  std :: vector< int&坏习惯
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>花哨
for(int i:fancy){
//只是使用i,不能修改。
}

// begin / end requires #include< iterator>也包括在大多数容器头文件中。
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>数字; 
for(auto num = numbers.begin(); num!= numbers.end(); / *故意为空* /){
...

if(someDeleteCondition ){
num = numbers.erase(num);
} else {
//没有删除,没有问题
++ num;
}
}

这份清单并不全面,有很多方法来迭代一个集合。一般来说,喜欢迭代器,除非你有很好的理由不这样做。


How do I iterate through a list of numbers, and how many different ways are there to do it?

What I thought would work:

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

}

I get an error on the for loop line:

request for member 'size' in 'numbers', which is of non-class type 'int[4]'

解决方案

Unlike a lot of modern languages plain C++ arrays don't have a .size() function. You have a number of options to iterate through a list depending on the storage type.

Some common options for storage include:

// 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]; 

Your options for iteration will depend on the type you're using. If you're using a plain old C array you can either store the size somewhere else or calculate the size of the array based on the size of it's types. Calculating the size of an array has a number of drawbacks outlined in this answer by 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
}

If you're using any type that provides a .begin() and .end() function you can use those to get an iterator which is considered good style in C++ compared to index based iteration:

// 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.
});

Vectors are also special because they are designed to be drop-in replacements for arrays. You can iterate over a vector exactly how you would over an array with a .size() function. However this is considered bad practice in C++ and you should prefer to use iterators where possible:

std::vector<int> badpractice;
for(int i = 0; i < badpractice.size(); ++i) {
    badpractice[i]; // Get
    badpractice[i] = 5; // Set
}

C++11 (the new standard) also brings the new and fancy range based for that should work on any type that provides a .begin() and .end(). However: Compiler support can vary for this feature. You can also use begin(type) and end(type) as an alternative.

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 also has another interesting property: it works on raw arrays. This means you can use the same iteration semantics between arrays and non-arrays (you should still prefer standard types over raw arrays):

int raw[10];
for(auto num = std::begin(raw); num != std::end(raw); ++num) {
    int current = *num; // Get
    *num = 131; // Set
}

You also need to be careful if you want to delete items from a collection while in a loop because calling container.erase() makes all existing iterators invalid:

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

This list is far from comprehensive but as you can see there's a lot of ways of iterating over a collection. In general prefer iterators unless you have a good reason to do otherwise.

这篇关于如何迭代通过c ++中的数字列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆