指定行数列数,打印出二维数组中对应元素的值。

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

void print(int *s);
/*这是一个指定行数列数,打印出二维数组中对应元素的值的程序。*/
void main()
{

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*p)[4];
p=a;

print(*p);
system("pause");
}

void print(int *s)
{
int i,j,a;

x:
printf("横向=");
scanf("%d",&i);
if(i>2||i<0)
{
goto x;
}//如果用户输入错误,则要求重新输入。

y:
printf("纵向=");
scanf("%d",&j);
if(j>3||j<0)
{
goto y;
}//如果用户输入错误,则要求重新输入。

a=*( s + j + ( i*4 ));//取得纵向的值后,乘上行数便是要求的值。
//这里是我最头痛的地方,出于无奈才这么写了。为什么用“*(*(s+i)+j)”就会提示非法的间接寻址?
printf("a[%d][%d]=%d",i,j,a);

}

void print(int *s){} ;
你通过 *s 来传递2维 数组。也就是 把2维数组排成 一列横队,并 传递 了 数组 的首地址。
打印某元素,只要找到 这个元素 在 这个队中 的 第几个 就可以了。

c 语言,2维数组 排成 一列横队 时的 次序是:
第一行 第一列,第一行 第二列,第一行 第三列,第一行 第四列,
第二行 第一列,第二行 第二列,第二行 第三列,第二行 第四列,
第三行 第一列,第三行 第二列,第三行 第三列,第三行 第四列,
A[i,j]:
a[0,0], a[0,1],a[0,2],a[0,3]
a[1,0], a[1,1],a[1,2],a[1,3]
a[2,0], a[2,1],a[2,2],a[2,3]
s[k]:
s[0],s[1],s[2],s[3]
s[4],s[5],s[6],s[7]
s[8],s[9],s[10],s[11]
对比看出,对于1行有4列的数组:
k = i * 4 + j
A[i,j] == s[i * 4 + j];
======================
c 语言语句中,中括号是“运算符”,
并有 恒等式:
x[i] == *(x+i)
s[i * 4 + j] 套用 恒等式 化为 *(s + i *4 + j)
这就是你的 a = *( s + j + ( i*4 ));
其实,你写 a = s[i * 4 + j]; 也可以,也更容易理解。

===
函数形参 不是 int **s, 所以 *(*(s+i)+j) 就不对了。追问

如果要写成*(*(s+i)+j)的形式,应该如何定义呢?

追答

那么 形参 用 int **s, 接着 你的调用 方法和实参也要作相应调整。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-01-25

/*

0 横向,1 纵向 : 1

  1  5  9

  2  6 10

  3  7 11

  4  8 12

请按任意键继续. . .

Press any key to continue

*/

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

void print(int a[][4],int m, int n);
/*这是一个指定行数列数,打印出二维数组中对应元素的值的程序。*/

int main() {
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
print(a,3,4);
system("pause");
return 0;
}

void print(int a[][4],int m, int n) {
int i,j,an;
printf("0 横向,1 纵向 : ");
scanf("%d",&an);
if(an) {
for(i = 0; i < n; ++i) {
for(j = 0; j < m; ++j)
printf("%3d",a[j][i]);
printf("\n");
}
}
else {
for(i = 0; i < m; ++i) {
for(j = 0; j < n; ++j)
printf("%3d",a[i][j]);
printf("\n");
}
}
}