C程序中“异常程序终止”错误的可能原因是什么?

时间:2015-10-18 06:04:41

标签: c algorithm

以下代码是通过将1视为岛而0视为2d数组中的水来查找离岛数。相邻的1个属于同一个岛屿,岛屿可以是任何形状。这意味着 1 0 1
0 1 0
1 0 1
应该给岛的数量为1.这个代码运行并打印一个2 x 2矩阵的东西,但显示任何更高阶矩阵的“异常终止错误”。代码是错误的,如何克服错误?我只是尝试递归地使相邻元素为零,但最终出现了这个错误。

#include <stdio.h>
#include <conio.h>

int a[10][10],m,n;
int islands=0;

void MakeZero(int,int);

void main()
{
   int i,j;
   clrscr();
   printf("Enter the number of rows and columns :");
   scanf("%d%d",&m,&n);
   printf("Enter the matrix of 0s and 1s\n");
   for(i=0;i<m;i++){
      for(j=0;j<n;j++){
         scanf("%d",&a[i][j]);
      }
   }
   printf("Input Matrix is :\n");
   for(i=0;i<m;i++){
      for(j=0;j<n;j++){
         printf("%d ",a[i][j]);
      }printf("\n");
   }

   printf("The Number of Islands is :\n");
   for(i=0;i<m;i++){
      for(j=0;j<n;j++){
         if(a[i][j])
         {islands++;
            MakeZero(i,j); }
      }
   }
   printf("%d",islands);
   getch();
}

void MakeZero(int i,int j)
{
   if(i>m-1||j>n-1)
      return;
   else if(i==0&&j==0)
   {
      if(a[i][j+1]==1)MakeZero(i,j+1);
      if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
      if(a[i+1][j]==1)MakeZero(i+1,j);
      a[i][j+1]=a[i+1][j+1]=a[i+1][j]=0;
   }
   else if(i==m-1&&j==0)
   {
      if(a[i-1][j]==1)MakeZero(i-1,j);
      if(a[i][j+1]==1)MakeZero(i,j+1);
      if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
      a[i-1][j]=a[i][j+1]=a[i-1][j+1]=0;
   }
   else if(i==0&&j==n-1)
   {
      if(a[i][j-1]==1)MakeZero(i,j-1);
      if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
      if(a[i+1][j]==1)MakeZero(i+1,j);
      a[i][j-1]=a[i+1][j-1]=a[i+1][j]=0;
   }
   else if(i==m-1&&j==n-1)
   {
      if(a[i][j-1]==1)MakeZero(i,j-1);
      if(a[i-1][j]==1)MakeZero(i-1,j);
      if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
      a[i][j-1]=a[i-1][j]=a[i-1][j-1]=0;
   }
   else if(i==0&&(j>0&&j<n-1))
   {
      if(a[i][j-1]==1)MakeZero(i,j-1);
      if(a[i][j+1]==1)MakeZero(i,j+1);
      if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
      if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
      if(a[i+1][j]==1)MakeZero(i+1,j);
      a[i][j-1]=a[i][j+1]=a[i+1][j-1]=a[i+1][j+1]=a[i+1][j]=0;
   }
   else if(i==m-1&&(j>0&&j<n-1))
   {
      if(a[i][j-1]==1)MakeZero(i,j-1);
      if(a[i][j+1]==1)MakeZero(i,j+1);
      if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
      if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
      if(a[i-1][j]==1)MakeZero(i-1,j);
      a[i][j-1]=a[i][j+1]=a[i-1][j-1]=a[i-1][j+1]=a[i-1][j]=0;
   }
   else if(j==0&&(i>0&&i<m-1))
   {
      if(a[i-1][j]==1)MakeZero(i-1,j);
      if(a[i+1][j]==1)MakeZero(i+1,j);
      if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
      if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
      if(a[i][j+1]==1)MakeZero(i,j+1);
      a[i-1][j]=a[i+1][j]=a[i-1][j+1]=a[i+1][j+1]=a[i][j+1]=0;
   }
   else if(j==n-1&&(i>0&&i<m-1))
   {
      if(a[i-1][j]==1)MakeZero(i-1,j);
      if(a[i+1][j]==1)MakeZero(i+1,j);
      if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
      if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
      if(a[i][j-1]==1)MakeZero(i,j-1);
      a[i-1][j]=a[i+1][j]=a[i-1][j-1]=a[i+1][j-1]=a[i][j-1]=0;
   }
   else
   {
      if(a[i-1][j]==1)MakeZero(i-1,j);
      if(a[i+1][j]==1)MakeZero(i+1,j);
      if(a[i-1][j-1]==1)MakeZero(i-1,j-1);
      if(a[i+1][j-1]==1)MakeZero(i+1,j-1);
      if(a[i][j-1]==1)MakeZero(i,j-1);
      if(a[i][j+1]==1)MakeZero(i,j+1);
      if(a[i-1][j+1]==1)MakeZero(i-1,j+1);
      if(a[i+1][j+1]==1)MakeZero(i+1,j+1);
      a[i-1][j]=a[i+1][j]=a[i-1][j-1]=a[i+1][j-1]=a[i][j-1]=a[i][j+1]=a[i-1][j+1]=a[i+1][j+1]=0;
   }
}

2 个答案:

答案 0 :(得分:0)

您的程序会引发堆栈溢出,因为递归函数MakeZero()永远不会达到基本情况。使用您提供的相同输入示例,只需在printf ("%d %d\n", i, j);的最后else条件中添加Makezero,程序将无限期地输出1 1,您将永远无法达到此条件(i > m-1 || j > n-1)停止该计划,因为m-1n-1的值为2i = 1j = 1为eternum。

建议:当矩阵a中至少有一个值为0时,尝试找出正在发生的事情,因为堆栈溢出似乎只发生在这种情况下。

答案 1 :(得分:0)

正如 M Oehm 已经说过,问题是你将一个正方形标记为零的时间(或者让他们说&#34;访问&#34;)。

当函数MakeZero找到一个至少有一个相邻正方形的正方形时,它会调用自身。由于您在调用0之后将方块标记为MakeZero ,因此只要矩阵中有两个包含1的相邻方块,就会导致堆栈溢出。由于第一个MakeZero找到了相邻的1,并且调用了MakeZero,它们也找到了相邻的1并再次调用了MakeZero ...(如果你从调试器中查看调用堆栈。)

关于MakeZero实现的另一个问题:您明确处理MakeZero中的所有特殊情况,这使得代码非常冗长且难以理解。我建议修改函数以仅检查输入值是否有效且方形是否为1。如果是这样,则将值设置为零,并为所有相邻方块调用MakeZero(无论矩阵内的当前位置如何)。实现如下所示:

void MakeZero(int i, int j)
{
   int x, y;

   if ((i >= 0) && (i < m) &&   /* i index valid? */
       (j >= 0) && (j < n) &&   /* j index valid? */
       (a[i][j] == 1))          /* square is an island? */
   {
      a[i][j] = 0;   /* remove 1 from matrix !!! */

      /* iterate all surrounding squares */
      for (x = (i - 1); x <= (i + 1); x++)
      {
         for (y = (j - 1); y <= (j + 1); y++)
         {
            MakeZero(x, y);
         }
      }
   }
}