我想反转我的数组。为啥这段代码给出垃圾值?

Posted

技术标签:

【中文标题】我想反转我的数组。为啥这段代码给出垃圾值?【英文标题】:I wanted to reverse my array. Why this code gives garbage value?我想反转我的数组。为什么这段代码给出垃圾值? 【发布时间】:2020-05-22 20:18:17 【问题描述】:
    #include <iostream>


    using namespace std;

    int main()

    int n;
    int a[n];
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i];
    
    for(int i=n;i>=0;i--)
       cout<<a[i]<<" ";
   
    

输入:- 4 1 2 3 4 输出 4199008 4 3 2 1

【问题讨论】:

在编译器上启用警告。 int a[n]; 并非每个编译器都支持,如果不是错误,则应生成警告。你不先初始化n。你实际上想要std::vector&lt;int&gt;。另外,do not use using namespace std;。您可以使用 std::reverse() 反转任何支持双向迭代的容器。 另外,您的第二个循环索引a[n],即UB。你需要从n-1开始。 您的代码显然不会尝试“反转数组”。见 std::reverse。应用它后,cout 生成的数组,从头到尾。这可以简化和记录您的编码意图,并避免意外的未定义行为。 【参考方案1】:

对于初学者,程序具有未定义的行为,因为变量 n 未初始化

int n;

所以这个声明

int a[n];

无效。此外,可变长度数组不是标准的 C++ 特性。而是使用标准类模板std::vector

也在这个循环中

for(int i=n;i>=0;i--) 
   cout<<a[i]<<" ";

您正在尝试访问索引为 n 的不存在元素。

此外,您没有反转数组。您正试图以相反的顺序输出一个数组。

注意在标头&lt;algorithm&gt;中声明了标准算法std::reversestd::reverse_copy

这是一个示例,使用您的方法的程序看起来如何

#include <iostream>
#include <vector>

int main() 

    size_t n = 0;

    std::cout << "Enter the size of an array ";

    std::cin >> n;

    std::vector<int> v( n );

    std::cout << "Enter " << n << " elements: ";

    for ( auto &item : v ) std::cin >> item;

    std::cout << "The array in the reverse order\n";

    for ( size_t i = v.size(); i != 0;  )
    
        std::cout << v[--i] << ' ';
    
    std::cout << '\n';

    return 0;

程序输出可能看起来像

Enter the size of an array 10
Enter 10 elements: 0 1 2 3 4 5 6 7 8 9
The array in the reverse order
9 8 7 6 5 4 3 2 1 0 

如果使用标准算法,那么您的程序可以如下所示

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main() 

    size_t n = 0;

    std::cout << "Enter the size of an array ";

    std::cin >> n;

    std::vector<int> v( n );

    std::cout << "Enter " << n << " elements: ";

    std::copy_n( std::istream_iterator<int>( std::cin ), n, std::begin( v ) );

    std::cout << "The array in the reverse order\n";

    std::reverse_copy( std::begin( v ), std::end( v ), 
                       std::ostream_iterator<int>( std::cout, " ") );
    std::cout << '\n';

    return 0;

程序输出可能与上面显示的方式相同

Enter the size of an array 10
Enter 10 elements: 0 1 2 3 4 5 6 7 8 9
The array in the reverse order
9 8 7 6 5 4 3 2 1 0 

【讨论】:

荣誉奖:rbegin()rend() 这使得 reverse_copy 完全没有必要。【参考方案2】:

a[n] 将返回最后一个元素之后的元素。逆序迭代时,以i=n-1开头。

【讨论】:

还有更多需要修复的地方,例如int a[n] 之前的 n 被初始化。除非nconst,否则即使初始化它也不起作用。【参考方案3】:

在你的程序开始时有一个错误:

    int n; // You declare n with no value
    int a[n]; // You use is
    cin>>n; // After you used it you get your value-

现在我可以假设这只是复制时的错误,因为您提供了输入和输出

输入:- 4 1 2 3 4 输出 4199008 4 3 2 1

所以忘记这一点,你声明一个大小为 n 的数组。 请记住,数组的元素将从 0 变为 n-1。 现在看看你的第二个 for 循环

    // the first element you acces is n and you stop at 1
    // but the array goes from n-1 to 0
    for(int i=n;i>=0;i--)
       cout<<a[i]<<" ";
    

所以你仍然会得到 n 个值作为输出,但你访问的第一个元素在数组之外。这就是为什么你会得到一个垃圾值,那是一个遗留在那里的值。

一个解决方案是改变for循环

    for(int i=n-1;i>=-1;i--)
       cout<<a[i]<<" ";
   

【讨论】:

【参考方案4】:

在反转数组时,从 n-1 开始循环,即 i=n-1(n 是数组中的元素数)。并运行循环直到 i>=0。如果你从 n 开始循环,它将读取超出范围的非法索引,并给你垃圾值。

 for(int i=n-1; i>=0; i++)
      cout<<arr[i]<<" ";

【讨论】:

以上是关于我想反转我的数组。为啥这段代码给出垃圾值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这段代码不打印我的数组?

为啥我的每个单词反转代码不反转某些单词?

为啥这段代码(在 Matlab 的 MEX 文件中使用 OpenMP)给出不同的结果?

在C中打印反转的字符串/数组

数组初始化给出垃圾值[重复]

为啥选择排序算法的这段代码没有给出输出?