Chinaunix

标题: 在《C程序设计伴侣》的交通灯例子中,我为什么没有使用解读专家的所谓更聪明的方法 [打印本页]

作者: 陈良乔    时间: 2012-10-22 23:16
标题: 在《C程序设计伴侣》的交通灯例子中,我为什么没有使用解读专家的所谓更聪明的方法
今天在豆瓣看到解读专家的关于交通灯这个例子中的一段读书笔记
2012-10-20 14:24:09 薛非

32. if(red == light)
33. puts("STOP"); // 停止
34. // 如果交通灯是绿色
35. else if( green == light )
36. puts("Go!Go!Go!"); // 继续前行


这是在教唆愚蠢
下面三种写法都比原来好

01.if(red == light)
02. puts("STOP");
03.if( green == light )
04. puts("Go!Go!Go!");

01.if( red == light )
02. puts("STOP");
03.else
04. puts("Go!Go!Go!");

01.puts( red == light?"STOP":"Go!Go!Go!");

我想说说为什么没有采用他提供的这三种更聪明的方法

01.if(red == light)
02. puts("STOP");
03.if( green == light )
04. puts("Go!Go!Go!");
// 这种方法,比较近似
// 然而让我想不痛的是,既然light都已经等于red了,为啥后面接着还要来个if判断light是否等于green?
// 这让我想起他曾经说我代码没有逻辑,明明fp不可能为NULL,而要去判断是多此一举
// 而这里,两个互斥的两个条件并列,所以我用了if...else if

01.if( red == light )
02. puts("STOP");
03.else
04. puts("Go!Go!Go!");
// 在我看来,这样写很危险
// 如果light为yellow呢?

01.puts( red == light?"STOP":"Go!Go!Go!");
// 这种形式,我说什么好呢?
// 同样存在第二种的light为其他颜色的问题
// 同时,我也觉得这种代码缺乏可读性,对于初学者,估计会把读者搞得云里雾里

所以,我没有采用这些在他看来更好的写法。

作者: linux_c_py_php    时间: 2012-10-22 23:23
这种2B帖子可以删除了。
作者: pmerofc    时间: 2012-10-22 23:38
提示: 作者被禁止或删除 内容自动屏蔽
作者: 群雄逐鹿中原    时间: 2012-10-22 23:39
两位专家终于达成默契了
作者: Ager    时间: 2012-10-22 23:40
小乔能来,大家能当面锣对面鼓地,是好事。

别搞砸了。

作者: 0xC1988    时间: 2012-10-22 23:40
  1. #include <stdio.h>    // 引入标准输出函数puts()的声明
  2. #include <stdlib.h>       // 引入随机数函数rand()和srand()的声明
  3. #include <time.h>     // 引入时间函数time()的声明
  4. // 枚举交通灯的颜色
  5. [color=Red]enum trafficlight
  6. {
  7.     red = 0,    // 红色
  8.     green       // 绿色
  9. };[/color]
  10. int main()
  11. {
  12.     // 用当前时间初始化随机种子
  13.     // 在C语言中,rand()函数所产生的随机数实际上是一个伪随机数(如果不使
  14.     // 用srand()函数初始化随机种子,每次调用都会产生相同的随机数)。而srand()的
  15.     // 意义就在于用一个真实的随机数(也就是所谓的随机种子),通常是当前系统时
  16.     // 间,作为初始条件,然后用一定的算法不停迭代产生真实的随机数
  17.     srand(time(NULL));
  18.     // 这里的rand()函数会产生一个0 到 RAND_MAX
  19.     // (不同的编译器对这个值有不同的定义,但是都会大于32767)之间的整数,
  20.     // 对这个整数用“%”对2进行取余运算,得到的就是随机的0或者1,
  21.     // 用来表示当前交通灯的红绿灯颜色
  22.     int light = rand()%2;
  23.     // 开始进入条件结构进行判断
  24.     // 如果交通灯是红色
  25.     // 在将一个变量(light)和一个常量(red)进行“==”比较的时候,
  26.     // 我们通常将常量放在“==”符号的前面,变量放在“==”符号的后面,
  27.     // 虽然两者位置颠倒在语法上也同样成立,但是将常量放在“==”之前,
  28.     // 可以避免因为疏忽(少写一个“=”号)引起的“常量=变量”错误。
  29.     // 针对这种错误,编译器会给出错误提示,不能为一个常量赋值,
  30.     // 如果将变量放在“=”前,编译器不会对“变量=常量”提示错误,也就
  31.     // 无法及时地发现这种极具隐蔽性的错误。
  32.     if(red == light)
  33.         puts("STOP");  // 停止
  34.     // 如果交通灯是绿色
  35.     else if( green == light )
  36.         puts("Go!Go!Go!"); // 继续前行
  37.     return 0;
  38. }
复制代码
我想说说为什么没有采用他提供的这三种更聪明的方法

01.if(red == light)
02. puts("STOP";
03.if( green == light )
04. puts("Go!Go!Go!";
// 这种方法,比较近似
// 然而让我想不痛的是,既然light都已经等于red了,为啥后面接着还要来个if判断light是否等于green?
// 这让我想起他曾经说我代码没有逻辑,明明fp不可能为NULL,而要去判断是多此一举
// 而这里,两个互斥的两个条件并列,所以我用了if...else if

01.if( red == light )
02. puts("STOP";
03.else
04. puts("Go!Go!Go!";
// 在我看来,这样写很危险
// 如果light为yellow呢?


01.puts( red == light?"STOP":"Go!Go!Go!";
// 这种形式,我说什么好呢?
// 同样存在第二种的light为其他颜色的问题
// 同时,我也觉得这种代码缺乏可读性,对于初学者,估计会把读者搞得云里雾里

所以,我没有采用这些在他看来更好的写法。


解毒专家说你蠢,你没必要跳出来自己证明自己蠢吧

作者: pmerofc    时间: 2012-10-22 23:43
提示: 作者被禁止或删除 内容自动屏蔽
作者: pmerofc    时间: 2012-10-22 23:49
提示: 作者被禁止或删除 内容自动屏蔽
作者: starwing83    时间: 2012-10-23 01:44
鼓掌鼓掌~~搬小板凳旁观~~刚刚看完《本杰明·巴顿奇事》~

恩,如果是我的话,enum基本上就意味着switch了~~嘿嘿
作者: pandaiam    时间: 2012-10-23 09:11
近距离围观楼主.
传说中的大神啊.
作者: 你还未够水准呢    时间: 2012-10-23 11:00
留名
拿分
走人
作者: snailshen    时间: 2012-10-23 11:02
我很想知道大神是做什么工作的?
作者: ah_kevin    时间: 2012-10-23 19:29
方法一:
if(red == light)
    puts("STOP"; // 停止
// 如果交通灯是绿色
else if( green == light )
    puts("Go!Go!Go!"; // 继续前行

方法二:
if(red == light)
    puts("STOP";
if( green == light )
    puts("Go!Go!Go!";

我想说的是方法一平均性能更好,楼下,你怎么看?

作者: starwing83    时间: 2012-10-23 19:52
回复 13# ah_kevin


    你似乎忘了有个东西叫”编译器优化“
作者: ah_kevin    时间: 2012-10-23 19:54
依赖编译器的程序员不是好程序员。
作者: isaacxu    时间: 2012-10-23 20:11
实在受不了啦,楼上的几位成心把本人这种初学者往沟里带。有啥呀,叔放狗搜了C的语法,再结合不多的小学算术知识,写了下面几句,看到黄灯了吗?别以为叔只在考前看了7天的谭书,但有狗想变出黄灯还是简单的。
  1. enum trafficlight
  2. {
  3.         red = 0,    // 红色
  4.         green,      // 绿色
  5.         yellow
  6.     };
复制代码
  1. int light = rand()%3;
复制代码

作者: folklore    时间: 2012-10-24 08:40
回复 13# ah_kevin


    "else if" is better.

"else" may help you to read a millon of code,
while you try to "trace" one routine of code, hunders of "if" that without "else" (while it is actually needed) may trouble you.
you must check each or than to identify that this "if" is the part of you care about now.

作者: folklore    时间: 2012-10-24 08:41
each or than  -->
eacho of them
作者: starwing83    时间: 2012-10-24 16:40
回复 15# ah_kevin


    你不依赖编译器?你人肉编译?

应该说,过度依赖编译器是不好的。

但是,明知道两个写法有一样的效果,并且这个效果是基于标准的,并且这两个语句之间的效率差别人眼根本看不出来,并且编译器可能把他们实现为一样的汇编——

——你又有什么理由在这里花费这么多精力判断哪个好呢……
作者: gtestm    时间: 2012-10-24 19:21
妈呀!
// 在我看来,这样写很危险
// 如果light为yellow呢?
我仔细看了陈大湿写的完整代码,不知道是不是我眼搓,没发现 yellow。陈大湿是怎么说出这话来的?
作者: folklore    时间: 2012-10-24 19:58
p@gtestm这次陈大湿是对的

现在没有,不说明以后没有。
作者: 陈良乔    时间: 2012-10-25 21:33
回复 21# folklore
你这个逻辑有点奇怪啊
“现在没有,不说明以后没有”

那么是否也可以说,现在有,不说明以后也有
或者也可以说,现在没有,不说明以后会有?
有点糊涂了



   
作者: cjaizss    时间: 2012-10-25 21:40
folklore 发表于 2012-10-24 19:58
p@gtestm这次陈大湿是对的

现在没有,不说明以后没有。

你被大师点名相中了
咱们妇科老人有力量,OH YEAH
作者: alanwan    时间: 2013-09-19 22:45
个人观点,编程是靠悟性的,不要太担心启蒙书的质量。不过对于那些不自知的人,还是应该敲打敲打的...

这种 if {} else if{} 然后就完了的代码,没经验的人不觉得有事,但实际上它是很多bug的根源,分支少还好,分支一多就特容易出错。
1. 如果你确定只有两种情况,那么你其实只需要判断一种情况,你不需要else if,而只需要else。
2. 如果你担心还有其他情况或意外,那么你需要再加个else,以免漏掉条件而出错。
3. 如果你有默认的情况,而且已经处理,后面这些if只是特例,那么就就用 if, if, if,因为多个特例经常在逻辑上没有互斥性,用else if 容易出错。

小乔同学很有意思,还反过来问别人“如果还有黄灯怎么办”。那么还有黄灯怎么办呢?他的程序什么灯都不亮。他会argue“我会给黄灯再加个else if啊”。是的,那么如果light的值被赋错了,或者还没赋初值,哪个颜色也不是呢?结果是,这个错误就深深的被埋住了。对了,小乔也许不懂,结果不正确不等于程序报错,真是没什么好谈的了。


作者: fender0107401    时间: 2013-09-20 08:59
围观大师。
作者: 蔡万钊    时间: 2013-09-21 08:42
陈大师去给天朝写红绿灯,计生委就可以下岗了。
作者: folklore    时间: 2013-09-21 09:03
回复 24# alanwan


    if -else if
    if - if

在逻辑上完全不同, 讲个鸡毛~~
要讲也只能讲: 该用if-else if时用if-else if, 该用if-if时用if-if
作者: folklore    时间: 2013-09-21 09:04
回复 23# cjaizss


    啊吔~~, 人生最大的梦想实现了~~




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2