C/C++;将自己的源代码打印为输出的程序

C/C++;将自己的源代码打印为输出的程序,c,quine,C,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> #include//corrected from#include 这样printf()就可以工作了 从字面上看,由于上述程序没有打印#inclu

说它叫奎因,有人给了下面的密码:

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>
#include//corrected from#include
这样
printf()
就可以工作了

从字面上看,由于上述程序没有打印
#include
,因此它不是解决方案(?)


我对“打印自己的源代码”的字面要求以及这类问题的任何目的感到困惑,特别是在采访中。

这里的技巧是大多数编译器将编译而不需要包含
stdio.h


他们通常只会发出警告。

奎因在与编程语言和一般执行相关的定点语义中有一定的深度根源。它们在理论计算机科学方面具有一定的重要性,但在实践中却毫无意义

它们是一种挑战或技巧

字面需求就是你所说的,字面:你有一个程序,它的执行产生自己作为输出。这就是为什么它被认为是一个固定点:通过语言语义执行程序本身就是它的输出

如果你把计算表示成一个函数,你就会得到

f(program, environment) = program

对于quine,环境被认为是空的(你没有任何输入,之前也没有预先计算过)

关于quine程序的采访问题的主要目的通常是看看你以前是否遇到过它们。它们在任何其他意义上几乎都没有用处

上述代码可以适度升级,以生成符合C99的程序(根据GCC),如下所示:

汇编 代码 如果源代码和输出之间存在差异,则会报告


“奎因样”技术的一个几乎有用的应用 早在我年轻的时候,我就制作了一个双语“自我复制”节目。它是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
将是相同的。但是,<>代码>文件0.4GL 可能会丢失所有生成的I4GL代码,只要文件顶部的shell脚本“注释”没有被损坏,它就可以重新生成一个自复制文件。

< P>这是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;}
字符串
s
主要包含源代码的副本,除了
s
本身的内容之外,它在那里有
%c%s%c

诀窍在于,在
printf
调用中,字符串
s
既用作格式,也用作
%s
的替换。这导致
printf
也将其放入
s
的定义中(即在输出文本上)


附加的
10
34
s对应于换行符和
字符串分隔符。它们由
printf
插入,作为
%c
的替代品,因为它们需要在格式字符串中增加一个
\
,这将导致格式字符串和替代字符串不同,因此该技巧不再有效。

您也可以手动定义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);}
Quine(c++中的基本自释放代码)`//自复制基本代码 [ [

//自复制基本代码

#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
#包括//1行
#包括//2行
使用命名空间std;//3行
//4线
int main(int argc,char*argv[])//第五行
{
char q=34;//第7行
字符串l[]={//8行----代码将在此处暂停,稍后将在第3个for循环中继续
" ",
“#包括//1行”,
“#包括//2行”,
“使用命名空间std;//3行”,
“//4行”,
“int main(int argc,char*argv[])//第五行”,
"{",
“char q=34;//第7行”,
“字符串l[]={//8行”,
“};//第9次继续打印代码的结束部分”//第3次循环从此处开始打印
“对于(int i=0;i<9;i++)//第10个前半段代码”,

“您是否需要
#包含
printf()的
<代码> >不是代码> >代码>代码太老,你不清楚你真的需要它。但是在现代C编译器下升级代码是很好的。在输出结束时没有新行的问题。这个代码当然不是C++代码。好的catch。它是。C++编译器是正确的。不编译上面的代码,只有C编译器才编译。也感谢您对quine实用价值的解释。感谢您更新C99版本。以及“有用的应用程序”"非常感谢!可能值得扩展此答案,以解释如何根据标准推断隐式定义函数的规则。您可能应该提到,数值10和34取决于主机字符编码,对于linefeed和双引号具有dif的平台,需要更改F
#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
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);}
main(a){printf(a="main(a){printf(a=%c%s%c,34,a,34);}",34,a,34);}
#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