运行代码时,我得到所有这些数字作为输出,这意味着我的while循环似乎遍历了不应跳过的元素。为什么会这样呢? 就上下文而言,我目前正在学习C ++,并且对C ++进行了了解,我对指针和引用感到非常困惑。
这是我获得代码的地方: Buggy code in "A Tour of C++" or non-compliant compiler?
int counter(int* arr,int c){
int counter = 0;
while(*arr){
cout << *arr<<"\n";
if(*arr == c){
++counter;
}
++arr;
}
return counter;
}
int main()
{
int arr[3] = {1,2,3};
int count = counter(arr,1);
cout<< count;
}
示例运行:
/Users/benediktschesch/CLionProjects/untitled/cmake-build-debug/untitled
1
2
3
-945684358
-1153026697
-280532248
32766
1839025881
32767
1839025881
32767
1
Process finished with exit code 0
答案 0 :(得分:3)
这非常类似于不为将用作字符串的字符数组提供空终止符。
while(*arr)
表示找到零时停止。
int arr[3] = {1,2,3};
不提供零,因此您无法控制循环何时停止。
使用Library container。 std :: vector或std::array
在这里非常合适,std::count
的the <algorithm>
library和the <iterator>
library的std::begin
和std::end
也是如此。 / p>
#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};
请注意,我删除了显式数组的大小。不需要,因为编译器可以从Initializer中的元素数量中得知。
还要注意,这将在到达第一个零时停止,因此
int arr[] = {1,2,3,0,1,2,3,0};
只会发现1。这使0成为终止整数列表的非常差的值,除非确保输入中没有0。
要扫描整个阵列并且仅扫描阵列,需要提供阵列的大小。可以通过传入size参数来完成
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;
}
,但是Modern 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
用val
从arr
的内容推导auto
的类型。该值不会因循环而更改,因此我们将其声明为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解决方案。
答案 1 :(得分:3)
我建议使用std::array和range based for loops
#include <array>
#include <iostream>
int counter(const std::array<int, 3> &arr, int c){
int counter = 0;
for (auto const a : arr) {
std::cout << a << "\n";
if(a == c){
++counter;
}
}
return counter;
}
int main()
{
std::array<int, 3> arr = {1,2,3};
int count = counter(arr,1);
std::cout << count;
}
出现问题的原因是在行
while(*arr){
声明
*arr
被评估为布尔值。 *arr == 0
为false,其他情况为true。在您的代码中,您需要获取数组的大小或值为0的最后一个元素的大小。有不同的方法。您可以将最后一个元素添加为0,也可以将大小传递给函数。但是C ++标准提供了stl容器,可以解决您的问题而不会产生开销。 std::array
是一个包含数据和数组大小的容器。这是一个模板类,因此大小不需要任何额外的数据。首先,您应该学习如何使用语言提供的工具,例如stl容器和算法。稍后,您将学习如何使用底层函数和数据类型。
答案 2 :(得分:1)
除了包含字符串的字符数组以外,其他所有数组(如果您不故意使用标记值)都不包含表示数组结尾的零元素。因此,如果数组不包含等于0的元素(如您的情况),则您的函数可以调用未定义的行为。
因此,通常,您的函数应该再有一个参数,用于指定数组中元素的数量,并且看起来应该像
size_t counter( const int *arr, size_t n, int value )
{
size_t count = 0;
for ( const int *p = arr; p != arr + n; ++p )
{
if ( *p == value ) ++count;
}
return count;
}
并称呼为
int main()
{
int arr[] = { 1, 2, 3 };
const size_t N = sizeof( arr ) / sizeof( *arr );
size_t count = counter( arr, N, 1 );
std::cout << count << '\n';
}
如果编译器支持C ++ 17,则可以在标头sizeof( arr ) / sizeof( *arr )
中声明标准函数std::size()
而不是表达式<iterator>
,例如std::size( arr )
。
否则,可以使用表达式代替表达式sizeof( arr ) / sizeof( *arr )
std::extent<decltype( arr )>::value
提供了标头<type_traits>
。
请注意,标头std::count
中声明了执行相同任务的标准算法<algorithm>
。这是一个演示程序
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int arr[] = { 1, 2, 3 };
auto count = std::count( std::begin( arr ), std::end( arr ), 1 );
std::cout << count << '\n';
}