簡體   English   中英

C程序中“程序異常終止”錯誤的可能原因是什么?

[英]What are the possible causes of “Abnormal Program Termination” error in a C Program?

以下代碼通過在2d數組中將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;
   }
}

您的程序引發了堆棧溢出,因為遞歸函數MakeZero()從未達到基本情況。 使用您提供的相同輸入示例,僅添加一個printf ("%d %d\\n", i, j); Makezero的最后else條件下,程序將無限期地輸出1 1並且您永遠不會達到停止程序的條件(i > m-1 || j > n-1) ,因為m-1n-1的值n-12i = 1j = 1表示。

建議:嘗試找出矩陣a中至少一個值為0發生的情況,因為堆棧溢出似乎僅在這種情況下才發生。

正如M Oehm所說的那樣,問題在於將正方形標記為零的時間(或者說“訪問”)。

只要函數MakeZero在至少一個相鄰正方形中找到一個正方形,就會調用自己。 因為調用MakeZero 之后將正方形標記為0 MakeZero每當矩陣中有兩個相鄰的正方形包含1時,就會導致堆棧溢出。 由於第一個MakeZero找到一個相鄰的1並調用MakeZero ,后者又找到一個相鄰的1並再次調用MakeZero ...(如果從調試器中查看調用堆棧,則可以看到此信息)。

關於你的另一件事MakeZero實現:你被明確處理中的所有特殊情況MakeZero這使得代碼非常長而且難於理解。 我建議將函數修改為僅檢查輸入值是否有效且平方為一。 如果是這樣,則將該值設置為零,並為所有相鄰的正方形調用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);
         }
      }
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM