C语言,同样使用if else while 这样的语法,但不同的人,就是有不同的实现方式,甚至是技巧。

eg:

 #include <stdio.h>
#include<string.h>
typedef _Bool bool;
#define true 1
#define false 0
#define N 10
bool identity_matrix(int matrix[][N])
{
int row, column;
for (row = ; row < N; ++row)
{
for (column = ; column < N; ++column)
{
/*如果row和column相等,它的值就为1,否则为0
这里还需要注意,正面不好找时,找反面,这在高中数学时就有体会了
如果我们要判断row和column相等的时候此时的数组值是否是1就需要判断
N次,而要是我们判断roe和column相等时,数组值不为1,即为0时,出现这样
的情况立即返回false显然更好
*/
if ((row == column) != matrix[row][column])
return false;
}
}
return true;
}
int main(void)
{
int matrix[][] = {
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
};
int ret = ;
ret=identity_matrix(matrix);
if (ret == )
{
printf("单位矩阵.\n");
}
else
{
printf("非单位矩阵.\n");
}
return ;
}

上面红线处的if语句,是一个值得借鉴的表达式,这也是上一篇博客所说到的,这需要平时的积累,就算都是基本语法,但不同的人能用出不一样的花样。

这个代码还有一点不足,就是如果我把数组改成matrix[10][11],其余什么也不改变,程序运行会失常(即误判,不信可以试试),作为一个专业的程序员,必须想到输入数据不符合规范的情况,我们当然知道单位矩阵必须row和column相同,但是我们设计的程序应该要能判断输入是否合法,并给予提示。在看改进代码之前,我们先得求出二维数组的维数,看下列代码:

eg1:

 int main(void)
{
int matrix[][] = {
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
};//只初始化了10*10的
int x, y;
y = sizeof(matrix[]) / sizeof(int);//求得列数
x = sizeof(matrix) / sizeof(int) / y;//求得行数
printf("%d %d\n", x, y);
}

这样是可以求出二维数组各个维数的,但是,再做更改如下:

eg2:

 int identity_matrix(int matrix[][])
{
int x, y;
y = sizeof(matrix[]) / sizeof(int);//求得列数
x = sizeof(matrix) /sizeof(int)/y;//求得行数
printf("%d %d\n", x, y);
。。。。。。
//下列代码省略
}

将其放在函数中时,此时数组当参数,这样会失败,注意了,此时的sizeof(matrix)为4,是一个指针的大小(我的是在X86下,指针4字节,X64下,8个字节)。这里必须要知道,编译器对数组做的退化处理,处理成指针了,那么,怎么办呢?

eg3:

 #include <stdio.h>
#include<string.h>
typedef _Bool bool;
#define true 1
#define false 0
#define N 10
bool identity_matrix(int (*matrix)[N])//二维数组退化后的形式
{
int row, column;
for (row = ; row < N; ++row)
{
for (column = ; column < N; ++column)
{
if ((row == column) != matrix[row][column])
return false;
}
}
return true; }
int main(void)
{
int matrix[][] = {
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
};
int x, y;
y = sizeof(matrix[]) / sizeof(int);//求得列数
x = sizeof(matrix) / sizeof(int) / y;//求得行数
int ret = ;
if (x == y)
{
ret = identity_matrix(matrix);
if (ret == )
{
printf("单位矩阵.\n");
}
else
{
printf("非单位矩阵.\n");
}
}
else
{
printf("请给我行列相同的矩阵\n");
}
return ;
}

这样改进之后,行列不同时会提示并且不执行identity_matrix函数,如果定义的数组matrix的维数超过10,例如上面的12*12的,不管你是不是单位矩阵,都将显式非单位矩阵,因为我必须要确定数组的列数,这也算是一个小bug吧(为什么会失败?虽然我们定义的列数是10的形参,但是我们传递来的却是列数为12的实参,这和多维数组其实是由一维数组拼接而来有关系,形参取10列之后,实参的第11列当做形参的第二列 开始,这样将出现误判,结论就是,传递的实参列数大于形参,但是由于本质是一维指针传递来的,实参会依次全部传来,而不受形参列数的限制。一般实参和形参不一致,都是实参转化成形参类型,这里也不例外,但是由于是指针,传来的是实参的地址,根据这个地址,我们可以一直在有效内存中访问),但程序员应该确保实参和形参匹配,不过C99已经支持VLA(变长数组),可以将列数用参数传递,只是因为用的vs2015,这个编译器对c99支持不够,所以不再演示,gcc是完美支持的。

既然已经发现了作为成熟的应用程序的bug,那么我们就应该想办法解决啊,一个更成熟的代码如下:

 #include <stdio.h>
#include<string.h>
typedef _Bool bool;
#define true 1
#define false 0
#define N 10
#define Out_p(col) printf("我只能处理"#col"列的内容。\n")
bool identity_matrix(int (*matrix)[N])//二维数组退化后的形式
{
int row, column;
for (row = ; row < N; ++row)
{
for (column = ; column < N; ++column)
{
if ((row == column) != matrix[row][column])
return false;
}
}
return true; }
int main(void)
{
int matrix111[][] = {
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, },
{ ,,,,,,,,, }, };
int x, y;
y = sizeof(matrix111[]) / sizeof(int);//求得列数
x = sizeof(matrix111) / sizeof(int) / y;//求得行数
int ret = ;
if (x == y)
{
if (y == N)
{
ret = identity_matrix(matrix111);
if (ret == )
{
printf("单位矩阵.\n");
}
else
{
printf("非单位矩阵.\n");
}
}
else Out_p(N);
}
else
{
printf("请给我行列相同的矩阵\n");
}
return ;
}

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

续写上一篇的数组or指针操作的更多相关文章

  1. Java核心基础第4篇-Java数组的常规操作

    Java数组 一.数组简介 数组是多个相同类型数据的组合,实现对这些数据的统一管理 数组属引用类型,数组型数据是对象(Object) 数组中的元素可以是任何数据类型,包括基本类型和引用类型 数组类型是 ...

  2. 终于明白上一篇的一顿误操作是什么了,是$,不是S !!!!!

    1,在命令行中输入export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin这样可以保证命令行命令暂时可以使用.命令执行完之后先不要关闭终端2. ...

  3. C语言数组操作和指针操作谁更高效

    在上一篇博文  代码优化小技巧(持续更新......) 第三条关于数组和指针谁更高效, 意犹未尽, 决定单独拉出一篇来讲 1. 数组和指针操作对比 #include <stdio.h> i ...

  4. C/C++数组和指针详解

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  5. (C语言)数组与指针的区别

    以前常常听过这种说法,说数组和指针这两者比较像,但是不能混淆,可是一直没能理解.刚刚在李云的<专业嵌入式软件开发>中,看了讲述数组与指针区别的一章,似乎有所领悟.本着知乎上看到的这张图,我 ...

  6. php数组和部分操作函数

    1. 数组定义 数组的定义使用 array()方式定义,可以定义空数组: <?php $number = array(1,3,5,7,9); //定义空数组 $result = array(); ...

  7. 新闻内页 上一篇写一篇问题,ID不连续,不用链表

    y要什么链表? 用sql查询上一篇 SELECT id,title FROM t_article WHERE id<10 ORDER BY id DESC LIMIT 1; 用sql查下一篇 S ...

  8. JAVA之旅(二十四)——I/O流,字符流,FileWriter,IOException,文件续写,FileReader,小练习

    JAVA之旅(二十四)--I/O流,字符流,FileWriter,IOException,文件续写,FileReader,小练习 JAVA之旅林林总总也是写了二十多篇了,我们今天终于是接触到了I/O了 ...

  9. 小猪猪C++笔记基础篇(四)数组、指针、vector、迭代器

    小猪猪C++笔记基础篇(四) 关键词:数组,Vector. 一.数组与指针 数组相信大家学过C语言或者其他的语言都不陌生,简单的就是同一个变量类型的一组数据.例如:int a[10],意思就是从a开始 ...

随机推荐

  1. POJ--2752--Seek the Name, Seek the Fame【KMP】

    链接:http://poj.org/problem? id=2752 题意:对于一个字符串S,可能存在前n个字符等于后n个字符,从小到大输出这些n值. 思路:这道题加深了对next数组的理解.next ...

  2. Oracle EBS SLA(子分类账)

    SLA概述 SLA(Subledger Accounting) 子帐是子分类帐会计的简称,字面上的含义就是子分类帐会计分录 SLA常用表介绍 在SLA中技术方面最常用的就是日记账来源追溯,在追溯的过程 ...

  3. CentOS 7 网络磁盘挂载到本地 并测试传输速度

    本文中的配置只做测试使用,正式环境中考虑到安全,请自行结合网上介绍的配置细节完善配置内容. 首先明确两个概念,服务器和客户端(本地),我们要做的是将服务端的硬盘上的/home/liuyx 目录挂载到本 ...

  4. te

    var option = {}; $(function() { /* var taskId = ${pd.taskId}; */ var taskId = "1470880530369&qu ...

  5. Chrome实用调试技巧

    如今Chrome浏览器无疑是最受前端青睐的工具,原因除了界面简洁.大量的应用插件,良好的代码规范支持.强大的V8解释器之外,还因为Chrome开发者工具提供了大量的便捷功能,方便我们前端调试代码,我们 ...

  6. Eclipse Xml编译错误Referenced file contains errors - spring-beans-4.0.xsd

    本文转自:http://josh-persistence.iteye.com/blog/2125420 在eclipse中,有时候在xml文件中,特别是于Spring相关的配置文件中,会出现一些不影响 ...

  7. OpenStack+Ceph存储空间回收《转》

    转自:http://blog.csdn.net/wytdahu/article/details/48288681 问题描述 在OpenStack云环境的部署中,存储通常具备Thin provision ...

  8. Linux命令-终止进程命令:kill

    kill -l 查看进程信号 常用信号 例如: 例子参见:Linux命令-查看进程命令:pstree

  9. Linux中网络通信中 使用的结构体

    "+++++++++++++++++++++++++ Linux TCP/UDP通信中的结构体 +++++++++++++++++++++++++++++++++++++++" s ...

  10. Python atan() 函数

    描述 atan() 返回x的反正切弧度值. 语法 以下是 atan() 方法的语法: import math math.atan(x) 注意:atan()是不能直接访问的,需要导入 math 模块,然 ...