【问题标题】:Why isn't this code printing my array?为什么这段代码不打印我的数组?
【发布时间】:2011-08-15 18:11:15
【问题描述】:

我在这里有一个整数数组排序程序,但我遇到了一个问题:每当我运行该程序时,我有时会收到“变量 'numbers' 周围的堆栈已损坏”消息,有时它只是重复打印出数字 8。这是我的代码(在 Visual C++ 2010 中编译):

#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;

void swap(int *x, int *y)
{
    int tmp=0;
    tmp = *x;
    *x  = *y;
    *y  = tmp;
    tmp = 0;
}

int main()
{
    int numbers[13] = {8,16,23,487,2,301,48,0,13,10,644,12};

    int size = sizeof(numbers) / sizeof(int);

    //sort

    int i = 0;
    int* a = &numbers[0];
    int* b = &numbers[1];


    while(i < size){

        if(*a > *b){
            swap(a, b);
        }

        *a++;
        *b++;
         i++;
    }

    //Print our results
    int loopIterator = 0;
    int numToPrint = 0;
    while(loopIterator < size){
        cout << numbers[numToPrint] << endl;
        loopIterator++;
    }


    system("PAUSE");

}

【问题讨论】:

  • 和主说:整数应该永远是4... sigh,使用sizeof(int)。
  • int size = sizeof(numbers) / sizeof(int);
  • 上述两种解决方案都不是最优的。更好:size_t size = sizeof numbers / sizeof numbers[0];

标签: c++ arrays pointers loops


【解决方案1】:

首先,您永远不会增加numToPrint,因此您永远不会打印超过numbers[0] 的值。至少将您的代码更改为:

while(loopIterator < size){
    cout << numbers[numToPrint++] << endl;
    loopIterator++;
}

其次,由于您的 while 循环使用测试 i &lt; size,因此在循环的最后一次迭代中,您将访问 numbers 之外的内存以获取您的 b 指针,并可能交换它值到numbers 的最后一个槽中(即a 指向的位置)。您想将测试更改为 i &lt; (size - 1) 以避免这种情况。例如,如果在i == 0 你有a = &amp;numbers[0]b = &amp;numbers[1],那么到i == 12 的时候,你最终会得到a = &amp;numbers[12]b = &amp;numbers[13] ... b 的值在这种情况下指向的是数组的末尾。根据您的编译器如何设置堆栈,以及您在堆栈上分配numbers 的方式,如果您最终以b 指向激活记录数据结构,这实际上可能会对您的程序造成一些破坏你的main() 函数,并反过来破坏它。

【讨论】:

  • 为什么有两个索引?如果他想要一个计数环,他应该使用一个计数环。即for(int i(0); i &lt; size; ++i) cout &lt;&lt; numbers[i] &lt;&lt; endl;
  • 这也行……我只是指出他的代码中的一个错误,以及一个快速修复它的方法,它只增加了两个字符。
【解决方案2】:

我假设您将数组排序作为练习来实现。这并不能真正回答您的问题,但我想我会发布以供参考,无论如何。这是使用 STL 实现预期结果的一种方法:

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

int main()
{
  int numbers[] = { 8, 16, 23, 487, 2, 301, 48, 0, 13, 10, 644, 12 };
  size_t const size = sizeof(numbers) / sizeof(numbers[0]);

  int * const begin = numbers;
  int * const end   = numbers + size;

  std::sort(begin, end);
  std::copy(begin, end, std::ostream_iterator<int>(std::cout, "\n"));
}

【讨论】:

  • 支持 STL。顺便说一句,他还可以使用 std::set 容器并将整个程序缩减到 2 行。
【解决方案3】:

我很确定您在这里遇到了运算符优先级问题:

*b++;

事实上,编译器应该警告你一个没有副作用的运算符(*)。

除此之外,指针 b 将离开数组的末尾,因为它从元素 1 开始并提前 size 次,它最终将指向 numbers[size+1]。如果编译器优化了无用的取消引用,那不会有问题,但在上一次传递中,您调用 swap(numbers+size-1, numbers+size) 并注销数组的末尾,从而导致您检测到的堆栈损坏。

【讨论】:

    【解决方案4】:

    嗯,我立即跳出来的一件事是你永远不会增加 numToPrint,所以它会打印出 numbers[0],size 次数。

    我会把你的印刷部分改写成

    for (int i = 0; i < size; i++)
        cout << numbers[i] << endl;
    

    这样您就可以摆脱代码的打印结果部分,因为上面是做同样事情的更简洁的方法。

    您收到的错误消息可能是因为您正在写入不应该触摸的内存部分。这可能是错误使用“sizeof”的结果。它返回数字中的元素数量,而不是内存大小。建议在实际问题上检查 cmets,以获得第二个问题的正确解决方案。

    【讨论】:

    • 请注意,这是 OP 报告的两个错误之一;)
    • 嘿,是的,只是解决了我确定看到的一件事,继续编辑以回答这两个问题,解决了错误使用 sizeof 转到 yi_H 的方法。
    【解决方案5】:

    这种排序不起作用,因为你只遍历你的数字列表一次,所以它会交换相邻的项目,但不会对列表进行排序(它是冒泡排序的一半实现)

    【讨论】:

    • sizeof numbers 是以字节为单位的大小,而不是元素。除以元素的大小是正确的(应该计算,例如sizeof numbers[0]
    • 好吧,在它锁定之前,我太慢了,无法取消投票。不过,您的回答仍然没有真正回答问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多