【题目描述和样例】
4 4
.ww.
....
w..w
.ww.
2
5 5
w.w.w
.w.w.
.....
w..ww
...w.
3
0 0
Program ended with exit code: 0
解释一下:比如上面第1行是输入空地的大小,2~5行输入空地的状态,w
代表有水,.
代表没水。然后第6行输出水洼个数(斜线相邻算一个水洼),然后等待用户输入下一组数据。多组输入输出,空地大小为
时退出。
【错误分析和示例代码】
博主首先在自定义函数func上出了错,错因是二维数组作为函数参数的写法问题,注意以下两种问题:
⚠️(1)二维数组名不是指针的指针
设有二维数组int a[10][10]
二维数组名a存储的是第0行地址,a+1是第1行地址……a的类型是int (*)[10]
,意思是指向含10个int类型元素的一维数组或行的指针,所以以下两种方式都是错误的:
void func(char **a,int i,int j,int n,int m)
这会导致错误:Thread 1: EXC_BAD_ACCESS (code=1, address=0x2e80e30a)
void func(char a[][],int i,int j,int n,int m)
这会导致错误:Array has incomplete element type 'char []'
由于程序中a的大小是MAX_N*MAX_M的,所以正确的写法是
void func(char a[MAX_N][MAX_M],int i,int j,int n,int m)
或者
void func(char a[][MAX_M],int i,int j,int n,int m)
或者
void func(char (*a)[MAX_M],int i,int j,int n,int m)
⚠️(2)适当使用getchar()吸收回车
在使用scanf等方式输入字符前,要检查此时是否有’\n’残留在缓冲区未被吸收,如有,需要使用getchar()将其吸收,然后再进行字符的输入。
下面是完整代码,改动痕迹和错误记录均以注释体现:
#include<stdio.h>
#define MAX_N 102
#define MAX_M 102
//void func(char **a,int i,int j,int n,int m){ //Thread 1: EXC_BAD_ACCESS (code=1, address=0x2e80e30a)
//void func(char a[][],int i,int j,int n,int m){ //Array has incomplete element type 'char []'
void func(char a[][MAX_M],int i,int j,int n,int m){
int new_i,new_j;
a[i][j]='.';
for(int dx=-1;dx<=1;dx++){
for(int dy=-1;dy<=1;dy++){
new_i=i+dy;
new_j=j+dx;
if(new_i<n&&new_i>=0&&new_j<m&&new_j>=0&&a[new_i][new_j]=='w')
func(a,new_i,new_j,n,m);
}
}
}
int main(){
char a[MAX_N][MAX_M];
int n,m;
int total=0;
while(scanf("%d %d",&n,&m)==2){
getchar(); //极容易疏忽,如果不加这句,下面的字符输入部分会先吸收上一个scanf结束时的回车
if(n==0&&m==0)break;
else{
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%c",*(a+i)+j);
}
getchar(); //极容易疏忽,如果不加这句,下面的字符输入部分会先吸收上一个scanf结束时的回车
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(a[i][j]=='w'){ //不小心漏写了if,造成的后果是程序将每一个点都当作水洼处理
total++;
func(a,i,j,n,m);
}
}
}
printf("%d\n",total);
}
total=0;
}
return 0;
}