科技讯息网 – 程序员的那点事!

首页 > 编程资料 > C/C++语言 > 正文

如何让程序打印它自己??

浏览次数:次 2007年05月04日 作者:sega6666 字号:

:em17:?
我还是个学生,请前辈们多指教。
我们这次作业思考题有一道是让我们编个程序
而最后打印出的结果是这个程序它自己!
请问前辈们我应该怎么些这个程序呢?
前提我现在只学了main函数,数组等基本知识
指针什么的都没学到!
老师让我们用现在所学的知识编出来,我不会!
请前辈们指点,谢谢!



?flw 回复于:2004-10-08 12:06:33

引用:老师让我们用现在所学的知识编出来

不用管老师的话,
只要你编出来就行了。
哪怕是用了指针也无妨。

文件操作学了吗?
如果没有学的话,这个题目是没法做的。

另外,老师指定的操作系统是什么?
编程工具是什么?

DOS?+?TC??
WINDOWS?+?VC?
UNIX?+?GCC?


?albcamus 回复于:2004-10-08 13:16:13

“程序打印自己”?

倘若是C这种编译型的,那么做“打印”这件事时的“程序”就是可执行文件,已经不是源代码的“自己”了


?不倒翁(A) 回复于:2004-10-08 13:40:06

刚开始学,那你老师的意思很有可能就是用数组保存你的程序了(你赋值字符串给数组,也就是你的程序),要不只有使用文件了


?win_hate 回复于:2004-10-08 14:09:18

It?sonuds?like?a?classical?problem?and?it?seems?to?be?too?hard?for?a?newbie.?Anyway,?the?codes?below?meet?your?requist.


char?*p?=?"\xa\x6d\x61\x69\x6e\x28\x29\xa\x7b\xa\x9\x63\x68\x61\x72\x20\x2a\x71\x20\x3d\x20\x70\x3b\xa\x9\x70\x72\x69\x6e\x74\x66\x20\x28\x22\x63\x68\x61\x72\x20\x2a\x70\x20\x3d\x20\x5c\x22\x22\x29\x3b\xa\x9\x77\x68\x69\x6c\x65\x20\x28\x2a\x70\x29\xa\x9\x9\x70\x72\x69\x6e\x74\x66\x20\x28\x22\x5c\x5c\x78\x25\x78\x22\x2c\x20\x2a\x70\x2b\x2b\x29\x3b\xa\x9\x70\x72\x69\x6e\x74\x66\x20\x28\x22\x5c\x22\x3b\x5c\x6e\x25\x73\x22\x2c\x20\x71\x29\x3b\xa\x7d\xa";

main()
{
????????char?*q?=?p;
????????printf?("char?*p?=?\"");
????????while?(*p)
????????????????printf?("\\x%x",?*p++);
????????printf?("\";\n%s",?q);
}


./a.out?|?diff?-?foo.c


?流川 回复于:2004-10-08 16:50:32

楼上的,?这个程序实在是经典

是不是可以解释一下?


?流川 回复于:2004-10-08 16:59:03

"\xa\x6d\x61\x69\x6e\x28\x29\xa\x7b\xa\x9\x63\x68\x61\x72\x20\x2a\x71\x20\x3d\x20\x70\x3b\xa\x9\x70\x72\x69\x6e\x74\x66\x20\x28\x22\x63\x68\x61\x72\x20\x2a\x70\x20\x3d\x20\x5c\x22\x22\x29\x3b\xa\x9\x77\x68\x69\x6c\x65\x20\x28\x2a\x70\x29\xa\x9\x9\x70\x72\x69\x6e\x74\x66\x20\x28\x22\x5c\x5c\x78\x25\x78\x22\x2c\x20\x2a\x70\x2b\x2b\x29\x3b\xa\x9\x70\x72\x69\x6e\x74\x66\x20\x28\x22\x5c\x22\x3b\x5c\x6e\x25\x73\x22\x2c\x20\x71\x29\x3b\xa\x7d\xa";?


刚测试了一下,以上的代码就是涵数体的变形用十六进制的形式表现出来!

其实就是打印两遍,一遍打印自身,一遍打印涵数体

不错不错,高,实在是高!


?流川 回复于:2004-10-08 17:01:20

那还可以把它转化而以\000开头的用八进制表示


?流川 回复于:2004-10-08 17:06:27

还有没有更好的方法?

上面的代码好像还要事先把源代码转化成字符串

有没有办法自动生成啊??


?FH 回复于:2004-10-08 17:18:49

俺记得前一阵俺也写过一个,再贴一次吧。
#include?;

int?main()
{
???FILE?*f;
???char?c;

???if?(?(?f?=?fopen(?__FILE__,?"r"?)?)?!=?NULL?)?{
??????while?(?fread(?&c,?1,?1,?f?)?==?1?)
??????????frwite(?&c,?1,?1,?stdout?);
??????fclose(?f?);
???}
???return?0;
}

这个实现要求文件操作的知识,而win_hate兄的则不需要;但是这个程序可在任何字符集的机器上得到正常结果,而win_hate兄的只能在ASCII字符集的机器上得到正常结果。当然把win_hate兄的实现稍做改动也是可以达到同样目的的,但那样就没有现在这样的悬念了,呵呵。


?aero 回复于:2004-10-08 17:20:37

呵呵,还可以用__FILE__来实现哦。不过,是偷懒的办法了。


?aero 回复于:2004-10-08 17:21:58

^_^,FH兄发上来了哈。


?converse 回复于:2004-10-08 17:43:02

无语,一个刚学c的学生碰到这样的老师只能自认倒霉了--不引导学生学习一些实用的编程技术,编程思想却来这么一个偏、怪的题目,唉........
这位同学,这个老师的课不上也罢了,找来老谭的书或者K&R的书自己来看吧(这两本书都有习题集),然后自己上机实践吧,不懂的上来问吧,不要给这个老师引到一些偏门去了。


?picobsd 回复于:2004-10-08 18:09:17

我觉得他的要求是打印程序,而不是打印源代码,思路是这样的,通过读取进程表等方法可获得当前进程的路径,open这个文件,然后按16进制打印出来就可以了


?win_hate 回复于:2004-10-08 18:20:19

如何“生成源代码”,按?it?界的标准,算得上是历史悠久的问题了。它是前辈黑客的游戏,请参考这篇文章,Ken?Thompson?得图灵奖后发表的演讲:

http://www.acm.org/classics/sep95/

这篇文章与?unix?历史上的??login?后门有关。


?sega6666 回复于:2004-10-08 20:42:51

哦,多谢前辈们!今天我刚下课回来!老师出的这个只是个思考题!
他说的答案是
#include;
void?main()
{
?????system("type?a.c")/*这个程序保存成a.c
}

对不起,之前没说清楚我现在学的是C用的是VC++6.0


?aero 回复于:2004-10-08 21:15:56

晕死,你们老师的答案也太……


?sega6666 回复于:2004-10-08 21:29:58

这个答案怎么了????说完整啊,很想知道,谢谢


?win_hate 回复于:2004-10-08 21:39:07

我也晕。

按你们老师的做,他说得没错。


?THEBEST 回复于:2004-10-08 22:35:15

1。?
char*f="main(){putchar('c');putchar('h');putchar('a');putchar('r');?
putchar('*');&?
putchar('f');putchar('=');putchar(34);printf(f);putchar(34);?
putchar(';');&?
putchar(10);printf(f);putchar(10);}";?
main(){putchar('c');putchar('h');putchar('a');putchar('r');?
putchar('*');putchar('f');&?
putchar('=');putchar(34);printf(f);putchar(34);putchar(';');?
putchar(10);&?
printf(f);putchar(10);}?

2。?
char*f="char*f=;main(){f[7]=0;printf(f);putchar(34);f[7]=';';?
printf(f);&?
putchar(34);f[8]=0;printf(&f[7]);f[8]='m';putchar(10);?
printf(&f[8]);putchar(10);}";?
main(){f[7]=0;printf(f);putchar(34);f[7]=';';printf(f);putchar(34);&?
f[8]=0;printf(&f[7]);f[8]='m';putchar(10);printf(&f[8]);?
putchar(10);}?

3。?
char*f="char*f=%c%s%c;%cmain(){printf(f,34,f,34,10,10);}%c";?
main(){printf(f,34,f,34,10,10);}?

4。?
char?a='"';char?b='\n';char?c='\\';?
char*f="char?a='%c';char?b='%cn';char?c='%c%c';%cchar*f=%c%s%c;%cmain(){&?
printf(f,a,c,c,c,b,a,f,a,b,b);}%c";?
main(){printf(f,a,c,c,c,b,a,f,a,b,b);}?

5。?
char*lines[]={?
"char*lines[]={",?
"%c%s%c%c%c",?
"0};",?
"main(){",?
"int?idx;",?
"puts(lines[0]);",?
"for(idx=0;lines[idx]!=0;idx++){",?
"printf(lines[1],34,lines[idx],34,',',10);",?
"}",?
"puts(lines[2]);",?
"for(idx=3;lines[idx]!=0;idx++){",?
"puts(lines[idx]);",?
"}",?
"}",?
0};?
main(){?
int?idx;?
puts(lines[0]);?
for(idx=0;lines[idx]!=0;idx++){?
printf(lines[1],34,lines[idx],34,',',10);?
}?

puts(lines[2]);?
for(idx=3;lines[idx]!=0;idx++){?
puts(lines[idx]);?
}?
}?



?win_hate 回复于:2004-10-08 22:44:08

http://www.cgl.uwaterloo.ca/~csk/washington/sdc_paper/index.html


?sega6666 回复于:2004-10-08 22:48:11

因为我刚开始学不久,C还没有完全学完,刚学习了数组,所以请前辈们不弃多指点指点我,谢谢你们!~晚辈在这里向你们敬礼了!~


?FH 回复于:2004-10-09 08:38:01

楼主的老师真不愧是中国的老师!让我想起了大跃进时用农村的大柴锅炼钢的创意——真土!


?黄山松 回复于:2004-10-09 09:20:21

倒,那干吗还号称要把程序的源代码打印出来啊,直接说打印一个文件内容不就明白啦!


?biwu 回复于:2004-10-09 10:09:00

我倒是觉得这个老师的答案非常好,大家不要让聪明蒙蔽了自己的眼睛


?win_hate 回复于:2004-10-09 10:21:11

引用:原帖由?"biwu"]我倒是觉得这个老师的答案非常好,大家不要让聪明蒙蔽了自己的眼睛
?发表:


引用:原帖由?"黄山松"]?倒,那干吗还号称要把程序的源代码打印出来啊,直接说打印一个文件内容不就明白啦!
?发表:


引用:原帖由?"win_hate"?发表:

如何“生成源代码”,按?it?界的标准,算得上是历史悠久的问题了。它是前辈黑客的游戏




?wqzunix 回复于:2004-10-09 11:12:30

:(?[color=red][/color][size=18][/size][size=12][/size]
看到这么多人发表的高见,我真是汗颜,
对于编程这个问题我真的是太不懂了,希望各位才人高手多指点指点!!!!


?sega6666 回复于:2004-10-09 11:43:19

引用:原帖由?"黄山松"]倒,那干吗还号称要把程序的源代码打印出来啊,直接说打印一个文件内容不就明白啦!
?发表:


?:shock:?老师的答案也可以叫做是打印一个文件内容吧!
??????????????不过老师说的也没错吧!
??????????????两种都可以编出这种结果吧!


?win_hate 回复于:2004-10-09 12:05:42

对一个问题的理解与具体的环境有关。同样的一句话,可能在你们的课堂环境中是很清楚的,没有歧义的,但转到这里来之后,就被误解了。

既然楼主的问题已经解决,这个贴子就不必再顶了吧?


?sega6666 回复于:2004-10-09 12:16:00

是,老大!


?czyf2001 回复于:2004-10-11 09:58:10

win_hate的程序是很有技巧!

其实*p以%c打印出来,就是以main开始的主程序!


呵呵,这种思路真的能让人迷惑啊!

牛人就是强!
强!!


?l4kernel 回复于:2007-04-28 00:11:32

这个就是所谓quine,其实很简单,和用什么数进制表达无关。

程序分为三部分:
1,字符串s,内容是s后的全部内容,包括"\n""\t"等;
2,函数定义(如果需要)
3,主函数,打印“s="”+s内容(显示escape?sequences)+s内容(不显示escape?sequences)

学过可计算理论的可以用不动点定理证明这种程序的存在。并且程序源码不仅是可以被打印,而是可以作为本程序自己的输入,所以也可以写个程序,输出程序自己的长度/MD5等等。

老师出这个题目并没有什么不妥,quine是很有趣的问题。


?cjaizss 回复于:2007-04-28 00:21:12

病毒的思想


?emacsnw 回复于:2007-04-28 05:52:47

也来一个:

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}




[bohnanza:misc]$?cc?test.c?-o?test
[bohnanza:misc]$?cat?test.c
char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}
[bohnanza:misc]$?./test
char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}



?emacsnw 回复于:2007-04-28 05:57:39

引用:原帖由?emacsnw?于?2007-4-27?13:52?发表
也来一个:

char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}




[bohnanza:misc]$?cc?test.c?-o?test
[bohnanza:misc]$?cat?tes?...?



刚看到前面有人回帖已经有这个了,貌似用C写的话这个是最短的了(就我所知)。
不知道有没有大侠能够证明一下,最短的这样的C程序至少要多长。应该比较有趣啊,呵呵。


?yuanchengjun 回复于:2007-04-28 09:04:12

大家不要丢我砖。

嗯,这个问题么,从软件工程的角度看,很简单,
就是需求没有搞明白。就是程序的具体功能没有搞明白。

还是比较喜欢ACM赛题,不仅有说明,而且有例子;
一次笔试,“请描述你打算使用的数据结构用来实现XX的功能。”
结果,我认为么,写个数据结构就OK了。
结果人家要整个算法实现。无语了。


?cugb_cat 回复于:2007-04-28 09:18:34

引用:原帖由?win_hate?于?2004-10-8?14:09?发表
It?sonuds?like?a?classical?problem?and?it?seems?to?be?too?hard?for?a?newbie.?Anyway,?the?codes?below?meet?your?requist.


char?*p?=?"\xa\x6d\x61\x69\x6e\x28\x29\xa\x7b\xa\x9\x63\x68\x?...?


对版主的敬仰犹如滔滔江水啊~~~~~~~
实在是佩服佩服
不过还是不太明白原理,版主老大给解释一下好吗?


?zhuomingliang 回复于:2007-05-03 23:20:48

from:http://www.cgl.uwaterloo.ca/~csk/washington/sdc_paper/index.html
都放这里:em12:
感谢21楼win_hate
引用:Appendix?A:?Source?Code
This?appendix?contains?all?the?individual?programs?which?appear?in?the?report,?along?with?the?ones?which?are?referred?to?but?which?to?not?appear?in?the?body?of?the?report.?

Failure?I?

????char*f="main(){printf(f);printf(f);}";main(){printf(f);printf(f);}

Failure?II?

????char*f="main(){printf("char*f="");printf(f);printf("";\n");printf(f);}";
????main(){printf("char*f="");printf(f);printf("";\n");printf(f);}

Failure?III?

????char*f="main(){printf(\"char*f=\"\");printf(f);printf(\"\";\\n\");printf(f);}";
????main(){printf("char*f=\"");printf(f);printf("\";\n");printf(f);}

Self?0?

????char*f="main(){putchar('c');putchar('h');putchar('a');putchar('r');putchar('*');&
????????putchar('f');putchar('=');putchar(34);printf(f);putchar(34);putchar(';');&
????????putchar(10);printf(f);putchar(10);}";
????main(){putchar('c');putchar('h');putchar('a');putchar('r');putchar('*');putchar('f');&
????????putchar('=');putchar(34);printf(f);putchar(34);putchar(';');putchar(10);&
????????printf(f);putchar(10);}

Self?I?

????char*f="char*f=;main(){f[7]=0;printf(f);putchar(34);f[7]=';';printf(f);&
????????putchar(34);f[8]=0;printf(&f[7]);f[8]='m';putchar(10);printf(&f[8]);putchar(10);}";
????main(){f[7]=0;printf(f);putchar(34);f[7]=';';printf(f);putchar(34);&
????????f[8]=0;printf(&f[7]);f[8]='m';putchar(10);printf(&f[8]);putchar(10);}

Self?II?

????char*f="char*f=%c%s%c;%cmain(){printf(f,34,f,34,10,10);}%c";
????main(){printf(f,34,f,34,10,10);}

Self?III?

????char?a='"';char?b='\n';char?c='\\';
????char*f="char?a='%c';char?b='%cn';char?c='%c%c';%cchar*f=%c%s%c;%cmain(){&
????????printf(f,a,c,c,c,b,a,f,a,b,b);}%c";
????main(){printf(f,a,c,c,c,b,a,f,a,b,b);}

Self?IV?

????char*lines[]={
????"char*lines[]={",
????"%c%s%c%c%c",
????"0};",
????"main(){",
????"int?idx;",
????"puts(lines[0]);",
????"for(idx=0;lines[idx]!=0;idx++){",
????"printf(lines[1],34,lines[idx],34,',',10);",
????"}",
????"puts(lines[2]);",
????"for(idx=3;lines[idx]!=0;idx++){",
????"puts(lines[idx]);",
????"}",
????"}",
????0};
????main(){
????int?idx;
????puts(lines[0]);
????for(idx=0;lines[idx]!=0;idx++){
????printf(lines[1],34,lines[idx],34,',',10);
????}
????puts(lines[2]);
????for(idx=3;lines[idx]!=0;idx++){
????puts(lines[idx]);
????}
????}

(Self?IV?assumes?in?advance?that?it?will?be?iterating?across?an?array?of?strings?rather?than?a?single?string.?It?iterates?across?the?array?the?first?time?to?output?the?mention,?namely?the?definition?of?the?array.?The?second?iteration?provides?outputs?the?use).?
Cheat?I?

????extern?void?print_a_prog();
????main(){print_a_prog();}

Cheat?II?

????#include?
????main(){
????????int?c;
????????FILE?*f;
????????f?=?fopen(?__FILE__,?"r"?);
????????c?=?fgetc(?f?);
????????while(?c?!=?EOF?)?{
????????????putchar(?c?);
????????????c?=?fgetc(?f?);
????????}
????????fclose(?f?);
????}

Cheat?III?

????main(){
????????Find?myself?in?the?computer's?memory.
????????Output?all?the?bits?that?make?me?up.
????}



[?本帖最后由?zhuomingliang?于?2007-5-3?23:23?编辑?]


?xiaomiao 回复于:2007-05-04 10:33:35

fopen(?__FILE__,?"r"?)?调用中__FILE__是什么文件的指针?


?win_hate 回复于:2007-05-04 10:44:42

占个位置,?第?3000?帖了。

40?楼,好高啊........

[?本帖最后由?win_hate?于?2007-5-4?10:47?编辑?]







?emacsnw 回复于:2007-05-04 11:22:28

引用:原帖由?win_hate?于?2007-5-3?18:44?发表
占个位置,?第?3000?帖了。

40?楼,好高啊........?



数字不错,还有777。