Wikipedia说它被称为quine,有人给出了以下代码:
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
但是,显然你必须添加
#include <stdio.h> //corrected from #include <stdlib.h>
以便printf()
可以正常工作。
从字面上看,由于上述程序没有打印#include <stdio.h>
,所以它不是解决方案(?)
我对“打印自己的源代码”的字面要求以及此类问题的任何目的感到困惑,特别是在采访时。
答案 0 :(得分:12)
这里的诀窍是大多数编译器都会编译而不需要你包含stdio.h
。
他们通常会发出警告。
答案 1 :(得分:12)
关于quine程序的面试问题的主要目的通常是看你以前是否遇到过这些问题。它们在任何其他意义上几乎都没用。
上面的代码可以适度升级,以制作符合C99标准的程序(根据GCC),如下所示:
/usr/bin/gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes \
-Wstrict-prototypes -Wold-style-definition quine.c -o quine
#include <stdio.h>
char*s="#include <stdio.h>%cchar*s=%c%s%c;%cint main(void){printf(s,10,34,s,34,10,10);}%c";
int main(void){printf(s,10,34,s,34,10,10);}
请注意,这假设代码集中"
是代码点34而换行是代码点10.此版本在末尾打印出换行符,与原始版本不同。它还包含所需的#include <stdio.h>
,并且这些行几乎足够短,无需水平滚动条即可在SO上工作。只需付出更多的努力,它无疑可以做得足够短。
quine计划的酸测试是:
./quine | diff quine.c -
如果源代码和输出之间存在差异,则会报告。
回到我年轻时代,我制作了一个双语的“自我复制”节目。它是shell脚本和Informix-4GL(I4GL)源代码的组合。使这成为可能的一个属性是I4GL将{ ... }
视为注释,但shell将其视为I / O重定向的一个单元。 I4GL也有#...EOL
条评论,shell也是如此。文件顶部的shell脚本包含数据和操作,以不支持指针的语言重新生成复杂的验证操作序列。我们生成的I4GL函数控制的数据以及每个函数的生成方式。然后编译I4GL代码以每周验证从外部数据源导入的数据。
如果您将文件(称为file0.4gl
)作为shell脚本运行并捕获输出(调用file1.4gl
),然后将file1.4gl
作为shell脚本运行并捕获file2.4gl
中的输出,两个文件file1.4gl
和file2.4gl
将是相同的。但是,file0.4gl
可能会丢失所有生成的I4GL代码,只要文件顶部的shell脚本“注释”没有损坏,它就会重新生成一个自我复制的文件。
答案 2 :(得分:5)
您也可以手动定义printf的原型。
const char *a="const char *a=%c%s%c;int printf(const char*,...);int main(){printf(a,34,a,34);}";int printf(const char*,...);int main(){printf(a,34,a,34);}
答案 3 :(得分:4)
quine在与编程语言和一般执行相关的定点语义方面有一些深度根源。它们与理论计算机科学有一定的重要性,但在实践中它们没有任何目的。
他们是一种挑战或诡计。
字面要求只是你说的,字面意思:你有一个程序,它的执行产生自己作为输出。没有更多或更少,这就是它被认为是一个固定点的原因:通过语言语义执行程序本身就是它的输出。
因此,如果您将计算表达为函数,那么您将拥有
f(program, environment) = program
在quine的情况下,环境被认为是空的(你之前没有预先计算过任何输入)
答案 4 :(得分:1)
这是一个将被C ++编译器接受的版本:
#include<stdio.h>
const char*s="#include<stdio.h>%cconst char*s=%c%s%c;int main(int,char**){printf(s,10,34,s,34);return 0;}";int main(int,char**){printf(s,10,34,s,34);return 0;}
试运行:
$ /usr/bin/g++ -o quine quine.cpp
$ ./quine | diff quine.cpp - && echo 'it is a quine' || echo 'it is not a quine'
it is a quine
字符串s
主要包含来源的副本,但s
本身的内容除外 - 而不是%c%s%c
。
诀窍在于,在printf
调用中,字符串s
用作格式和作为%s
的替代。这会导致printf
将它也放入s
的定义中(在输出文本上,即)
其他10
和34
对应于换行符和"
字符串分隔符。它们由printf
作为%c
的替换插入,因为它们在格式字符串中需要额外的\
,这会导致格式和替换字符串不同,所以这个伎俩不再适用了。
答案 5 :(得分:0)
[http://www.nyx.net/~gthompso/quine.htm#links] [https://pastebin.com/2UkGbRPF#links]
//自我复制基本代码
#include <iostream> //1 line
#include <string> //2 line
using namespace std; //3 line
//4 line
int main(int argc, char* argv[]) //5th line
{
char q = 34; //7th line
string l[] = { //8th line ---- code will pause here and will resume later in 3rd for loop
" ",
"#include <iostream> //1 line ",
"#include <string> //2 line ",
"using namespace std; //3 line ",
" //4 line ",
"int main(int argc, char* argv[]) //5th line ",
"{",
" char q = 34; //7th line ",
" string l[] = { //8th line ",
" }; //9th resume printing end part of code ", //3rd loop starts printing from here
" for(int i = 0; i < 9; i++) //10th first half code ",
" cout << l[i] << endl; //11th line",
" for(int i = 0; i < 18; i++) //12th whole code ",
" cout << l[0] + q + l[i] + q + ',' << endl; 13th line",
" for(int i = 9; i < 18; i++) //14th last part of code",
" cout << l[i] << endl; //15th line",
" return 0; //16th line",
"} //17th line",
}; //9th resume printing end part of code
for(int i = 0; i < 9; i++) //10th first half code
cout << l[i] << endl; //11th line
for(int i = 0; i < 18; i++) //12th whole code
cout << l[0] + q + l[i] + q + ',' << endl; 13th line
for(int i = 9; i < 18; i++) //14th last part of code
cout << l[i] << endl; //15th line
return 0; //16th line
} //17th line
答案 6 :(得分:-2)
main(a){printf(a="main(a){printf(a=%c%s%c,34,a,34);}",34,a,34);}
答案 7 :(得分:-6)
#include<stdio.h>
int main(void)
{
char a[20],ch;
FILE *fp;
// __FILE__ Macro will store File Name to the array a[20]
sprintf(a,__FILE__);
// Opening the file in Read mode
fp=fopen(a,"r");
// Taking character by character from file,
// you can also use fgets() to take line by line
while((ch=fgetc(fp))!=EOF)
printf("%c",ch);
return 0;
}