Debug日志:用new运算符动态分配二维数组的测试

来源:互联网 发布:枪花乐队知乎 编辑:程序博客网 时间:2024/06/04 23:22

缘起:由学堂在线-清华大学《程序设计基础》-第5章第1题需要的输入输出格式引起。

正确的代码:(由QQ群“C/C++、MFC讨论群”来自浙江的S1xe在我错误的代码基础上改写)

#include <iostream>using namespace std;int main() {    int N = 1;    cin >> N;    int *len = new int[N];    int **array = new int *[N];    for (int i = 0; i < N; i++) {        cin >> len[i];        array[i] = new int[len[i]];        for (int j = 0; j < len[i]; j++)            cin >> array[i][j];    }    cout << endl;    for (int i = 0; i < N; i++) {        cout << len[i] << ' ';        for (int j = 0; j < len[i]; j++)            cout << array[i][j] << ' ';        cout << endl;    }    for (int i = 0; i < N; i++)        delete[] array[i];    delete[] array;    delete[] len;    return 0;}

正确的测试结果:



错误的代码:

#include <iostream>using namespace std;int main(){int N;  //设置需要输入的行数N,也是二维数组第一维的下标 int n;  //设置二维数组第二维的下标 int length;cin >> N;  //给行数N赋值 int **array = new int *[N];  //设置一个N行的二维数组,每一行的首地址是*array[i]   for(int i = 0; i < N; i++)  //针对已输入的行数N,设置循环结构输入各行的数据{cin >> array[i][0];  //每一行的第一个元素确定本行后面的列数n = array[i][0];  //给每行除首元素所在列以外的列数n赋值 length = n + 1;array[i] = new int[length];  //给二维数组每一行的length个元素分配动态空间//**********************************************************//主要错误就在这里:在给array的元素已经赋值的情况下,又调用new给array分配长度空间,这是逻辑上相矛盾的 //**********************************************************for(int j = 1; j < length; j++)  //每行正式输入的第一个元素直到最后一个元素cin >> array[i][j]; } cout << endl;for(int i = 0; i < N; i++){n = array[i][0];length = n + 1;for(int j = 1; j < length; j++)cout << array[i][j] << ' ';cout << endl;}  //测试代码,看能否正常输出for(int i = 0; i < N; i++)delete[] array[i];  //深度内存释放,对每个单元里指针指向的内存都要释放 delete[] array;  //最后释放整个二维数组 return 0; }
错误的测试结果:


之前错误的测试结果已经丢失了,上述二图是参照正确的代码的结构,修改了我的代码以后的运行结果,程序居然崩溃退出!我找了一天都没有找到确凿的原因,但是我猜想:应该是在运行过程中,变量出现了干涉,尤其是与new运算符分配的动态空间出错有关。必须用一个单独的数组来存储每行的第一个元素,不能放在第一个元素然后再用它确定后面的元素个数。这可能违反了编译器的编译顺序,也许逻辑上解释得通,但是编译上行不通,有bug。
PS:刚刚翻了翻群聊记录,S1xe说:“你的代码我看了一遍,主要问题其实在于你的第二层所谓new是错误的,最好把长度信息用另一处来存储”。
启示与经验:编程序要思路清晰、条理分明,不要试图为了减少变量的数量而绕来绕去、玩复杂的技巧——对于初学者,复杂的技巧很可能会玩砸!清晰、明了、简洁——这是编程的三大精华经验!就像下围棋,AlphaGo可以想到所有的可能,我们人类则不可能,也不需要。同样,编程序,我们不可能做到空间绝对最小、时间绝对最少,我们首先要做到正确,那么就要参照这三大经验——清晰、明了、简洁!