zoukankan      html  css  js  c++  java
  • 续写上一篇的数组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("单位矩阵.
    ");
    45     }
    46     else 
    47     {
    48         printf("非单位矩阵.
    ");
    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
    ", 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
    ", 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("单位矩阵.
    ");
    45         }
    46         else 
    47         {
    48             printf("非单位矩阵.
    ");
    49         }
    50     }
    51     else
    52     {
    53         printf("请给我行列相同的矩阵
    ");
    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"列的内容。
    ")
     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("单位矩阵.
    ");
    49             }
    50             else
    51             {
    52                 printf("非单位矩阵.
    ");
    53             }
    54         }
    55         else Out_p(N);
    56     }
    57     else
    58     {
    59         printf("请给我行列相同的矩阵
    ");
    60     }
    61     return 0;
    62 }

    这样要是输入的矩阵不符合要求,将出现提示信息。这样的程序,才能算基本合格。那么有没有办法在不支持c99的编译器下,完成identity_matrix函数的参数也可以随输入的不同而不同呢?当然也还是可以的,定义一个一维指针,虽然传递二维数组给这个一维指针,会报类型不符的警告,但是C语言中并没有二维数组,在内存中都是以一维的方式排列的,所以只要一个一维指针就可以做到,《c和指针》上正是用的这种方法。

  • 相关阅读:
    毕业季 | 如何做出99分的答辩PPT
    git: error setting certificate verify locations解决办法
    获取表格里面的内容
    MD5加密算法
    mybatis多条件批量删除
    layer.confirm
    DevExpress控件的GridControl实现行多选
    sz与rz命令
    @TableField的使用
    C# WinForm 中Label自动换行 解决方法
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6623210.html
Copyright © 2011-2022 走看看