CWYAlpha

Just another WordPress.com site

Thought this was cool: 打印自身的程序

leave a comment »




当初看到matrix67上介绍的这个函数时震惊的不行,看了解释后发现其实也不是很难,于是最近又看到这个打印自身源码程序的程序,一开始大家都会有种神来之笔的感觉,其实了解到背后的想法和构思过程的话,其实自己去实现一个也不是很难的事情。

首先我们要说的这个问题其实已经是蛮常见的了,被成为Quine,详细的介绍可以看wiki,我们可以在这里看到很多quine程序,简单来说quine是表示一个可以生成他自己的完全的源代码的程序,但是要求程序不能接受输入,而且不能读文件,不然我们可以有如下简单的python程序。

  1. printopen(__file__).read()

因此我们这里需要无视掉类似读文件等cheating的做法,首先声明,我是看了这篇文章才理解的如何写quine的,如果英语不错的话,建议还是去读读原文。

对于c++的程序而言,我们都是这样写的

  1. #include<cstdio>
  2. intmain(){
  3.    //todo
  4.    return0;
  5. }

于是我们的quine应该大体是这样的

  1. #include<cstdio>
  2. intmain(){
  3.    //todo
  4.    printf(“#include<cstdio>\nint main(){    //todo\n   printf();\n   retuen 0;\n}\n”);
  5.    return0;
  6. }

于是问题来了在printf里的printf写什么呢,又需要把整个程序写一遍吗,于是我们可以想到可以利用字符串来进行类似的操作也就是这样

a=”a=%s”;

printf(a,a);

那么,这就是我们quine的核心思想了,总结一下,就是说我们代码分为两部分,第一部分是data,第二部分是code,data中就是整个程序,描述了data自己还有code部分,然后code就是需要把data输出就可以了,而data中描述自己的技巧就是利用”%s”这样子了,于是c++代码如下。

  1. #include<cstdio>
  2. intmain(){
  3.    constchar*a=”#include<cstdio>%cint main(){%c    const char *a=%c%s%c;%c    printf(a,10,10,34,a,34,10,10,10,10);%c    return 0;%c}%c”;
  4.    printf(a,10,10,34,a,34,10,10,10,10);
  5.    return0;
  6. }

还有个需要注意的地方就是引号和\n需要进行转义,这里就用了其ASCII中的值,34是引号,10就是\n。

ok,我们进一步做点更有难道的,让程序A输出程序B,程序B去生成程序A,先看我写的代码吧。

  1. a=’a=%s%cb=%s%cprint b%%(`b`,`a`)’
  2. b=’b=%s;a=%s;print a%%(`a`,10,`b`,10)’
  3. printb%(`b`,`a`)
  1. b=’b=%s;a=%s;print a%%(`a`,10,`b`,10)’;a=’a=%s%cb=%s%cprint b%%(`b`,`a`)’;print a%(`a`,10,`b`,10)

这两个都是python程序,其中一个可以去生成另一个。其实思想都是一样的每个程序都分为data和code两部分,然后让code去输出data部分,那么这里我们需要生成两个程序,所以每个程序都要有两个程序的描述,一个描述自己,另一个去描述另一个,然后code部分输出时依旧是利用那个技巧进行嵌套于是程序就出来了。

最后不得不提一下scturtle童鞋的这篇文章利用quine来实现不定义函数实现递归,也是很赞的东西阿。

我猜您可能还会喜欢:


0

   

0

IT 牛人博客聚合网站(udpwork.com) 聚合
|
评论: 0
|
10000+ 本编程/Linux PDF/CHM 电子书下载

from IT牛人博客聚合网站: http://www.udpwork.com/item/8752.html

Written by cwyalpha

十一月 27, 2012 在 7:45 上午

发表在 Uncategorized

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: