首页 > 代码库 > 从一道简单模拟题看数组越界以及其他

从一道简单模拟题看数组越界以及其他

技术分享

题目要求比较明确,可能做起来难度不是很大。

但我这道题用了比较久的时间。

原因是我用了一种特别容易错的方法。我在移动数组元素的时候采用不用辅助数组由前往后复制的方法(想来我也真是没事找事干),然后在这种方法下我起初交了许多遍WA,然后自己经过长时间的测试终于发现了问题所在,不止一个,各种逻辑错误。

总结主要有以下几点:

  • 分类讨论不够明确,不够完整
  • 没有考虑到前边操作对后边数据的影响
  • 没有意识到数组越界的后果(a[-1],a[maxn])

要发现和解决这些问题并不容易,需要有很高的调试技巧,通过这个题的练习,也积累了一些经验:在不使用gdb的情况下,通过在恰当的位置输出中间值来进行测试是相当重要的。关键在于如何选择恰当的位置。选择的位置不好,看不出啥问题来,还显着输出结果很乱。

下边展开说一下导致逻辑错误的三大原因。

首先,分类讨论的问题。

分类讨论首先想到的是头尾可能需要特殊考虑。比如这题。在最后插入输入的情况下不需要往后复制东西,要是执意复制可能导致数组越界。

这就引出了第三个问题,数组越界。

数组越界是一个神奇的东西。我第一次发现A[-1]竟然是一个合法的东西(意思是这个数组前边的数据),第一次发现数组越界一位之后恰好把定义在他后边的变量修改了导致输出超限。导致这个的原因经过百度与C程序内存结构有关系。

关于第二个问题,我的错误在于循环结束条件已经在循环中被修改过了。不仔细找真的不太好改此类错误,以后应该加强这方面经验的积累。

下边贴一下这次作业的代码,以备日后查看。

#include <stdio.h>#define MAX_SIZE 1001int getkey(int key[]){    int k;    scanf("%d",&k);    for(int i=0;i<k;i++)scanf("%d",&key[i]);    return k;}int getarray(int array[]){    int i=0;    while(scanf("%d",&array[i])==1&&array[i]!=0)i++;    if(i<MAX_SIZE-1)array[MAX_SIZE-1]=-1;    return 0;}int insert(int array[], int key, int vol){    int i=0;    if(array[vol]==0)return -2;    while(key>array[i]&&array[i]!=0)i++;    if(array[i]==key)return -1;    else{        int t1=array[i];        int t2=1;        int j=i;        if(t1)for( j=i;!j||t2;j++){            t2=array[j+1];            array[j+1]=t1;            t1=t2;        }        array[j+1]=0;        array[i]=key;        return i;    }}int result(int flag){    if(flag==-1)printf("The key is already in this array!");    else if(flag==-2)printf("The array if full!");    else {        printf("The key is inserted in position %d.",flag);    }    printf("\n");    return 0;}int main(){    int array[MAX_SIZE], cases, ca, i, key[MAX_SIZE], size;    scanf("%d", &cases);    for(ca = 1; ca <= cases; ca++)    {        getarray(array);        size = getkey(key);        printf("Case %d:\n", ca);        for(i = 0; i < size; i++){            result(insert(array, key[i], MAX_SIZE - 1));           // array[1001]=2;        }    }    return 0;}

 

从一道简单模拟题看数组越界以及其他