【问题标题】:Segmentation Fault for 2d array in CC中二维数组的分段错误
【发布时间】:2016-05-07 17:43:37
【问题描述】:

The orange crosses are made from 'G' of the matrix and are valid. Blue ones are made from 'B' and are invalid

以下代码用于从 2D 数组(由“G”和“B”组成。)中找到 2 个最大可能的交叉区域。十字架应由“G”组成。 以下代码在扫描 2D 矩阵时/之后给我分段错误。请帮忙!!

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
int i,j,k,l,p,q;
char M[10][10];
int m, n;
int min=0;
int rl=0;
int max1=1;
int max2=1;
int area;
int tarea;
int cu=0;
scanf("%d",&n);
scanf("%d",&m);
//matrix scan
for(i=0;i<n;i++){
  for(j=0;j<m;j++){
    scanf("%c",&M[i][j]);

  }
}
 // finding first cross

for(i=0;i<n;i++){
   for(j=0;j<n;j++){
     k=j;
     l=k;
    p=i;
    q=i;
    while(M[i][k]!='B' || M[i][l]!='B' || l!=m || k!=0){
        k--;
        l++;
        rl++;
    }

    while(M[p][j]!='B' || M[q][j]!='B' || p!=0 || q!=n){
        p--;
        q++;
        cu++;
    }
    if(rl>cu){
    min=cu;
    }
    else
    min=rl;
    area=min*4+1;
    if(area>max2){
    max2=area;
    }
    if(area>max1){
    max1=area;
    }

    }
  }

tarea=max1+max2;
printf("%d",tarea);

return 0;
}

【问题讨论】:

  • 尝试阅读的代码有点像灾难,但我看不到边界测试(您的数组是 10x10,但您从不检查 m 或 n 以验证它们不会超过. 还要注意,在调试器中运行它会给你一个答案,就像 SO 一样快。
  • 您没有给出任何输入示例。另外,使用调试器。您将 i 和 j 都循环到 n,也许这就是问题所在?
  • 为了便于我们人类理解和阅读,1) 请一致地缩进代码。在每个左大括号 '{' 后缩进。在每个右大括号 '}' 之前取消缩进,即使可选大括号实际上不在代码中,也执行缩进。 2) 使用有意义的变量名。 M、p、q、rl、cu 等没有意义。 3) 用一个空行分隔代码块(for、if、else、while、do...while、switch、case、default)
  • 当需要用户输入时(参见对scanf()的调用),总是告诉用户他们应该输入什么。否则,用户将盯着空白屏幕,光标闪烁,不知道下一步该做什么。
  • 作为有意义名称的示例:m 可以是 numRows,n 可以是 numCols。同样,在现代C语言中,如果先输入行数和列数,然后将矩阵M声明为:char M[numRows][numCols];,那么超出矩阵边界的风险将大大降低,甚至可能消除

标签: c multidimensional-array segmentation-fault


【解决方案1】:

您的两个while 循环很容易产生对数组M 的越界访问。例如,考虑...

while(M[i][k]!='B' || M[i][l]!='B' || l!=m || k!=0){
    k--;
    l++;
    rl++;
}

... 在第一次通过包含循环时,i、k 和 l 最初都是零。进一步假设M[0][0] 的值不同于'B'。然后将执行循环体,导致k 取值-1,然后再次评估控制表达式,导致尝试读取M[0][-1] 的值。结果是未定义的,但分段错误(当时或以后)是完全合理的。

您需要先进行边界测试,并且您需要使用&amp;&amp; 而不是|| 来确保在达到边界时实际上退出循环。我并不清楚你想在边缘做什么,但总体思路如下:

while((k > 0) && (l < m) && (M[i][k] != 'B' || M[i][l] != 'B')) {
    k--;
    l++;
    rl++;
}

同样适用于您的其他 while 循环。

这些不是唯一的问题,但它们可能是造成您所询问的行为的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-11
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 2012-09-09
    • 2019-01-28
    • 1970-01-01
    相关资源
    最近更新 更多