前两天老是布置了一个练习题,题目如下:
a,b数组都是从小到大排序的,将a数组和b数组中的数,写到c中,c也是从小到大排序的并且要求如果两个数字相同的话,只保留两个相同数字中的一个。
当时,写出的代码如下:
#include <stdio.h>
int main(void)
{
int a[] = {1,2,4,7,8,9,10,12,16,18};
int b[] = {1,2,6,7,8,9,10,17,19,29};
int c[20] = {0};
int ACount = 0; //a数组中的位置
int BCount = 0; //b数组中的位置
int CCount = 0;
for(int k = 0; k < 20; k++)
{
if(a[ACount] < b[BCount])
{
c[CCount++] = a[ACount++];
continue;
}
else if(a[ACount] == b[BCount])
{
c[CCount++] = a[ACount++];
BCount++;
continue;
}
else
{
c[CCount++] = b[BCount++];
continue;
}
}
for(int i = 0; i < 20; i++)
printf("%d ",c[i]);
printf("\n");
return 0;
}
运行结果如下:
在排序中出现了垃圾值,回头看代码,发现了问题,在上面的程序代码中没有对ACount和BCount进行边界检查,导致了先比较完的数组(这里是A数组)的count指向了一个越界元素上(在这里就是-858993460),由于该值是一个极小值,比B数组的值都要小,所以执行这句:
if(a[ACount] < b[BCount])
{
c[CCount++] = a[ACount++];
continue;
}
将-858993460赋值到了c[12]的位置上,完成这个动作后,ACount++,ACount根据运行结果来看是指向了一个大值,所以运行该句:
else
{
c[CCount++] = b[BCount++];
continue;
}
将19,29分别赋值给了c数组,随后BCount也越出了数组容量,到了数组后一个位置,其数据也为-858993460,与ACount指的大值相比,还是小,所以运行上面的else语句,将-858993460赋值到c数组中,BCount++,而遇到的下一个元素依然是-858993460,又运行else将其赋值到了c数组中。
随后BCount++,根据运行结果来看,这下BCount指向到了a数组中的元素,而ACount的指向依然是一个较大数,所以依然执行else语句,直到k = 20 循环结束.
后经论坛大大的帮助,修改了程序,代码如下:
#include <stdio.h>
int main(void)
{
int a[] = {1,2,4,7,8,9,10,12,16,18};
int b[] = {1,2,6,7,8,9,10,17,19,29};
int c[sizeof(a)/sizeof(a[0]) + sizeof(b)/sizeof(b[0])];
int ACount = 0; //a数组中的位置
int BCount = 0; //b数组中的位置
int CCount = 0;
while(ACount < sizeof(a)/sizeof(a[0]) && BCount < sizeof(b)/sizeof(b[0]))
{
if(a[ACount] < b[BCount])
c[CCount++] = a[ACount++];
else if(a[ACount] == b[BCount])
{
c[CCount++] = a[ACount++];
BCount++;
}
else if(a[ACount] > b[BCount])
c[CCount++] = b[BCount++];
}
while (ACount != sizeof(a) / sizeof(a[0]))
c[CCount++] = a[ACount++];
while (BCount != sizeof(b) / sizeof(b[0]))
c[CCount++] = b[BCount++];
for(int i = 0; i < CCount; i++)
printf("%d ",c[i]);
printf("\n");
return 0;
}
运行结果如下:
结果正常。
得到的推论:
-858993460可能是一个极为特殊的值,可能代表着数组的界限(上界和下界)。