C、二维数组,如何在所有 8 个方向上查找特定数字
C, 2D Array, How to find specific number in all 8 directions
您只能输入 0 和 1 作为数组中的值。然后代替所有值为 0 的元素,在所有八个方向上输入该元素周围值为 1 的元素的数量。最后打印二维数组,将 1 的值更改为 *.
这是一个示例:
这是我的代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,m;
scanf("%d%d", &n, &m);
int a[n][m];
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
scanf("%d", &a[i][j]);
if(a[i][j]==1){
a[i][j]=9;
}
}
}
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
int counter=0;
if(a[i][j]==9){
printf("*\t");
}else if(a[i][j]==0){
if(a[i+1][j+1]==9 && i!=n && j!=m) counter++;
if(a[i-1][j-1]==9 && i!=0 && j!=0) counter++;
if(a[i+1][j-1]==9 && i!=n && j!=0) counter++;
if(a[i-1][j+1]==9 && i!=0 && j!=m) counter++;
if(a[i][j+1]==9 && j!=m) counter++;
if(a[i][j-1]==9 && j!=0) counter++;
if(a[i+1][j]==9 && i!=n) counter++;
if(a[i-1][j]==9 && i!=0) counter++;
a[i][j]=counter;
counter=0;
printf("%d\t", a[i][j]);
}
}
printf("\n");
}
return 0;
}
不确定问题是什么,但代码中存在错误 -
例如,您正在通过以下方式访问数组边界:
if(a[i-1][j-1]==9 && i!=0 && j!=0)
当 i 和 j 为零时,您正在读取 a[-1][-1] 的值。改变条件的顺序并首先检查 i 和 j 将防止这种访问。
当您访问矩阵的“边界”时,也会发生同样的情况。
而且,“i!=n && j!=m”条件在循环中始终为真 - 只要 i
但除此之外,其中一些访问实际上是从 数组中读取的,但是从错误的位置读取的。
下面是一个示例:
给定2x2的矩阵
0 1
1 0
这是您的代码生成的结果:
2 *
* 3
显然,'3' 是错误的。
为什么会这样?
二维数组实际上是作为一维数组存储在内存中的,像这样:
0 1 1 0 // this is your data
0 1 2 3 // this is the index in the array (offset from the array start)
并且每个元素都位于从数组开始的 row*columns+column 的偏移量处(即这是在给定 i 和 j 的一维数组中查找索引的公式)。
当您计算最后一个元素(本例中的 a[1][1])的“1”邻居时,您计算两个明显的结果(在 a[1][0] 和 a[0][1]) ,但随后您遇到了这种情况:
if(a[i-1][j+1]==9 && i!=0 && j!=m)
对于最后一个单元格,i 为 1,j 为 1,因此条件的第二部分为真。
但是 a[i-1][j+1]==9 呢?
这引用了 row*columns+column 处的内存,对吧? IE。 (i-1)*2+(j+1),因为那是您尝试访问的内容。将 i 和 j 替换为 1 和 1,您将在上面的一维数组中得到偏移量 2。
这是输入矩阵中的 1(或者实际上是 9,因为你已经替换了它)。
所以你数了两次。
更好地防止“跳出”矩阵(但不一定跳出实际数组)将解决此错误。
您有 UB(未定义行为)。
与(例如):
if (a[i + 1][j + 1] == 9 && i != n && j != m)
然后,a
总是 获取,即使 i
或 j
超出范围。
要解决此问题,请重新排序条款:
if (i != n && j != m && a[i + 1][j + 1] == 9)
现在,如果 i
或 j
超出范围,则 if
将被“短路”:(即 _short 电路评估)和 a
值 不会 被提取。
但是,您的程序输出不正确。您正在手写所有内容。这使得调试变得困难(即哪些行有错误)。
没有明确描述的是,您在给定零点附近的 3x3 内核中对 non-zero 值求和。
硬编码缩放 不太好。假设内核必须是 100x100。我们会编写 10,000 行代码吗?
如果我们重构使用 for
循环,调试起来会容易得多。并且,使用更具描述性的名称而不是 i/j/m/n
:
n hgt
m wid
i y*
j x*
代码如下:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc,char **argv)
{
int hgt, wid;
int counter;
FILE *xf;
--argc;
++argv;
if (argc > 0)
xf = fopen(*argv,"r");
else
xf = stdin;
if (xf == NULL) {
perror(*argv);
exit(1);
}
fscanf(xf,"%d%d", &hgt, &wid);
int a[hgt][wid];
for (int ycur = 0; ycur < hgt; ycur++) {
for (int xcur = 0; xcur < wid; xcur++) {
int val;
fscanf(xf,"%d", &val);
if (val == 1)
val = 9;
a[ycur][xcur] = val;
}
}
for (int yctr = 0; yctr < hgt; yctr++) {
for (int xctr = 0; xctr < wid; xctr++) {
if (a[yctr][xctr] == 9) {
printf("*\t");
continue;
}
counter = 0;
for (int yoff = -1; yoff <= 1; yoff++) {
int ycur = yctr + yoff;
if (ycur < 0)
continue;
if (ycur >= hgt)
continue;
for (int xoff = -1; xoff <= 1; xoff++) {
int xcur = xctr + xoff;
if (xcur < 0)
continue;
if (xcur >= wid)
continue;
counter += (a[ycur][xcur] == 9);
}
}
printf("%d\t",counter);
}
printf("\n");
}
return 0;
}
这是您的示例输入的程序输出:
* 1 1 2 *
2 2 2 * 3
* 1 2 * 2
您只能输入 0 和 1 作为数组中的值。然后代替所有值为 0 的元素,在所有八个方向上输入该元素周围值为 1 的元素的数量。最后打印二维数组,将 1 的值更改为 *.
这是一个示例:
这是我的代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,m;
scanf("%d%d", &n, &m);
int a[n][m];
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
scanf("%d", &a[i][j]);
if(a[i][j]==1){
a[i][j]=9;
}
}
}
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
int counter=0;
if(a[i][j]==9){
printf("*\t");
}else if(a[i][j]==0){
if(a[i+1][j+1]==9 && i!=n && j!=m) counter++;
if(a[i-1][j-1]==9 && i!=0 && j!=0) counter++;
if(a[i+1][j-1]==9 && i!=n && j!=0) counter++;
if(a[i-1][j+1]==9 && i!=0 && j!=m) counter++;
if(a[i][j+1]==9 && j!=m) counter++;
if(a[i][j-1]==9 && j!=0) counter++;
if(a[i+1][j]==9 && i!=n) counter++;
if(a[i-1][j]==9 && i!=0) counter++;
a[i][j]=counter;
counter=0;
printf("%d\t", a[i][j]);
}
}
printf("\n");
}
return 0;
}
不确定问题是什么,但代码中存在错误 - 例如,您正在通过以下方式访问数组边界:
if(a[i-1][j-1]==9 && i!=0 && j!=0)
当 i 和 j 为零时,您正在读取 a[-1][-1] 的值。改变条件的顺序并首先检查 i 和 j 将防止这种访问。
当您访问矩阵的“边界”时,也会发生同样的情况。
而且,“i!=n && j!=m”条件在循环中始终为真 - 只要 i 但除此之外,其中一些访问实际上是从 数组中读取的,但是从错误的位置读取的。
下面是一个示例: 给定2x2的矩阵 这是您的代码生成的结果: 显然,'3' 是错误的。 为什么会这样?
二维数组实际上是作为一维数组存储在内存中的,像这样: 并且每个元素都位于从数组开始的 row*columns+column 的偏移量处(即这是在给定 i 和 j 的一维数组中查找索引的公式)。
当您计算最后一个元素(本例中的 a[1][1])的“1”邻居时,您计算两个明显的结果(在 a[1][0] 和 a[0][1]) ,但随后您遇到了这种情况: 对于最后一个单元格,i 为 1,j 为 1,因此条件的第二部分为真。
但是 a[i-1][j+1]==9 呢?
这引用了 row*columns+column 处的内存,对吧? IE。 (i-1)*2+(j+1),因为那是您尝试访问的内容。将 i 和 j 替换为 1 和 1,您将在上面的一维数组中得到偏移量 2。
这是输入矩阵中的 1(或者实际上是 9,因为你已经替换了它)。
所以你数了两次。 更好地防止“跳出”矩阵(但不一定跳出实际数组)将解决此错误。0 1
1 0
2 *
* 3
0 1 1 0 // this is your data
0 1 2 3 // this is the index in the array (offset from the array start)
if(a[i-1][j+1]==9 && i!=0 && j!=m)
您有 UB(未定义行为)。
与(例如):
if (a[i + 1][j + 1] == 9 && i != n && j != m)
然后,a
总是 获取,即使 i
或 j
超出范围。
要解决此问题,请重新排序条款:
if (i != n && j != m && a[i + 1][j + 1] == 9)
现在,如果 i
或 j
超出范围,则 if
将被“短路”:(即 _short 电路评估)和 a
值 不会 被提取。
但是,您的程序输出不正确。您正在手写所有内容。这使得调试变得困难(即哪些行有错误)。
没有明确描述的是,您在给定零点附近的 3x3 内核中对 non-zero 值求和。
硬编码缩放 不太好。假设内核必须是 100x100。我们会编写 10,000 行代码吗?
如果我们重构使用 for
循环,调试起来会容易得多。并且,使用更具描述性的名称而不是 i/j/m/n
:
n hgt
m wid
i y*
j x*
代码如下:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc,char **argv)
{
int hgt, wid;
int counter;
FILE *xf;
--argc;
++argv;
if (argc > 0)
xf = fopen(*argv,"r");
else
xf = stdin;
if (xf == NULL) {
perror(*argv);
exit(1);
}
fscanf(xf,"%d%d", &hgt, &wid);
int a[hgt][wid];
for (int ycur = 0; ycur < hgt; ycur++) {
for (int xcur = 0; xcur < wid; xcur++) {
int val;
fscanf(xf,"%d", &val);
if (val == 1)
val = 9;
a[ycur][xcur] = val;
}
}
for (int yctr = 0; yctr < hgt; yctr++) {
for (int xctr = 0; xctr < wid; xctr++) {
if (a[yctr][xctr] == 9) {
printf("*\t");
continue;
}
counter = 0;
for (int yoff = -1; yoff <= 1; yoff++) {
int ycur = yctr + yoff;
if (ycur < 0)
continue;
if (ycur >= hgt)
continue;
for (int xoff = -1; xoff <= 1; xoff++) {
int xcur = xctr + xoff;
if (xcur < 0)
continue;
if (xcur >= wid)
continue;
counter += (a[ycur][xcur] == 9);
}
}
printf("%d\t",counter);
}
printf("\n");
}
return 0;
}
这是您的示例输入的程序输出:
* 1 1 2 *
2 2 2 * 3
* 1 2 * 2