我想设置一个测试条件来确定数组的大小,然后在for
循环中遍历数组的每个值。
以此数组为例
std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
括号为空,其中有10个元素。如何在不创建包含10的int的单独变量的情况下为此创建for
循环?
答案 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->first
和iterator->second
引用,每个地图对的first
和second
值。在这种情况下,这些是存储在string
中的float
和map
。
答案 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::begin
和std::end
来完成(大致)相同的操作:
for (auto s = std::begin(expenses); s != std::end(expenses); ++s)
std::cout << *s;
请注意,尽管在C ++ 11中添加了std::begin
和std::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>