这与不为将用作字符串的字符数组提供空终止符非常相似。
while(*arr)
表示找到零时停止。
int arr[3] = {1,2,3};
不提供零,因此您无法控制循环何时停止。
TL;DR 解决方案:
使用Library container。 std::vector 或 std::array 非常适合这里,std::count 来自 the <algorithm> library 和 std::begin 和 std::end 来自 the <iterator> library。
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int arr[] = { 1, 2, 3 };
int count = std::count(std::begin(arr), std::end(arr), 1);
std:: cout << count;
}
说明:
你可以提供一个零
int arr[] = {1,2,3,0};
注意我删除了显式数组大小。不需要,因为编译器从初始化器中的元素数量知道。
还要注意,这将在到达第一个零时停止,所以
int arr[] = {1,2,3,0,1,2,3,0};
只会发现一个 1。这使得零成为一个非常糟糕的值,用于终止整数列表,除非 0 保证不会出现在输入中。
要扫描整个数组并且只扫描数组,需要提供数组的大小。这可以通过传入一个大小参数来完成
int counter(int* arr, size_t len, int c)
{
int counter = 0;
while (len--)
{
std::cout << *arr << "\n";
if (*arr == c)
{
++counter;
}
++arr;
}
return counter;
}
int main()
{
int arr[3] = { 1, 2, 3 };
int count = counter(arr, std::size(arr), 1);
std:: cout << count;
}
但现代 C++ 中的首选解决方案是使用容器代替数组。容器知道它们的大小,并提供了各种各样的其他工具,使编写代码更容易,更不容易出错。
#include <iostream>
#include <vector>
int counter(const std::vector<int> & arr, int c)
{
int counter = 0;
for (const auto & val: arr)
{
std::cout << val << "\n";
if (val == c)
{
++counter;
}
}
return counter;
}
int main()
{
std::vector<int> arr = { 1, 2, 3 };
int count = counter(arr, 1);
std:: cout << count;
}
注意使用range-based for loop 来简化代码。 const auto & val 从arr 和auto 的内容推导出val 的类型。该值不会因循环而更改,因此我们将其声明为const 以防止意外并使其成为参考,因为也许编译器可以执行一些额外的优化巫术。此外,如果容器或容器中的数据类型发生变化,您可以继续重复使用这个确切的语句,而无需更改任何内容。这样可以防止以后在维护代码时出错。
您也可以使用std::array 并将counter 设为模板化函数,用于检测std::array 的大小,但目前这有点多。
下一次演进利用<algorithm> 库。
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> arr = { 1, 2, 3 };
int count = std::count(arr.begin(), arr.end(), 1);
std:: cout << count;
}
在这种情况下,使用迭代器而不是指定长度。这使您可以轻松扫描容器的子集。
这使我们可以利用std::begin 和std::end 将数组转换为一对迭代器,从而重新使用普通数组:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int arr[] = { 1, 2, 3 };
int count = std::count(std::begin(arr), std::end(arr), 1);
std:: cout << count;
}
这让我们想到了 TL;DR 解决方案。