在for循环中使用数组 - C ++

时间:2014-11-04 01:15:01

标签: c++ arrays

我想设置一个测试条件来确定数组的大小,然后在for循环中遍历数组的每个值。

以此数组为例

std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};  

括号为空,其中有10个元素。如何在不创建包含10的int的单独变量的情况下为此创建for循环?

6 个答案:

答案 0 :(得分:1)

使用countof宏,声明如下:

#define countof(a) (sizeof(a)/sizeof((a)[0]))

所以你可以说:

for (i = 0; i < countof(expenses); i++) ...

正如大家所指出的那样,你必须要有足够的热门知识来了解数组和指针之间的区别。 如果您将指针传递给expenses,当然countof将是假的。

答案 1 :(得分:1)

如果你想要遍历每个元素(在同一个scope内),那么'黑暗'是正确的:

#include <string>
#include <iostream> 

int main()
{
  std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
  std::cout<< "NumEls = " << sizeof(expenses) / sizeof(expenses[0]) << std::endl;
}

产生10的输出,用cout循环替换for将允许测试字符串,例如

for (int i=0; i< (sizeof(expenses)/sizeof(expenses[0])); i++)
{
    std::cout<< "The " << i << "th string is : " << expenses[i] << std::endl;
}

注意这会产生“0th”,“1th”等......

*警告*

反映问题中的评论,我们的答案似乎不完整而没有提及sizeof(POINTER)不会给你有用的信息 - 或者至少对此没用。因此,如果您想要使用:

myFunction (std::string someArray[])
{
    for( all the strings in someArray )
    {
        std::cout << someArray[i];
    }
}

然后你会发现自己无法这样做。

相反,您可以使用:

myFunction (std::string someArray[], int sizeOfArray)
{
    for(int i=0; i<sizeOfArray; i++)
    {
        std::cout<< someArray[i];
    }
}

但这完全违背了你的问题(不存储单独的int)

*输入std :: vector *

更简单的解决方案是使用std::vector

在更新的(C ++ 11)编译器/编译器选项的情况下,向量的使用允许函数调用,例如myVector.size(),并且还基于向量的大小自动循环。

矢量可以愉快地传入和传出函数,如果你想更改它们,对矢量的引用也是一种简单的方法 - 参考你的答案:

inputFunction (std::vector<string> &expenses, budget &info)
{
    for (int i=0; i< expenses.size(); i++)
    {
        std::cout<< "Enter your expense for " << expenses[i] << ": ";
        // Operation to store input as needed
    }
}

在旁注中,您似乎想要将string的费用名称与费用的值相关联?如果是这样,请考虑使用map。在这种情况下,您可能需要考虑std::map<std::string, float>

*使用std :: map *

在使用地图时,您可能需要一个迭代器。一个例子可能是:

void input(const std::vector<std::string> &exp, std::map<std::string, float> &map)
{
  for (int i=0; i<exp.size(); i++)
  {
    float tempFloat;
    std::cout<< "Please enter the amount for " << exp[i] << ": ";
    std::cin >> tempFloat;
    map.emplace(exp[i], tempFloat);
  }
};

main()

std::map<std::string, float> myMap;
  input(myVec, myMap);
  for (std::map<std::string, float>::iterator it=myMap.begin(); it!=myMap.end(); it++)
  {
    std::cout << "myMap values -> " << it->first << " = " << it->second << std::endl;
  }

这将输出您拥有的每一对,使用从myMap.begin()开始到地图的最后一个条目结束的迭代器。

emplace(...)构造一对,然后将其添加到地图中。您应该注意不要使用insert,这需要一组不同的参数,并且不太可能是您想要的。

输出由iterator->firstiterator->second引用,每个地图对的firstsecond值。在这种情况下,这些是存储在string中的floatmap

答案 2 :(得分:1)

我的直接倾向是告诉你使用向量而不是数组。使用向量,您可以非常轻松地获得大小,并且(更好的是)通过使用基于范围的for循环避免缩小大小:

std::vector<std::string> expenses {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};

// print out the strings, one per line:
for (auto const &s : expenses)
    std::cout << s << "\n";

如果确实必须使用数组而不是向量,则可以使用函数模板来计算大小:

template <class T, size_t N>
size_t size(T (&array)[N]) { 
    return N;
}

for (int i=0; i<size(expenses); i++)
    std::cout << expenses[i] << '\n';

这个模板函数相对于通常的宏((sizeof(x)/sizeof(x[0])))的主要优点是它是强类型的 - 任何传递指针而不是数组的尝试都不会简单地编译(并且给出一个数组名称衰减到指针是多么容易,这是非常重要的。

如果您有C ++ 11可用,则可以使用标准库中的std::beginstd::end来完成(大致)相同的操作:

for (auto s = std::begin(expenses); s != std::end(expenses); ++s)
    std::cout << *s;

请注意,尽管在C ++ 11中添加了std::beginstd::end,但您可以使用与上面size模板类似的代码为C ++ 98创建类似的模板03编译器。

template <class T, size_t N>
T *begin(T (&array)[N]) { 
    return array;
}

template <class T, size_t N>
T *end(T (&array)[N]) { 
    return array + N;
}

这些也可以与标准算法一起使用,因此你可以这样做:

std::copy(begin(expenses), end(expenses), 
          std::ostream_iterator<std::string>(std::cout, "\n"));

再次注意,我们避免直接处理计数或在数组中创建下标,只是将迭代器处理到数组中,以及这些迭代器引用的项目。

答案 3 :(得分:0)

您可以使用sizeof(expenses) / sizeof (expenses[0])。请注意,您不需要括号,但我更喜欢它。

答案 4 :(得分:0)

很多人都提到了(sizeof(费用)/ sizeof(费用[0]))技巧,但是如果你要去那条路,那么在C ++中有一种更好的方法可以做到这一点。使用模板化函数:

/* returns # of items in array, or will error out at compile time if you try to pass it a pointer instead of an array */
template<typename T, int size> unsigned int array_size(T(&)[size]) {return size;}

这样更安全,因为如果您不小心传入指针而不是数组,它会给您一个编译时错误。 (sizeof()版本将编译,然后在运行时执行一些意外的操作,这是不可取的)

答案 5 :(得分:0)

两种可能性。如果你想在你定义的范围内迭代它,你可以简单地使用一个基于范围的for循环:

for(auto& expense : expenses)
{
    std::cout << expense << std::endl;
}

如果你想将它传递给一个函数,你必须要一些丑陋的东西才能使它适合std :: array,然后你可以在任何地方使用上面的范围循环。 / p>