六个变态的hello word&&怎么写混乱代码&&在线编译器
2011-06-09 16:23
351 查看
下面的六个程序片段主要完成这些事情:
输出Hello, World
混乱C语言的源代码
下面的所有程序都可以在GCC下编译通过,只有最后一个需要动用C++的编译器g++才能编程通过。
hello1.c
hello2.c
hello3.c
hello4.c
hello5.c
hello6.c
展示了一些C语言的变态玩法。也向大家展示了一下程序是可以写得让人看不懂的,在那篇文章中,可以看到很多人的留言,很多人都觉得很好玩,是的,那本来是用来供朋友们“消遣作乐”,供娱乐娱东而已,不必太过认真。
不过,通过这种极端的写法,大家可以看到源代码都可以写得那么复杂难懂的。大家也许在赞叹之余一笑了之,而我则希望,大家能够在娱乐以后认真思考一下,你不要以为咱们自己不会把代码搞得那么复杂,只不过没有像那6个Hello World一样那么极端,不过,说句老实话,咱们每个程序都有把清晰的程序搞得一团混乱的潜能,只不过程度不一样罢了,我并不是在这里危言耸听,大家好自为之
。
下面是一个Step by Step的教程,教你如何把一个清晰的代码变得复杂难懂的。当然,这只是一个“简明教程”了。还是那句话——“本文仅供朋友们“消遣作乐”,如果你要觉得有意思的话,顶个贴。如果你觉得没什么意思的话,一笑了之。仅供娱乐而已,不必太过认真。
”
第二步,把循坏变成递归
递归在某些时候是可以把代码变得简单,但大多数的情况下是把代码变得复杂,而且很没有效率。下面是把上面的while循环变成了递归。变成了递归后,函数的参数都变成3个了。
第三步,弄乱代码结构/使用没有含义的变量名
关于如何弄乱代码结构,其中一个小技巧是,使用“?”表达式代替if-else语句。
第四步,取消临时变量
临时变量一般用来保存反复使用的一个表达式的值。使用大量重复的表达式来取消这些临时变量的也可以让代码复杂起来。
第五步,继续弄乱变量名
我们知道,下划线是合法的变量名,所以,我们不妨用__,___,____来代替m,t,c。函数名也可以使用下划线来代替。让我们来看看求素数的函数能变成什么。
程序到这里应该差不多了。还是那句话——“每一个程序员都有把源代码弄复杂的潜质
”,大家好自为之。
如何写出无法维护的代码?
这篇文章的原文在这里(http://mindprod.com/jgloss/unmain.html
),我看完后我想说——
什么叫“创造力”,创造力就是——就算是要干一件烂事都能干得那么漂亮那么有创意的能力。
什么叫“抓狂”,抓狂就是——以一种沉着老练的不屈不挠的一本正经的精神一点一点把你推向崩溃的边缘
。
。比如:Fred,asdf
单字母的变量名
。比如:a,b,c, x,y,z(陈皓注:如果不够用,可以考虑a1,a2,a3,a4,….)
有创意地拼写错误
。比如:SetPintleOpening, SetPintalClosing。这样可以让人很难搜索代码。
抽象
。比如:ProcessData, DoIt, GetData… 抽象到就跟什么都没说一样。
缩写
。比如:WTF,RTFSC …… (陈皓注:使用拼音缩写也同样给力,比如: BT,TMD,TJJTDS)
随机大写字母
。比如:gEtnuMbER..
重用命名
。在内嵌的语句块中使用相同的变量名有奇效。
使用重音字母
。比如:int ínt(注:第二个 ínt不是int)
使用下划线
。比如:_, __, ___。
使用不同的语言
。比如混用英语,德语,或是中文拼音。
使用字符命名
。比如:slash, asterix, comma…
使用无关的单词
。比如:god, superman, iloveu….
混淆l和1
。字母l和数字1有时候是看不出来的。
。
隐藏宏定义
。如:#define a=b a=0-b,当人们看到a=b时,谁也想不到那是一个宏。
换行
。如下所示,下面的示例使用搜索xy_z变得困难。。
代码和显示不一致
。比如,你的界面显示叫postal code,但是代码里确叫 zipcode.
隐藏全局变量
。把使用全局变量以函数参数的方式传递给函数,这样可以让人觉得那个变量不是全局变量。
使用同意词
。如:
使用相似的变量名
。如:单词相似,swimmer 和 swimner,字母相似:ilI1| 或
oO08。parselnt 和 parseInt, D0Calc 和 DOCalc。还有这一组:xy_Z, xy__z, _xy_z,
_xyz, XY_Z, xY_z, Xy_z。
重载函数
。使用相同的函数名,但是其功能和具体实现完全没有关系。
操作符重载
。重载操作符可以让你的代码变得诡异,感谢CCTV,感谢C++。这个东西是可以把混乱代码提高到
一种艺术的形式。比如:重载一个类的 ! 操作符,但实际功能并不是取反,让其返回一个整数。于是,如果你使用 ! !
操作符,那么,有意思的事就发生了—— 先是调用类的重载 ! 操作符,然后把其返回的整数给 ! 成了 布尔变量,如果是 !!! 呢?呵呵。
#define
。看过本站那些混乱代码的文章,你都会知道宏定义和预编译对于写出不可读的代码的重大意义。不过,一个具有想像力的东西是——在头文件中使用预编译来查看这个头文件被include了几次,而被include不同的次数时,其中的函数定义完全不一样。
。你不用真的去撒谎,只需在改代码的时候不要更新注释就可以了。
注释明显的东西
。比如:/* add 1 to i */。(五种应该避免的注释
)
只注释是什么,而不是为什么
。
不要注释秘密
。如果你开发一个航班系统,请你一定要保证每有一个新的航班被加入,就得要修改25个以上的位置的程序。千万别把这个事写在文档中。
注重细节
。当你设计一个很复杂的算法的时候,你一定要把所有的详细细设计都写下来,没有100页不能罢休,段
落要有5级以上,段落编号要有500个以上,例如:1.2.4.6.3.13 – Display all impacts for activity
where selected mitigations can apply (short pseudocode omitted).
这样,当你写代码的时候,你就可以让你的代码和文档一致,如:Act1_2_4_6_3_13()
千万不要注释度衡单位
。比如时间用的是秒还是毫秒,尺寸用的是像素还是英寸,大小是MB还是KB。等等。另外,在你的代码里,你可以混用不同的度衡单位,但也不要注释。
Gotchas
。陷阱,千万不要注释代码中的陷阱。
在注释和文档中发泄不满
。(五种应该避免的注释
)
。Java的类型转型是天赐之物。每一次当你从Collection里取到一个object的时候,你都需要把其转回原来的类型。因些,这些转型操作会出现在N多的地方。如果你改变了类型,那么你不一定能改变所有的地方。而编译器可能能检查到,也可能检查不到。
利用Java的冗余
。比如:Bubblegum b = new Bubblegom(); 和 swimmer = swimner + 1; 注意变量间的细微差别。
从不验证
。从不验证输入的数据,从不验证函数的返回值。这样做可以向大家展示你是多么的信任公司的设备和其它程序员。
不要封装
。调用者需要知道被调用的所有的细节。
克隆和拷贝
。为了效率,你要学会使用copy + paste。你几乎都不用理解别人的代码,你就可以高效地编程了。(陈皓注:Copy + Paste出来的代码bug多得不能再多)
巨大的listener
。写一个listener,然后让你的所有的button类都使用这个listener,这样你可以在这个listener中整出一大堆if…else…语句,相当的刺激。
使用三维数组
。如果你觉得三维还不足够,你可以试试四维。
混用
。同时使用类的get/set方法和直接访问那个public变量。这样做的好处是可以极大的挫败维护人员。
包装,包装,包装
。把你所有的API都包装上6到8遍,包装深度多达4层以上。然后包装出相似的功能。
没有秘密
。把所有的成员都声明成public的。这样,你以后就很难限制其被人使用,而且这样可以和别的代码造成更多的耦合度,可以让你的代码存活得更久。
排列和阻碍
。把drawRectangle(height, width) 改成 drawRectangle(width, height),等release了几个版本后,再把其改回去。这样维护程序的程序员们将不能很快地明白哪一个是对的。
把变量改在名字上
。例如,把setAlignment(int alignment)改成,setLeftAlignment, setRightAlignment, setCenterAlignment。
Packratting
。保留你所有的没有使用的和陈旧的变量,方法和代码。
That’s Fina
l。Final你所有的子结点的类,这样,当你做完这个项目后,没有人可以通过继承来扩展你的类。java.lang.String不也是这样吗?
避免使用接口
。在java中,BS接口,在C++中BS使用虚函数。
避免使用layout
。这样就使得我们只能使用绝对坐标。如果你的老大强制你使用layout,你可以考虑使用GridBagLayout,然后把grid坐标hard code.
环境变量
。如果你的代码需要使用环境变量。(getenv() – C++ / System.getProperty() – Java ),那么,你应该把你的类的成员的初始化使用环境变量,而不是构造函数。
使用Magic numbe
r。参看《Linux一个插曲
》。
使用全局变量
。1)把全局变量的初始化放在不同的函数中,就算这个函数和这个变量没有任何关系,这样能够让我们的维护人员就像做侦探工作一样。2)使用全局变量可以让你的函数的参数变得少一些。
配置文件
。配置文件主要用于一些参数的初始化。在编程中,我们可以让配置文件中的参数名和实际程序中的名字不一样。
膨胀你的类
。让你的类尽可能地拥有各种臃肿和晦涩的方法。比如,你的类只实现一种可能性,但是你要提供所有可能性的方法。不要定义其它的类,把所有的功能都放在一个类中。
使用子类
。面向对象是写出无法维护代码的天赐之物。如果你有一个类有十个成为(变量和方法)你可以考虑写10个层次的继承,然后把这十个属性分别放在这十个层次中。如果可能的话,把这十个类分别放在十个不同的文件中。
。XML的强大是无人能及的。使用XML你可以把本来只要10行的代码变成100行。而且,还要逼着别人也有XML。(参看,信XML得永生
,信XML得自信
)
混乱C代码
。在《如何加密源代码
》中已经说过一些方法了,这里再补充一些。
使用不同的进制
。比如:10 和010不是一样的。再比如:array = new int[]{ 111, 120, 013, 121,};
尽量使用void*
。然后把其转成各种类型
使用隐式的转型
。C++的构造函数可以让你神不知鬼不觉得完成转型。
分解条件表达式
。如:把 a==100分解成,a>99 && a<101
学会利用分号
。如:if ( a );else;{ int d; d = c;}
间接转型
。如:把double转string,写成new Double(d).toString() 而不是 Double.toString(d)
大量使用嵌套
。一个NB的程序员可以在一行代码上使用超过10层的小括号(),或是在一个函数里使用超过20层的语句嵌套{},把嵌套的if else 转成 [? :] 也是一件很NB的事。
使用C的变种数组
。myArray[i] 可以变成*(myArray + i) 也可以变成 *(i +
myArray) 其等价于 i[myArray]。再看一个函数调用的示例,函数声明:int myfunc(int q, int p) {
return p%q; } 函数调用myfunc(6291, 8)[Array];
长代码行
。一行的代码越长越好。这样别人阅读时就需要来来回回的
不要较早的return
。不要使用goto,不要使用break,这样,你就需要至少5层以上的if-else来处理错误。
不要使用{}
。不要在if else使用{},尤其是在你重量地使用if-else嵌套时,你甚至可以在其中乱缩进代码,这样一来,就算是最有经验的程序员也会踩上陷阱。
使用宏定义
。宏定义绝对是混乱C/C++代码的最佳利器。参看 老手是这样教新手编程的
。
琐碎的封装
。比较封装一个bool类,类里面什么都做,就是一个bool.
循环
。千万不可用for(int i=0; i<n; i++)使用while代替for,交换n和i,把<改成<=,使用 i–调整步伐 。
。千万不要测试任何的出错处理,从来也不检测系统调用的返回值。
永远不做性能测试
。如果不够快就告诉用户换一个更快的机器。如果你一做测试,那么就可能会要改你的算法,甚至重设计,重新架构。
不要写测试案例
。不要做什么代码覆盖率测试,自动化测试。
测试是懦夫行为
。一个勇敢的程序员是根本不需要这一步的。太多的程序太害怕他们的老板,害怕失去工作,害怕用户抱怨,甚至被起诉。这种担心害怕直接影响了生产力。如果你对你的代码有强大的信心,那还要什么测试呢?真正的程序员是不需要测试自己的代码的。
。无论你的老板有多SB,你都要严格地遵照他的旨意办事,这样一来,你会学到更多的知识如何写出无法维护的代码来的。
颠覆Help Desk
。你要确保你那满是bug的程序永远不要被维护团队知道。当用户打电话和写邮件给你的时候,你就不要理会,就算要理会,让用户重做系统或是告诉用户其帐号有问题,是标准的回答。
闭嘴
。对于一些像y2k这样的大bug,你要学会守口如瓶,不要告诉任何人,包括你的亲人好友以及公司的同事和管理层,这样当到那一天的时候,你就可以用这个bug挣钱了。
忽悠
。你会学会忽悠,就算你的代码写得很烂,你也要为其挂上GoF设计模式的标签,就算你的项目做得再烂,你也要为其挂上敏捷的标签,只有学会像中国Thoughtworks的咨询师那样去忽悠
,你才能学会更炫更酷的方法,让整个团队和公司,甚至整个业界都开始躁动,这样才能真正为难维护的代码铺平道路。
这个文档中还有很多很多,实在是太TMD强大了,大家自己去看看吧。有精力有能力的朋友不妨把其翻译成中文。
总之,我们的口号是——Write Everywhere, Read Nowhere
在线编译器
,现在网上有很多在线编译器,直接贴代码,编译运行结果。比如各大高校的ACM OJ。
Codepad.org
是一个很有意思的网站,它的主页http://codepad.org/
很简单,左边是可以编译并执行的程序语言,右边则是让你输入程序的输入框,输入框的下面是一个“Run Code”的复选钮和一个“Submit”的提交按钮。
其操作起来也非常简单,先选中你要编译并运行的程序语言,然后在输入框中粘贴或输入程序的原代码,然后,点击提交,你就可以看么你程序编译出错的提示,或是执行的结果。
也许,你会觉得很无聊天,但我觉得这在某些时候会非常有用,尤其是你找不到编译器而又想验证一段代码的时候,这种时候还是比较多的。特别是我们很难
有一台可以运行所有语言的电脑,如果有的话,那一定是你自己的个人电脑,当你不使用你自己的电脑时,你就会着急了。而且,我觉得这项服务非常地有意思,因
为,这样一来,你甚至可以在你的手机上写任何语言的程序了。
目前这个网站支持下面这样语言——C,C++,D,Haskell,Lua,OCaml,PHP,Perl,Plain Text,Python,Ruby,Scheme,Tcl。(没有Java)
这个更猛在线的代码开发的IDE http://www.coderun.com/ide/ ,可以编译,执行,调试。不过,主要针对Web方面的,主要是C#,ASP.NET,Javascript(JQuery)和
PHP,很强大哦。那句话是怎么说来的——“如果一个软件可以用Javascript来写,那么这个软件的最终版本会是Javascript”。另外这个Online的IDE是开源的,源码在这里:http://coderun.codeplex.com/
。
comp.lang.c上有人问如何C输出下面图形
有人给出了这样的给力代码:
可以在Codepad
上面编译运行~~
=======转自http://coolshell.cn/
很不错的网站
输出Hello, World
混乱C语言的源代码
下面的所有程序都可以在GCC下编译通过,只有最后一个需要动用C++的编译器g++才能编程通过。
hello1.c
#define _________ } #define ________ putchar #define _______ main #define _(a) ________(a); #define ______ _______(){ #define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C) #define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F) #define ____ _(0x72)_(0x6C)_(0x64)_(0x21) #define _____ __ ___ ____ _________ #include<stdio.h> _____
hello2.c
#include<stdio.h> main(){ int x=0,y[14],*z=&y;*(z++)=0x48;*(z++)=y[x++]+0x1D; *(z++)=y[x++]+0x07;*(z++)=y[x++]+0x00;*(z++)=y[x++]+0x03; *(z++)=y[x++]-0x43;*(z++)=y[x++]-0x0C;*(z++)=y[x++]+0x57; *(z++)=y[x++]-0x08;*(z++)=y[x++]+0x03;*(z++)=y[x++]-0x06; *(z++)=y[x++]-0x08;*(z++)=y[x++]-0x43;*(z++)=y[x]-0x21; x=*(--z);while(y[x]!=NULL)putchar(y[x++]); }
hello3.c
#include<stdio.h> #define __(a) goto a; #define ___(a) putchar(a); #define _(a,b) ___(a) __(b); main() { _:__(t)a:_('r',g)b:_('$',p) c:_('l',f)d:_(' ',s)e:_('a',s) f:_('o',q)g:_('l',h)h:_('d',n) i:_('e',w)j:_('e',x)k:_('/n',z) l:_('H',l)m:_('X',i)n:_('!',k) o:_('z',q)p:_('q',b)q:_(',',d) r:_('i',l)s:_('w',v)t:_('H',j) u:_('a',a)v:_('o',a)w:_(')',k) x:_('l',c)y:_('/t',g)z:___(0x0)}
hello4.c
int n[]={0x48, 0x65,0x6C,0x6C, 0x6F,0x2C,0x20, 0x77,0x6F,0x72, 0x6C,0x64,0x21, 0x0A,0x00},*m=n; main(n){putchar (*m)!='/0'?main (m++):exit(n++);}
hello5.c
main(){int i,n[]={(((1<<1)<<(1<<1)<<(1<< 1)<<(1<<(1>>1)))+((1<<1)<<(1<<1))), (((1 <<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<<( 1<<1)<<(1<<1))+((1<<1)<<(1<<(1>>1)))+ (1 <<(1>>1))),(((1<<1)<<(1<<1)<<(1<<1)<< (1 <<1))-((1<<1)<<(1<<1)<<(1<<(1>>1)))- ((1 <<1)<<(1<<(1>>1)))),(((1<<1)<<(1<<1)<<(1 <<1)<<(1<<1))-((1<<1)<<(1<<1)<<(1<<(1>>1 )))-((1<<1)<<(1<<(1>>1)))),(((1<<1)<< (1 <<1)<<(1<<1)<<(1<<1))-((1<<1)<<(1<<1)<<( 1<<(1>>1)))-(1<<(1>>1))),(((1<<1)<<(1<<1 )<<(1<<1))+((1<<1)<<(1<<1)<<(1<<(1>>1))) -((1<<1)<<(1<<(1>>1)))),((1<<1)<< (1<<1) <<(1<<1)),(((1<<1)<<(1<<1)<<(1<<1)<<(1<< 1))-((1<<1)<<(1<<1))-(1<<(1>>1))),(((1<< 1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<< (1 <<1)<<(1<<(1>>1)))-(1<<(1>>1))), (((1<<1 )<<(1<<1)<<(1<<1)<<(1<<1))- ((1<<1)<< (1 <<1)<<(1<<(1>>1)))+(1<<1)), (((1<<1)<< ( 1<<1)<<(1<<1)<< (1<<1))-((1<<1)<< (1<<1) <<(1<<(1>>1)))-((1<<1) <<(1<< (1>>1)))), (((1<<1)<< (1<<1)<<(1<<1)<< (1<<1))- ((1 <<1)<<(1<<1)<<(1<<1))+((1<<1)<< (1<<(1>> 1)))), (((1<<1)<<(1<<1) <<(1<<1))+(1<<(1 >>1))),(((1<<1)<<(1<<1))+((1<<1)<< (1<<( 1>>1))) + (1<< (1>>1)))}; for(i=(1>>1);i <(((1<<1) <<(1<<1))+((1 <<1)<< (1<<(1>>1 ))) + (1<<1)); i++) printf("%c",n[i]); }
hello6.c
#include <stdio.h> #define _(_) putchar(_); int main(void){int i = 0;_( ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++i)_(++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++i)_(++++++++++++++ i)_(--++i)_(++++++i)_(------ ---------------------------- ---------------------------- ---------------------------- ---------------------------- ----------------i)_(-------- ----------------i)_(++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++ ++++++++++++++++++++++++++i) _(----------------i)_(++++++ i)_(------------i)_(-------- --------i)_(---------------- ---------------------------- ---------------------------- ---------------------------- ---------------------------- ------i)_(------------------ ---------------------------- i)return i;}
展示了一些C语言的变态玩法。也向大家展示了一下程序是可以写得让人看不懂的,在那篇文章中,可以看到很多人的留言,很多人都觉得很好玩,是的,那本来是用来供朋友们“消遣作乐”,供娱乐娱东而已,不必太过认真。
不过,通过这种极端的写法,大家可以看到源代码都可以写得那么复杂难懂的。大家也许在赞叹之余一笑了之,而我则希望,大家能够在娱乐以后认真思考一下,你不要以为咱们自己不会把代码搞得那么复杂,只不过没有像那6个Hello World一样那么极端,不过,说句老实话,咱们每个程序都有把清晰的程序搞得一团混乱的潜能,只不过程度不一样罢了,我并不是在这里危言耸听,大家好自为之
。
下面是一个Step by Step的教程,教你如何把一个清晰的代码变得复杂难懂的。当然,这只是一个“简明教程”了。还是那句话——“本文仅供朋友们“消遣作乐”,如果你要觉得有意思的话,顶个贴。如果你觉得没什么意思的话,一笑了之。仅供娱乐而已,不必太过认真。
”
开始程序
下面是一个找出素数的程序:void primes(int cap) { int i, j, composite; for(i = 2; i < cap; ++i) { composite = 0; for(j = 2; j * j < i; ++j) { composite += !(i % j); } if(!composite){ printf("%dt", i); } } } int main() { primes(100); }
第一步、把for变成while
通常来说,for循坏要以while循坏简单一些,上面的程序有二重for循环,我们不但要把其变成while循环,而且还要把二重循环的变成一重的循环,然后使用大量的if-else语句来判断。void primes(int cap) { int i, j, composite, t = 0; while(t < cap * cap) { i = t / cap; j = t++ % cap; if(i <= 1); else if(!j) composite = j; else if(j == i && !composite) printf("%dt",i); else if(j > 1 && j < i) composite += !(i % j); } } int main() { primes(100); }
第二步,把循坏变成递归
递归在某些时候是可以把代码变得简单,但大多数的情况下是把代码变得复杂,而且很没有效率。下面是把上面的while循环变成了递归。变成了递归后,函数的参数都变成3个了。
void primes(int cap, int t, int composite) { int i,j; i = t / cap; j = t % cap; if(i <= 1) primes(cap,t+1,composite); else if(!j) primes(cap,t+1,j); else if(j == i && !composite) (printf("%dt",i), primes(cap,t+1,composite)); else if(j > 1 && j < i) primes(cap,t+1, composite + !(i % j)); else if(t < cap * cap) primes(cap,t+1,composite); } int main() { primes(100,0,0); }
第三步,弄乱代码结构/使用没有含义的变量名
关于如何弄乱代码结构,其中一个小技巧是,使用“?”表达式代替if-else语句。
void primes(int m, int t, int c) { int i,j; i = t / m; j = t % m; (i <= 1) ? primes(m,t+1,c) : (!j) ? primes(m,t+1,j) : (j == i && !c) ? (printf("%dt",i), primes(m,t+1,c)) : (j > 1 && j < i) ? primes(m,t+1,c + !(i % j)) : (t < m * m) ? primes(m,t+1,c) : 0; } int main() { primes(100,0,0); }
第四步,取消临时变量
临时变量一般用来保存反复使用的一个表达式的值。使用大量重复的表达式来取消这些临时变量的也可以让代码复杂起来。
void primes(int m, int t, int c) { ((t / m) <= 1) ? primes(m,t+1,c) : !(t % m) ? primes(m,t+1, t % m) : ((t % m)==(t / m) && !c) ? (printf("%dt",(t / m)), primes(m,t+1,c)) : ((t % m)> 1 && (t % m) < (t / m)) ? primes(m,t+1,c + !((t / m) % (t % m))) : (t < m * m) ? primes(m,t+1,c) : 0; } int main() { primes(100,0,0); }
第五步,继续弄乱变量名
我们知道,下划线是合法的变量名,所以,我们不妨用__,___,____来代替m,t,c。函数名也可以使用下划线来代替。让我们来看看求素数的函数能变成什么。
void _(int __, int ___, int ____) { ((___ / __) <= 1) ? _(__,___+1,____) : !(___ % __) ? _(__,___+1,___ % __) : ((___ % __)==(___ / __) && !____) ? (printf("%dt",(___ / __)), _(__,___+1,____)) : ((___ % __) > 1 && (___ % __) < (___ / __)) ? _(__,___+1,____ + !((___ / __) % (___ % __))) : (___ < __ * __) ? _(__,___+1,____) : 0; } int main() { _(100,0,0); }
第六步,移除常量
在上面的程序中,还有一些常量,你可以通过增加一个宏定义,或是增加一个函数的形参来取代这一常量。void _(int __, int ___, int ____, int _____) { ((___ / __) <= _____) ? _(__,___+_____,____,_____) : !(___ % __) ? _(__,___+_____,___ % __, _____) : ((___ % __)==(___ / __) && !____) ? (printf("%dt",(___ / __)), _(__,___+_____,____,_____)) : ((___ % __) > _____ && (___ % __) < (___ / __)) ? _(__,___+_____,____,_____ + !((___ / __) % (___ % __))) : (___ < __ * __) ? _(__,___+_____,____,_____) : 0; } int main() { _(100,0,0,1); }
程序到这里应该差不多了。还是那句话——“每一个程序员都有把源代码弄复杂的潜质
”,大家好自为之。
如何写出无法维护的代码?
这篇文章的原文在这里(http://mindprod.com/jgloss/unmain.html
),我看完后我想说——
什么叫“创造力”,创造力就是——就算是要干一件烂事都能干得那么漂亮那么有创意的能力。
什么叫“抓狂”,抓狂就是——以一种沉着老练的不屈不挠的一本正经的精神一点一点把你推向崩溃的边缘
。
程序命名
容易输入的名字。比如:Fred,asdf
单字母的变量名
。比如:a,b,c, x,y,z(陈皓注:如果不够用,可以考虑a1,a2,a3,a4,….)
有创意地拼写错误
。比如:SetPintleOpening, SetPintalClosing。这样可以让人很难搜索代码。
抽象
。比如:ProcessData, DoIt, GetData… 抽象到就跟什么都没说一样。
缩写
。比如:WTF,RTFSC …… (陈皓注:使用拼音缩写也同样给力,比如: BT,TMD,TJJTDS)
随机大写字母
。比如:gEtnuMbER..
重用命名
。在内嵌的语句块中使用相同的变量名有奇效。
使用重音字母
。比如:int ínt(注:第二个 ínt不是int)
使用下划线
。比如:_, __, ___。
使用不同的语言
。比如混用英语,德语,或是中文拼音。
使用字符命名
。比如:slash, asterix, comma…
使用无关的单词
。比如:god, superman, iloveu….
混淆l和1
。字母l和数字1有时候是看不出来的。
伪装欺诈
把注释和代码交织在一起。
for(j=0; j<array_len; j+ =8) { total += array[j+0 ]; total += array[j+1 ]; total += array[j+2 ]; /* Main body of total += array[j+3]; * loop is unrolled total += array[j+4]; * for greater speed. total += array[j+5]; */ total += array[j+6 ]; total += array[j+7 ]; }
隐藏宏定义
。如:#define a=b a=0-b,当人们看到a=b时,谁也想不到那是一个宏。
换行
。如下所示,下面的示例使用搜索xy_z变得困难。。
#define local_var xy/ _z // local_var OK
代码和显示不一致
。比如,你的界面显示叫postal code,但是代码里确叫 zipcode.
隐藏全局变量
。把使用全局变量以函数参数的方式传递给函数,这样可以让人觉得那个变量不是全局变量。
使用同意词
。如:
#define xxx global_var // in file std.h #define xy_z xxx // in file ../other/substd.h #define local_var xy_z // in file ../codestd/inst.h
使用相似的变量名
。如:单词相似,swimmer 和 swimner,字母相似:ilI1| 或
oO08。parselnt 和 parseInt, D0Calc 和 DOCalc。还有这一组:xy_Z, xy__z, _xy_z,
_xyz, XY_Z, xY_z, Xy_z。
重载函数
。使用相同的函数名,但是其功能和具体实现完全没有关系。
操作符重载
。重载操作符可以让你的代码变得诡异,感谢CCTV,感谢C++。这个东西是可以把混乱代码提高到
一种艺术的形式。比如:重载一个类的 ! 操作符,但实际功能并不是取反,让其返回一个整数。于是,如果你使用 ! !
操作符,那么,有意思的事就发生了—— 先是调用类的重载 ! 操作符,然后把其返回的整数给 ! 成了 布尔变量,如果是 !!! 呢?呵呵。
#define
。看过本站那些混乱代码的文章,你都会知道宏定义和预编译对于写出不可读的代码的重大意义。不过,一个具有想像力的东西是——在头文件中使用预编译来查看这个头文件被include了几次,而被include不同的次数时,其中的函数定义完全不一样。
#ifndef DONE #ifdef TWICE // put stuff here to declare 3rd time around void g(char* str); #define DONE #else // TWICE #ifdef ONCE // put stuff here to declare 2nd time around< void g(void* str); #define TWICE #else // ONCE // put stuff here to declare 1st time around void g(std::string str); #define ONCE #endif // ONCE #endif // TWICE #endif // DONE
文档和注释
在注释中撒谎。你不用真的去撒谎,只需在改代码的时候不要更新注释就可以了。
注释明显的东西
。比如:/* add 1 to i */。(五种应该避免的注释
)
只注释是什么,而不是为什么
。
不要注释秘密
。如果你开发一个航班系统,请你一定要保证每有一个新的航班被加入,就得要修改25个以上的位置的程序。千万别把这个事写在文档中。
注重细节
。当你设计一个很复杂的算法的时候,你一定要把所有的详细细设计都写下来,没有100页不能罢休,段
落要有5级以上,段落编号要有500个以上,例如:1.2.4.6.3.13 – Display all impacts for activity
where selected mitigations can apply (short pseudocode omitted).
这样,当你写代码的时候,你就可以让你的代码和文档一致,如:Act1_2_4_6_3_13()
千万不要注释度衡单位
。比如时间用的是秒还是毫秒,尺寸用的是像素还是英寸,大小是MB还是KB。等等。另外,在你的代码里,你可以混用不同的度衡单位,但也不要注释。
Gotchas
。陷阱,千万不要注释代码中的陷阱。
在注释和文档中发泄不满
。(五种应该避免的注释
)
程序设计
Java Casts。Java的类型转型是天赐之物。每一次当你从Collection里取到一个object的时候,你都需要把其转回原来的类型。因些,这些转型操作会出现在N多的地方。如果你改变了类型,那么你不一定能改变所有的地方。而编译器可能能检查到,也可能检查不到。
利用Java的冗余
。比如:Bubblegum b = new Bubblegom(); 和 swimmer = swimner + 1; 注意变量间的细微差别。
从不验证
。从不验证输入的数据,从不验证函数的返回值。这样做可以向大家展示你是多么的信任公司的设备和其它程序员。
不要封装
。调用者需要知道被调用的所有的细节。
克隆和拷贝
。为了效率,你要学会使用copy + paste。你几乎都不用理解别人的代码,你就可以高效地编程了。(陈皓注:Copy + Paste出来的代码bug多得不能再多)
巨大的listener
。写一个listener,然后让你的所有的button类都使用这个listener,这样你可以在这个listener中整出一大堆if…else…语句,相当的刺激。
使用三维数组
。如果你觉得三维还不足够,你可以试试四维。
混用
。同时使用类的get/set方法和直接访问那个public变量。这样做的好处是可以极大的挫败维护人员。
包装,包装,包装
。把你所有的API都包装上6到8遍,包装深度多达4层以上。然后包装出相似的功能。
没有秘密
。把所有的成员都声明成public的。这样,你以后就很难限制其被人使用,而且这样可以和别的代码造成更多的耦合度,可以让你的代码存活得更久。
排列和阻碍
。把drawRectangle(height, width) 改成 drawRectangle(width, height),等release了几个版本后,再把其改回去。这样维护程序的程序员们将不能很快地明白哪一个是对的。
把变量改在名字上
。例如,把setAlignment(int alignment)改成,setLeftAlignment, setRightAlignment, setCenterAlignment。
Packratting
。保留你所有的没有使用的和陈旧的变量,方法和代码。
That’s Fina
l。Final你所有的子结点的类,这样,当你做完这个项目后,没有人可以通过继承来扩展你的类。java.lang.String不也是这样吗?
避免使用接口
。在java中,BS接口,在C++中BS使用虚函数。
避免使用layout
。这样就使得我们只能使用绝对坐标。如果你的老大强制你使用layout,你可以考虑使用GridBagLayout,然后把grid坐标hard code.
环境变量
。如果你的代码需要使用环境变量。(getenv() – C++ / System.getProperty() – Java ),那么,你应该把你的类的成员的初始化使用环境变量,而不是构造函数。
使用Magic numbe
r。参看《Linux一个插曲
》。
使用全局变量
。1)把全局变量的初始化放在不同的函数中,就算这个函数和这个变量没有任何关系,这样能够让我们的维护人员就像做侦探工作一样。2)使用全局变量可以让你的函数的参数变得少一些。
配置文件
。配置文件主要用于一些参数的初始化。在编程中,我们可以让配置文件中的参数名和实际程序中的名字不一样。
膨胀你的类
。让你的类尽可能地拥有各种臃肿和晦涩的方法。比如,你的类只实现一种可能性,但是你要提供所有可能性的方法。不要定义其它的类,把所有的功能都放在一个类中。
使用子类
。面向对象是写出无法维护代码的天赐之物。如果你有一个类有十个成为(变量和方法)你可以考虑写10个层次的继承,然后把这十个属性分别放在这十个层次中。如果可能的话,把这十个类分别放在十个不同的文件中。
混乱你的代码
使用XML。XML的强大是无人能及的。使用XML你可以把本来只要10行的代码变成100行。而且,还要逼着别人也有XML。(参看,信XML得永生
,信XML得自信
)
混乱C代码
。在《如何加密源代码
》中已经说过一些方法了,这里再补充一些。
使用不同的进制
。比如:10 和010不是一样的。再比如:array = new int[]{ 111, 120, 013, 121,};
尽量使用void*
。然后把其转成各种类型
使用隐式的转型
。C++的构造函数可以让你神不知鬼不觉得完成转型。
分解条件表达式
。如:把 a==100分解成,a>99 && a<101
学会利用分号
。如:if ( a );else;{ int d; d = c;}
间接转型
。如:把double转string,写成new Double(d).toString() 而不是 Double.toString(d)
大量使用嵌套
。一个NB的程序员可以在一行代码上使用超过10层的小括号(),或是在一个函数里使用超过20层的语句嵌套{},把嵌套的if else 转成 [? :] 也是一件很NB的事。
使用C的变种数组
。myArray[i] 可以变成*(myArray + i) 也可以变成 *(i +
myArray) 其等价于 i[myArray]。再看一个函数调用的示例,函数声明:int myfunc(int q, int p) {
return p%q; } 函数调用myfunc(6291, 8)[Array];
长代码行
。一行的代码越长越好。这样别人阅读时就需要来来回回的
不要较早的return
。不要使用goto,不要使用break,这样,你就需要至少5层以上的if-else来处理错误。
不要使用{}
。不要在if else使用{},尤其是在你重量地使用if-else嵌套时,你甚至可以在其中乱缩进代码,这样一来,就算是最有经验的程序员也会踩上陷阱。
使用宏定义
。宏定义绝对是混乱C/C++代码的最佳利器。参看 老手是这样教新手编程的
。
琐碎的封装
。比较封装一个bool类,类里面什么都做,就是一个bool.
循环
。千万不可用for(int i=0; i<n; i++)使用while代替for,交换n和i,把<改成<=,使用 i–调整步伐 。
测试
从不测试。千万不要测试任何的出错处理,从来也不检测系统调用的返回值。
永远不做性能测试
。如果不够快就告诉用户换一个更快的机器。如果你一做测试,那么就可能会要改你的算法,甚至重设计,重新架构。
不要写测试案例
。不要做什么代码覆盖率测试,自动化测试。
测试是懦夫行为
。一个勇敢的程序员是根本不需要这一步的。太多的程序太害怕他们的老板,害怕失去工作,害怕用户抱怨,甚至被起诉。这种担心害怕直接影响了生产力。如果你对你的代码有强大的信心,那还要什么测试呢?真正的程序员是不需要测试自己的代码的。
其它
你的老板什么都知道。无论你的老板有多SB,你都要严格地遵照他的旨意办事,这样一来,你会学到更多的知识如何写出无法维护的代码来的。
颠覆Help Desk
。你要确保你那满是bug的程序永远不要被维护团队知道。当用户打电话和写邮件给你的时候,你就不要理会,就算要理会,让用户重做系统或是告诉用户其帐号有问题,是标准的回答。
闭嘴
。对于一些像y2k这样的大bug,你要学会守口如瓶,不要告诉任何人,包括你的亲人好友以及公司的同事和管理层,这样当到那一天的时候,你就可以用这个bug挣钱了。
忽悠
。你会学会忽悠,就算你的代码写得很烂,你也要为其挂上GoF设计模式的标签,就算你的项目做得再烂,你也要为其挂上敏捷的标签,只有学会像中国Thoughtworks的咨询师那样去忽悠
,你才能学会更炫更酷的方法,让整个团队和公司,甚至整个业界都开始躁动,这样才能真正为难维护的代码铺平道路。
这个文档中还有很多很多,实在是太TMD强大了,大家自己去看看吧。有精力有能力的朋友不妨把其翻译成中文。
总之,我们的口号是——Write Everywhere, Read Nowhere
在线编译器
,现在网上有很多在线编译器,直接贴代码,编译运行结果。比如各大高校的ACM OJ。
Codepad.org
是一个很有意思的网站,它的主页http://codepad.org/
很简单,左边是可以编译并执行的程序语言,右边则是让你输入程序的输入框,输入框的下面是一个“Run Code”的复选钮和一个“Submit”的提交按钮。
其操作起来也非常简单,先选中你要编译并运行的程序语言,然后在输入框中粘贴或输入程序的原代码,然后,点击提交,你就可以看么你程序编译出错的提示,或是执行的结果。
也许,你会觉得很无聊天,但我觉得这在某些时候会非常有用,尤其是你找不到编译器而又想验证一段代码的时候,这种时候还是比较多的。特别是我们很难
有一台可以运行所有语言的电脑,如果有的话,那一定是你自己的个人电脑,当你不使用你自己的电脑时,你就会着急了。而且,我觉得这项服务非常地有意思,因
为,这样一来,你甚至可以在你的手机上写任何语言的程序了。
目前这个网站支持下面这样语言——C,C++,D,Haskell,Lua,OCaml,PHP,Perl,Plain Text,Python,Ruby,Scheme,Tcl。(没有Java)
这个更猛在线的代码开发的IDE http://www.coderun.com/ide/ ,可以编译,执行,调试。不过,主要针对Web方面的,主要是C#,ASP.NET,Javascript(JQuery)和
PHP,很强大哦。那句话是怎么说来的——“如果一个软件可以用Javascript来写,那么这个软件的最终版本会是Javascript”。另外这个Online的IDE是开源的,源码在这里:http://coderun.codeplex.com/
。
comp.lang.c上有人问如何C输出下面图形
* *** ***** ******* ********* ********* ******* ***** *** *
有人给出了这样的给力代码:
#define M 002354l #define A 000644l #define G 000132l #define I 000322l #define C 000374l #define a ; #define b for #define c ++ #define d % #define e int #define f , #define g - #define h 011 #define i = #define j { #define k ) #define l '/n' #define m main #define n < #define o } #define p > #define q && #define r ( #define s || #define t ? #define u putchar #define v void #define w '*' #define x : #define y ' ' #define _ / #define C_O_O_L return e u r e k a e m r v k j j j j j j j j j j j j j j j j j j j j j j j j e z a b r z i M _ A _ G _ I _ C a z n G a u r z d h + z _ h p M _ A q z d h + z _ h n M _ G q z _ h n z d h + M _ I q z _ h p z d h g M _ C t w x y k f z d h g h + 1 s u r l k f z c k a u r l k a j j j j j j j j j j j C_O_O_L M _ A _ G _ I _ C a o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
可以在Codepad
上面编译运行~~
=======转自http://coolshell.cn/
很不错的网站
相关文章推荐
- 六个变态的Hello World!(混乱代码)
- java在线预览txt、word、ppt、execel,pdf代码
- echo 'hello lining' > /dev/wordcount
- google_v8学习笔记:NO2 第一个代码Hello_word
- C中char str[] = "hello word";与char *str = "hello word";
- java在线预览txt、word、ppt、execel,pdf代码
- 遇到一个代码混乱不堪的Android项目该怎么办?
- 在线编辑word文档代码
- String s = "Hello";s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
- 在线word文件怎么转换成pdf
- python在线编译器的简单原理及简单实现代码
- win7 变WIFI热点 & 在线Linux 内核代码
- HTML/CSS/Javascript/json代码在线压缩&格式化常用工具
- java在线预览txt、word、ppt、execel,pdf代码
- ASP.NET实现word文档在线预览功能代码
- java在线预览txt、word、ppt、execel,pdf代码
- easyUI学习记录(一)- Helloword&&easyloader介绍
- java在线预览txt、word、ppt、execel,pdf代码
- 当不断添加的新功能让代码混乱不堪该怎么办?
- 几个“Hello World"的代码混淆