二维数组传参传值

二维数组传参传值
二维数组传参传值

二维数组传参||传值

先给出问题:

像下面这样的数组,在函数中如何传参?也就是说如何保证虚参与实参类型一致。

char str_arr[3][10] = {"yes","no","uncertain"};

char *str_array[] = {"yes","no","unsure"};

函数原型:

void func1( char (*a)[10] )

void func2( char **a )

调用:

func1( str_arr );

func2( str_array);

如果向func2()中传入str_arr会怎么样呢?编译器会警告:传递参数 1 (属于‘func2’)时在不兼容的指针类型间转换。即虚参与实参类型不一致。

同理,也不能向func1()中传入str_array。

我们给出完整的测试程序:

/********二维数组传参测试程序***************/

#include

void func1( char (*a)[10])

{

int i;

for(i=0;i<3;i++)

printf("%s/n",a[i]);

}

void func2( char **a )

{

int i;

for(i=0;i<3;i++)

printf("%s/n",*(a+i));

}

int main()

{

char str_arr[3][10] = {"yes","no","uncertain"};

char *str_array[] = {"yes","no","unsure"};

char *str[3] = {"a","b","c"};/*这两种表达效果一样*/

func1(str_arr);

func2(str_array);

return 0;

}

/******************end*******************/

运行结果:

[root@localhost ansi_c]# gcc test.c

[root@localhost ansi_c]# ./a.out

yes

no

uncertain

yes

no

unsure

[root@localhost ansi_c]#

如果将

func1(str_arr);

func2(str_array);

改成:

func1(str_array);

func2(str_arr);

会怎么呢?

[root@localhost ansi_c]# gcc test.c

test.c: 在函数‘main’ 中:

test.c:22: 警告:传递参数1 (属于‘func1’)时在不兼容的指针类型间转换test.c:23: 警告:传递参数1 (属于‘func2’)时在不兼容的指针类型间转换

这两种数组的正确赋值应该如下:

char str_arr[3][10] = {"yes","no","uncertain"};

char *str_array[] = {"yes","no","unsure"};

char (*pa)[10] = str_arr;

char **p = str_array;

pa和p才是和他们相一致的类型。

当然,如果不是传参的话,在main()函数中就不会发生这么多烦恼了。/*************非传参时的情况************************/

#include

int main()

{

char str_arr[3][10] = {"yes","no","uncertain"};

char *str_array[] = {"yes","no","unsure"};

char *str[3] = {"a","b","c"};

int i;

for(i=0;i<3;i++)

printf("%s/n",str_arr[i]);

for(i=0;i<3;i++)

printf("%s/n",str_array[i]);

return 0;

}

/*************************************/

运行结果:

[root@localhost ansi_c]# gcc test1.c

[root@localhost ansi_c]# ./a.out

yes

no

uncertain

yes

no

unsure

[root@localhost ansi_c]#

这说明了一点,在没传参之前,main()函数清楚它们都是二维数组。对于上面给出的两种函数原型:函数原型:

void func1( char (*a)[10] )

void func2( char **a )

这两种传参方法有什么不同呢?这们对实参有什么要求呢?

上面只是抛出了一个问题,我在这里的主题是想搞清楚二维数组传参有什么奥秘,而非只针对这一个问题提出解决方法。

后面从基础的开始讨论。

我们先看看教材上怎么讲这一块的,

谭浩强的《C程序设计》二维数组作为参数传递,原文如下(略有改变,请原谅):

[原文开始]

可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以可以指定所有维数的大小,也可以省略第一维的大小说明,如:

void Func(int array[3][10]);

void Func(int array[][10]);

二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是不合法的:void Func(int array[][]);

因为从实参传递来的是数组的起始地址,在内存中按数组排列规则存放(按行存放),而并不区分行和列,如果在形参中不说明列数,则系统无法决定应为多少行多少列,不能只指定一维而不指定第二维,下面写法是错误的:

void Func(int array[3][]);

实参数组维数可以大于形参数组,例如实参数组定义为:

void Func(int array[3][10]);

而形参数组定义为:

int array[5][10];

这时形参数组只取实参数组的一部分,其余部分不起作用。

[原文结束]

也就是说多维数组传参要指定第二维或者更高维的大小,可以省略第一维的大小。

像int array[3][4],要传参的话,函数原型可以为下面三种的任一种:

void func(int a[3][4])

void func(int a[][4])

void func(int (*a)[4])

调用时为:func(array);

同时教材里也说了,如果在型参里不说明列数,则编译器无法决定应为多少行多少列。那么能不能把

int array[3][4]的数组名array 传给void func(int **a)呢?

看下面:

/**********************************/

#include

int main()

{

int array[3][4];

int **p = array;

}

**********************************/

root@localhost ansi_c]# gcc test2.c

test2.c: 在函数‘main’ 中:

test2.c:5: 警告:从不兼容的指针类型初始化

[root@localhost ansi_c]#

虽然从本质上讲int array[3][4] 的数组名相当于二级指针,但它不等同于一般的二级指针,因为它还含有数组相关的信息,所以在main函数中:

char str_arr[3][10] = {"yes","no","uncertain"};

for(i=0;i<3;i++)

printf( "%s/n",str_arr+i );

它可以通过下标,每次跳过10个字节来寻址。我们再看看编译器是怎样处理数组的:对于数组int p[m][n];

如果要取p[i][j]的值(i>=0 && i

编译器是这样寻址的:

p + i*n + j;

我们再看一个例子:

/*********************二维数组传参*****************************/

#include

void fun( int *a, int m, int n)

{

int i,j;

for( i=0; i

{

for(j=0;j

{

printf("%d ", *( a+i*n+j ) );

}

putchar('/n');

}

}

void func( int *a, int m, int n)

{

int i,j;

for( i=0;i

{

printf("%d ",a[i]);

}

putchar('/n');

}

int main()

{

int a[3][3] =

{

{2, 2, 2},

{3, 3, 3}

};

fun( (int *)a, 3,3);

func( &a[0][0],3,3);

func( (int *)a, 3,3);

return 0;

}

********************end******************************/ [root@localhost ansi_c]# gcc test4.c

[root@localhost ansi_c]# ./a.out

1 1 1

2 2 2

3 3 3

1 1 1

2 2 2

3 3 3

1 1 1

2 2 2

3 3 3

[root@localhost ansi_c]#

我们来看其中的要点,

数组为:

int a[3][3] =

{

{1, 1, 1},

{2, 2, 2},

{3, 3, 3}

};

函数原型和调用为:

原型:

void fun( int *a, int m, int n)

{

.............

printf("%d ", *( a+i*n+j ) ); .............

}

调用:

fun( (int *)a, 3,3);

原型:

void func( int *a, int m, int n)

{

.............

printf("%d ",a[i]);

.............

}

调用:

func( &a[0][0],3,3);

func( (int *)a, 3,3);

我们发现这两种方式都能正常执行,我们把一个二级指针,强制转换成了一级指针传了进去,并在函数中模仿编译器数组的寻址方式:*( a+i*n+j )。

我们再看看二维字符数组的例子:

/*******************二维字符数组*******************************/

#include

void f( char **a, int n)

{

int i;

printf("%c/n",*( (char*)a+0 ) );

printf("%c/n",((char * )a)[n] );

puts("------------OK");

for(i=0;i<3;i++)

printf("%s/n",(char*)a+i*n );

}

int main()

{

char str_arr[3][10] = {"yes","no","uncertain"};

f( (char **)str_arr, 10);

return 0;

}

/****************end*************************/

运行结果:

[root@localhost ansi_c]# ./a.out

y

n

------------OK

yes

no

uncertain

[root@localhost ansi_c]#

这里也做了强制类型转换,转换成字符指针,

printf("%s/n",(char*)a+i*n ); 每个字符串的地址就是数组中字符'y'、'n'、'u'的地址,

printf("%c/n",*( (char*)a+0 ) );字符在数组中的排列是顺序的,可以用*( (char*)a+i )或((char * )a)[i] 表示。

当然这个程序也可以改成这样,完全不用二级指针:

/*****************************************************************/

#include

void f( char *a, int n)

{

int i;

printf("%c/n",*( a+0 ) );

printf("%c/n",(a)[n] );

puts("------------OK");

for(i=0;i<3;i++)

printf("%s/n",a+i*n );

}

int main()

{

char str_arr[3][10] = {"yes","no","uncertain"};

f( (char *)str_arr, 10);

return 0;

}

/*****************************************************************/

归根结底,还是把它转成一级指针来用。

下面做个小结:

数组传参

数组:

int array[4][10];

函数原型:

void func1( int a[][10] );

void func2( int (*a)[10] );

void func3( int *p, int col, int row );

函数调用:

func1( array );

func2( array );

func3( (int *)array, 4, 10 );

容易出错的地方:

int arr[][10];

int **p = arr;

这种方式是错误的.

应该是

int (*p)[10] = arr;

同理,也不能将arr传给fun( int **p)

另外数组传参之后会降级为指针,如:

#include

void Test(char a[][2])

{

int size = sizeof( a );//4

}

int main(void)

{

char a[3][2] = {'a','b','c','d','e','f'};

int size =sizeof( a );//6

Test( a );

return 0;

}

来源:https://www.360docs.net/doc/4011140775.html,/d_life/blog/item/912062ef1fd363e9ce1b3e2a.html

函数原型:要求传入一个动态二维数组

void func1(int **p,int row, int column)

{

}

调用:

int main()

{

int m,n;

int **b;

cin >> m;

cin >> n;

b = new int *[m];

for(int i=0; i

{

b[i] = new int[n];

};

func1(b,m,n);

return 0;

}

我习惯的做法是不用指针数组,定义一个大块(这种情况主要面向每行行数相同):比如现在有一个W*H 的矩阵(H个长度为W的数组),你就直接定义一个float型指针: float* pfBuffer;然后动态分配大小pfBuffer = new float[W*H];这个buffer在用完之后要调用delete pfBuffer;来释放.你传递这个float指针,传递行列数之后,你如果要访问y行x列的话,只要算一下它在哪儿, int addr = y*W+x;就是其"地址"了,你要访问它,直接使用pfBuffer[addr]就OK了,实际上我做图象处理的时候全部这样做,因为这样的地址访问很明了,不会给阅读带来不便,而且作为大部分的时候,我们用矩阵比较多,列数不等的情况很少。这只是个人见解。

用QR算法求矩阵的特征值

一、实验名称:用QR 算法求矩阵的特征值 二、实验目的:1、通过实验进一步熟悉掌握求矩阵特征值的QR 方法及原理。 2、理解QR 方法的计算流程。 3、能够编程实现QR 方法。 三、实验内容:给定矩阵 ??? ? ? ??=111132126A , ?? ??? ?? ? ? ?=0100098 20 087630 7654465432H ,采用QR 方法计算A 和H 矩阵的全部特征值。 四、实验要求: (1) 根据QR 算法原理编写程序求矩阵A 及矩阵H 的全部特征值(要求误差<10 5 -)。 (2) 直接用MATLAB 的内部函数eig 求矩阵A 及矩阵H 的全部特征值,并与(1)的结果比较。 五、QR 方法计算矩阵特征值的程序: function [namda,time,data_na]=qr_tz(A,tol) if nargin==1; tol=1e-5; end wucha=1; time=0; while (wucha>tol)&(time<500) [q,r]=qr(A); A1=r*q; tz0=diag(A1); tz1=diag(A); wucha=norm(tz0-tz1); A=A1; time=time+1; data_na(time,:)=tz1; end namda=tz1; disp(‘特征值为’) namda disp(‘第一个特征在值’) time n1=length(data_na); n2=(1:n1)’; temp1=[n2,data_na]; subplot(2,2,1:2)

plot(date_na(:,1)) title(‘迭代次数为’) grid subplot(2,2,3) plot(data-na(:,2)) title(‘第二个特征值’)grid subplot(2,2,4) plot(data-na(:,3)) title(‘第三个特征值’) grid 六、实验结果: >> A=[6,2,1;2,3,1;1,1,1];[namda,time,data_na]=qr_tz(A,1e-5);特征值为 namda = 迭代次数为 time = 6 图 1

求矩阵特征值算法及程序

求矩阵特征值算法及程序简介 1.幂法 1、幂法规范化算法 (1)输入矩阵A、初始向量( 0),误差eps; (2) k 1; (3)计算V(k)A(k 1); (4)m k max(V(k)) ,m k1max( V ( k 1)); (5) (k)V(k)/m k; (6)如果m k m k 1eps,则显示特征值1和对应的特征向量x(1) ),终止; (7)k k 1, 转(3) 注:如上算法中的符号max(V )表示取向量V 中绝对值最大的分量。本算法使用了数据规范化处理技术以防止计算过程中出现益出错误。 2、规范化幂法程序 Clear[a,u,x]; a=Input[" 系数矩阵A="]; u=Input[" 初始迭代向量u(0)="]; n=Length[u]; eps=Input[" 误差精度eps ="]; nmax=Input[" 迭代允许最大次数nmax="]; fmax[x_]:=Module[{m=0,m1,m2}, Do[m1=Abs[x[[k]]]; If[m1>m,m2=x[[k]];m=m1], {k,1,Length[x]}]; m2] v=a.u; m0=fmax[u]; m1=fmax[v]; t=Abs[m1-m0]//N; k=0; While[t>eps&&k

相关主题
相关文档
最新文档