14

ウィキペディアはそれがクワインと呼ばれ、誰かが以下のコードを与えたと言っています:

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>、それは解決策ではありません(?)

「独自のソースコードを印刷する」という文字通りの要件と、特にインタビューでのこの種の問題の目的について、私は混乱しています。

4

7 に答える 7

17

通常、クワインプログラムに関するインタビューの質問の主な目的は、以前にそれらに出くわしたことがあるかどうかを確認することです. それらは、他の意味ではほとんど役に立ちません。

上記のコードは、次のように (GCC に従って) C99 準拠のプログラムを作成するために適度にアップグレードできます。

コンパイル

/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 | diff quine.c -

ソースコードと出力に違いがある場合は、報告されます。


「クインのような」テクニックのほぼ有用なアプリケーション

若い頃、バイリンガルの「自己再生」プログラムを作成しました。これは、シェル スクリプトと Informix-4GL (I4GL) ソース コードの組み合わせでした。これを可能にした 1 つの特性は、I4GL が{ ... }コメントとして扱うことですが、シェルはそれを I/O リダイレクションの単位として扱います。シェルと同様に、 I4GL にも#...EOLコメントがあります。ファイルの先頭にあるシェル スクリプトには、ポインターをサポートしない言語で検証操作の複雑なシーケンスを再生成するためのデータと操作が含まれていました。このデータは、どの I4GL 関数を生成したか、および各関数がどのように生成されたかを制御します。次に、I4GL コードをコンパイルして、外部データ ソースからインポートされたデータを毎週検証しました。

ファイルfile0.4glをシェル スクリプトとして実行し (それを と呼びます)、出力をキャプチャし (それを と呼びますfile1.4gl)、次にfile1.4glシェル スクリプトとして実行し、出力を でキャプチャしたfile2.4gl場合、2 つのファイルfile1.4glfile2.4glは同一になります。ただし、file0.4gl生成された I4GL コードがすべて欠落している可能性があり、ファイルの先頭にあるシェル スクリプトの「コメント」が破損していない限り、自己複製ファイルが再生成されます。

于 2012-04-20T04:00:03.313 に答える
15

ここでの秘訣は、ほとんどのコンパイラが .xml を含めなくてもコンパイルできることですstdio.h

彼らは通常、警告を投げるだけです。

于 2012-04-20T00:27:18.063 に答える
6

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);}
于 2015-01-15T14:14:21.357 に答える
5

クワインは、プログラミング言語および一般的な実行に関連する固定小数点セマンティクスにいくつかの深さのルーツがあります。それらは、理論的なコンピューター サイエンスに関連する重要性を持っていますが、実際には目的がありません。

それらは一種の挑戦またはトリックです。

文字通りの要件は、あなたが言ったとおりです。文字通り、プログラムがあり、その実行はそれ自体を出力として生成します。多かれ少なかれ、それが固定点と見なされる理由です。言語セマンティクスによるプログラムの実行は、その出力としてそれ自体を持っています。

したがって、計算を関数として表現すると、それが得られます

f(program, environment) = program

クワインの場合、環境は空と見なされます (事前に計算された入力として何もありません)。

于 2012-04-20T00:30:14.350 に答える
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

追加の1034s は、改行と"文字列区切り文字に対応します。printfこれらは s の置換として挿入されます。これは、format-string に%c追加が必要\になり、format-string と replacement-string が異なるため、トリックが機能しなくなるためです。

于 2015-01-12T12:07:08.913 に答える