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

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

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

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

总结主要有以下几点:

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

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

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

首先,分类讨论的问题。

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

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

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

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

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

#include <stdio.h>
#define MAX_SIZE 1001
int 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;
}
时间: 2024-10-12 06:28:25

从一道简单模拟题看数组越界以及其他的相关文章

FZU Problem 2034 Password table (简单模拟题)

这种简单题做了好长时间,我是不是有点逗? 地址:http://acm.fzu.edu.cn/problem.php?pid=2034 不解释了,自己看吧,练手的好题 上个代码吧 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> #include <string.h> #include <stdlib.h>

HDU 4772 Zhuge Liang&#39;s Password (简单模拟题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4772 题面: Zhuge Liang's Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1404    Accepted Submission(s): 926 Problem Description In the anc

POJ 1008 简单模拟题

e.... 虽然这是一道灰常简单的模拟题.但是米做的时候没有读懂第二个日历的计时方法.然后捏.敲完之后华丽的WA了进一个点.坑点就在一年的最后一天你是该输出本年的.e ...但是我好想并没有..看discuss里好想被坑的人还不少.总天数能直接整除260的时候.年数要减1. 不喜欢做模拟.....5555.... 附代码: #include<stdio.h>#include<string.h>#include<iostream>#include<string>

HDU 5059 Help him(简单模拟题)

http://acm.hdu.edu.cn/showproblem.php?pid=5059 题目大意: 给定一个字符串,如果这个字符串是一个整数,并且这个整数在[a,b]的范围之内(包括a,b),那就输出YES,其它的都是NO. 这个字符串是整数的条件: 1.如果它是正整数,它只包含前导不是0的数(这个数前面没有零). 2.如果它是负整数,只包含一个'-'符号,任然没有前导0. 3.除此之外都不是非法的 解题思路: http://bestcoder.hdu.edu.cn/ 这里有 要注意: 0

HDU 1234 简单模拟题

题目很简单不多说了,我只是觉得这题目的输入方式还是很有特点的 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 7 struct People{ 8 char name[20]; 9 int h1 , h2 , m1 , m2 , s1 , s2; 10 }p[10005]; 11 12

又一道简单的题

题目描述 输入一个四个数字组成的整数 n,你的任务是数一数有多少种方法,恰好修改一个数字,把它 变成一个完全平方数(不能把首位修改成 0).比如 n=7844,有两种方法:3844=622 和 7744=882. 输入 输入第一行为整数 T (1<=T<=1000),即测试数据的组数,以后每行包含一个整数 n (1000<=n<=9999). 输出 对于每组数据,输出恰好修改一个数字,把 n变成完全平方数的方案数 样例输入 2 7844 9121 样例输出 Case 1: 2 Ca

关于括号的简单模拟题

description 给定一个括号字符数组S,S可以用两个整数数组P和W来描述,其中: 数组P中的元素Pi定义为:第i个右括号前面有Pi个左括号: 数组W中的元素Wi定义为,第i个右括号和其配对的左括号之间所包含的完整的括号的对数. 现在给你P数组,让你求出该字符数组S所对应的W数组. 比如下面这个例子 S (((()()()))) P 4 5 6666 W 1 1 1456 input 输入第一行是一个整数t (1 <= t <= 10), 表示有t组测试数据.每组数据第一行是一个整数n

HihoCoder1052基因工程(简单模拟题)

描述 小Hi和小Ho正在进行一项基因工程实验.他们要修改一段长度为N的DNA序列,使得这段DNA上最前面的K个碱基组成的序列与最后面的K个碱基组成的序列完全一致. 例如对于序列"ATCGATAC"和K=2,可以通过将第二个碱基修改为"C"使得最前面2个碱基与最后面两个碱基都为"AC".当然还存在其他修改方法,例如将最后一个碱基改为"T",或者直接将最前面两个和最后面两个碱基都修改为"GG". 小Hi和小Ho

HDU ACM 1035 Robot Motion 简单模拟题

分析:一步步的走,走出矩阵则说明没有环,若走到已经走过的地方,说明有环,按格式输出结果,OK. #include<iostream> using namespace std; #define N 15 int dir[4][2]={-1,0,1,0,0,-1,0,1}; char map[N][N]; int vis[N][N]; char ch[]="NSWE"; int n,m; int id(char c) { int i; for(i=0;i<4;i++) i