c - C程序中出现 "Abnormal Program Termination"错误的可能原因是什么?

标签 c algorithm

以下代码是在二维数组中将 1 视为岛屿,将 0 视为水来查找岛屿的数量。相邻的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;
   }
}

最佳答案

正如M Oehm已经说过的,问题在于你将一个方 block 标记为零(或者我们说“访问过”)的时间。

当你的函数 MakeZero 发现一个至少有一个相邻方格中包含 1 的方格时,它就会调用自身。由于您在调用 MakeZero 之后将方 block 标记为 0 ,因此每当有两个相邻方 block 包含 1< 时,就会导致堆栈溢出 在你的矩阵中。由于第一个 MakeZero 找到相邻的 1 并调用 MakeZero,后者也找到相邻的 1 并调用 再次 MakeZero ...(如果您从调试器中查看调用堆栈,您可以看到这一点)。

关于 MakeZero 实现的另一件事:您在 MakeZero 中显式处理所有特殊情况,这使得代码相当冗长且难以理解。我建议修改该函数以仅检查输入值是否有效以及平方是否为一。如果是这样,则将该值设置为零,并对所有相邻方 block 调用 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);
         }
      }
   }
}

关于c - C程序中出现 "Abnormal Program Termination"错误的可能原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33194857/

相关文章:

javascript - 如何有效地在 JavaScript 中的唯一字符串中找到相似的字符串?

c++ - 如何将具有递减索引的方程式转换为具有求和的数学方程式?

python - Python 中的 C 风格指针,这是正确的吗?

c++ - 使用 CUDA 并行特征值求解器

c - 如何计算字符串中字符串的出现次数?

c# - 将字符串 "172406"快速转换为整数 17、24、06

algorithm - 这个关于动态调整数组大小的公式是如何得出的?

c - 使用 libcurl 加载 http URL

c - 从c中的文件中删除一个单词

python - Python 中的 3n+1 编程挑战