续写上一篇的数组or指针操作
C语言,同样使用if else while 这样的语法,但不同的人,就是有不同的实现方式,甚至是技巧。
eg:
1 #include <stdio.h>
2 #include<string.h>
3 typedef _Bool bool;
4 #define true 1
5 #define false 0
6 #define N 10
7 bool identity_matrix(int matrix[][N])
8 {
9 int row, column;
10 for (row = 0; row < N; ++row)
11 {
12 for (column = 0; column < N; ++column)
13 {
14 /*如果row和column相等,它的值就为1,否则为0
15 这里还需要注意,正面不好找时,找反面,这在高中数学时就有体会了
16 如果我们要判断row和column相等的时候此时的数组值是否是1就需要判断
17 N次,而要是我们判断roe和column相等时,数组值不为1,即为0时,出现这样
18 的情况立即返回false显然更好
19 */
20 if ((row == column) != matrix[row][column])
21 return false;
22 }
23 }
24 return true;
25 }
26 int main(void)
27 {
28 int matrix[10][10] = {
29 { 1,0,0,0,0,0,0,0,0,0 },
30 { 0,1,0,0,0,0,0,0,0,0 },
31 { 0,0,1,0,0,0,0,0,0,0 },
32 { 0,0,0,1,0,0,0,0,0,0 },
33 { 0,0,0,0,1,0,0,0,0,0 },
34 { 0,0,0,0,0,1,0,0,0,0 },
35 { 0,0,0,0,0,0,1,0,0,0 },
36 { 0,0,0,0,0,0,0,1,0,0 },
37 { 0,0,0,0,0,0,0,0,1,0 },
38 { 0,0,0,0,0,0,0,0,0,1 },
39 };
40 int ret = 0;
41 ret=identity_matrix(matrix);
42 if (ret == 1)
43 {
44 printf("单位矩阵.\n");
45 }
46 else
47 {
48 printf("非单位矩阵.\n");
49 }
50 return 0;
51 }
上面红线处的if语句,是一个值得借鉴的表达式,这也是上一篇博客所说到的,这需要平时的积累,就算都是基本语法,但不同的人能用出不一样的花样。
这个代码还有一点不足,就是如果我把数组改成matrix[10][11],其余什么也不改变,程序运行会失常(即误判,不信可以试试),作为一个专业的程序员,必须想到输入数据不符合规范的情况,我们当然知道单位矩阵必须row和column相同,但是我们设计的程序应该要能判断输入是否合法,并给予提示。在看改进代码之前,我们先得求出二维数组的维数,看下列代码:
eg1:
1 int main(void)
2 {
3 int matrix[11][12] = {
4 { 1,0,0,0,0,0,0,0,0,0 },
5 { 0,1,0,0,0,0,0,0,0,0 },
6 { 0,0,1,0,0,0,0,0,0,0 },
7 { 0,0,0,1,0,0,0,0,0,0 },
8 { 0,0,0,0,1,0,0,0,0,0 },
9 { 0,0,0,0,0,1,0,0,0,0 },
10 { 0,0,0,0,0,0,1,0,0,0 },
11 { 0,0,0,0,0,0,0,1,0,0 },
12 { 0,0,0,0,0,0,0,0,1,0 },
13 { 0,0,0,0,0,0,0,0,0,1 },
14 };//只初始化了10*10的
15 int x, y;
16 y = sizeof(matrix[0]) / sizeof(int);//求得列数
17 x = sizeof(matrix) / sizeof(int) / y;//求得行数
18 printf("%d %d\n", x, y);
19 }
这样是可以求出二维数组各个维数的,但是,再做更改如下:
eg2:
1 int identity_matrix(int matrix[][10])
2 {
3 int x, y;
4 y = sizeof(matrix[0]) / sizeof(int);//求得列数
5 x = sizeof(matrix) /sizeof(int)/y;//求得行数
6 printf("%d %d\n", x, y);
7 。。。。。。
8 //下列代码省略
9 }
将其放在函数中时,此时数组当参数,这样会失败,注意了,此时的sizeof(matrix)为4,是一个指针的大小(我的是在X86下,指针4字节,X64下,8个字节)。这里必须要知道,编译器对数组做的退化处理,处理成指针了,那么,怎么办呢?
eg3:
1 #include <stdio.h>
2 #include<string.h>
3 typedef _Bool bool;
4 #define true 1
5 #define false 0
6 #define N 10
7 bool identity_matrix(int (*matrix)[N])//二维数组退化后的形式
8 {
9 int row, column;
10 for (row = 0; row < N; ++row)
11 {
12 for (column = 0; column < N; ++column)
13 {
14 if ((row == column) != matrix[row][column])
15 return false;
16 }
17 }
18 return true;
19
20 }
21 int main(void)
22 {
23 int matrix[12][12] = {
24 { 1,0,0,0,0,0,0,0,0,0 },
25 { 0,1,0,0,0,0,0,0,0,0 },
26 { 0,0,1,0,0,0,0,0,0,0 },
27 { 0,0,0,1,0,0,0,0,0,0 },
28 { 0,0,0,0,1,0,0,0,0,0 },
29 { 0,0,0,0,0,1,0,0,0,0 },
30 { 0,0,0,0,0,0,1,0,0,0 },
31 { 0,0,0,0,0,0,0,1,0,0 },
32 { 0,0,0,0,0,0,0,0,1,0 },
33 { 0,0,0,0,0,0,0,0,0,1 },
34 };
35 int x, y;
36 y = sizeof(matrix[0]) / sizeof(int);//求得列数
37 x = sizeof(matrix) / sizeof(int) / y;//求得行数
38 int ret = 0;
39 if (x == y)
40 {
41 ret = identity_matrix(matrix);
42 if (ret == 1)
43 {
44 printf("单位矩阵.\n");
45 }
46 else
47 {
48 printf("非单位矩阵.\n");
49 }
50 }
51 else
52 {
53 printf("请给我行列相同的矩阵\n");
54 }
55 return 0;
56 }
这样改进之后,行列不同时会提示并且不执行identity_matrix函数,如果定义的数组matrix的维数超过10,例如上面的12*12的,不管你是不是单位矩阵,都将显式非单位矩阵,因为我必须要确定数组的列数,这也算是一个小bug吧(为什么会失败?虽然我们定义的列数是10的形参,但是我们传递来的却是列数为12的实参,这和多维数组其实是由一维数组拼接而来有关系,形参取10列之后,实参的第11列当做形参的第二列 开始,这样将出现误判,结论就是,传递的实参列数大于形参,但是由于本质是一维指针传递来的,实参会依次全部传来,而不受形参列数的限制。一般实参和形参不一致,都是实参转化成形参类型,这里也不例外,但是由于是指针,传来的是实参的地址,根据这个地址,我们可以一直在有效内存中访问),但程序员应该确保实参和形参匹配,不过C99已经支持VLA(变长数组),可以将列数用参数传递,只是因为用的vs2015,这个编译器对c99支持不够,所以不再演示,gcc是完美支持的。
既然已经发现了作为成熟的应用程序的bug,那么我们就应该想办法解决啊,一个更成熟的代码如下:
1 #include <stdio.h>
2 #include<string.h>
3 typedef _Bool bool;
4 #define true 1
5 #define false 0
6 #define N 10
7 #define Out_p(col) printf("我只能处理"#col"列的内容。\n")
8 bool identity_matrix(int (*matrix)[N])//二维数组退化后的形式
9 {
10 int row, column;
11 for (row = 0; row < N; ++row)
12 {
13 for (column = 0; column < N; ++column)
14 {
15 if ((row == column) != matrix[row][column])
16 return false;
17 }
18 }
19 return true;
20
21 }
22 int main(void)
23 {
24 int matrix111[11][11] = {
25 { 1,0,0,0,0,0,0,0,0,0 },
26 { 0,1,0,0,0,0,0,0,0,0 },
27 { 0,0,1,0,0,0,0,0,0,0 },
28 { 0,0,0,1,0,0,0,0,0,0 },
29 { 0,0,0,0,1,0,0,0,0,0 },
30 { 0,0,0,0,0,1,0,0,0,0 },
31 { 0,0,0,0,0,0,1,0,0,0 },
32 { 0,0,0,0,0,0,0,1,0,0 },
33 { 0,0,0,0,0,0,0,0,1,0 },
34 { 0,0,0,0,0,0,0,0,0,1 },
35
36 };
37 int x, y;
38 y = sizeof(matrix111[0]) / sizeof(int);//求得列数
39 x = sizeof(matrix111) / sizeof(int) / y;//求得行数
40 int ret = 0;
41 if (x == y)
42 {
43 if (y == N)
44 {
45 ret = identity_matrix(matrix111);
46 if (ret == 1)
47 {
48 printf("单位矩阵.\n");
49 }
50 else
51 {
52 printf("非单位矩阵.\n");
53 }
54 }
55 else Out_p(N);
56 }
57 else
58 {
59 printf("请给我行列相同的矩阵\n");
60 }
61 return 0;
62 }
这样要是输入的矩阵不符合要求,将出现提示信息。这样的程序,才能算基本合格。那么有没有办法在不支持c99的编译器下,完成identity_matrix函数的参数也可以随输入的不同而不同呢?当然也还是可以的,定义一个一维指针,虽然传递二维数组给这个一维指针,会报类型不符的警告,但是C语言中并没有二维数组,在内存中都是以一维的方式排列的,所以只要一个一维指针就可以做到,《c和指针》上正是用的这种方法。
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并获取更多隐藏干货,QQ交流群:816747642 微信公众号:Crystal软件学堂
作者:Crystal软件学堂 bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |