2015-08-28 7 views
8

Im więcej próbuję zrozumieć tę zakłopotaną zagadkę, tym bardziej chcę się poddać.Program, którego kod źródłowy jest dokładnie taki sam jak jego wyjście

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

Jak dzieje się na tym kodzie źródłowym jednej linii, aby wygenerować dokładnie taką samą moc, gdy program wykonuje i jest tam jakąkolwiek wspólną koncepcję dla tego typu programów?

+2

Czy wiesz, co robi 'printf'? Czy potrafisz ustalić, co 'printf (" char * s =% c% s% c; main() {printf (s, 34, s, 34);} ", 34," char * s =% c% s% c; main() {printf (s, 34, s, 34);} ", 34)' drukuje, biorąc pod uwagę, że 34 to kod ASCII dla '' ' – immibis

+0

Teraz to jest oficjalne - strasznie brakuje mi umiejętności analitycznych – Malina

+0

Wiem co to jest 34 i co printf robi .. to tylko semantycznie myli mnie – Malina

Odpowiedz

11

Nazywa się to Quine.

Więc zobaczmy co main() robi:

printf(s,34,s,34); 

34 to kod ASCII dla znaku " (cudzysłów), więc to jest takie samo jak:

printf(s, '"', s, '"'); 

pierwszy argument printf(3) to ciąg formatu. Ciąg przekazywane jest:

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

Więc printf(3) wyjście będzie dokładnie to, ale należy zwrócić uwagę na %c, %s i %c specyfikatory formatu, które instruują printf(3) wydrukować znak, po którym następuje ciąg znaków, a następnie przez innego bohatera, który miejsce, które są odpowiednio 2., 3. i 4. argumentem.

Znaki, jak widzieliśmy, są zarówno ", jak i ciąg znaków ponownie s (ten sam ciąg). Więc wyjście programu jest:

char *s = "X"; main(){printf(s,34,s,34);} 

Gdzie X jest ciąg s w programie. Więc otrzymujemy to jako wyjście:

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

Co, co ciekawe, jest źródłem samego programu.

+0

Nieuchronnie wyjaśniający-zaciemniony, więc myślę, że nie dawanie tego uczniom jest wspaniałym pomysłem.Dziękuję :) – Malina

+1

@Malina Rzeczywiście, to może być podstępne dla niewytrenowanego ucznia, ale programy samoreplikujące są ważną częścią teorii obliczalności. Uczniowie powinni przynajmniej nauczyć się tej koncepcji. –

+0

Zaktualizowałem też pytanie, aby było ono bardziej wartościowe dla innych czytających odpowiedź równolegle z dodaniem. – Malina

3

wziąć ten ciąg od pierwszego parametru printf:

'char *s = %c%s%c; main(){printf(s,34,s,34);}' 

i zrobić podstawienie gdzie

%c = 34 = '"' //(same for both %c) 
%s = 'char *s = %c%s%c; main(){printf(s,34,s,34);}' 

printf zrobi podstawienie tylko raz (nie rekurencyjny), więc wynik jest:

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

Aby zrozumieć kod, najpierw uprościć i sformatować:

char *s = "some format string"; 
main() { 
    printf(s,34,s,34); 
} 

więc używa s jako ciąg formatowania wydrukować trzy podmioty: 34, ciąg s sama i 34. W tym przypadku ważnym elementem łańcucha formatowania s jest:

char *s = "... %c%s%c ..." 

które oznaczają dwa 34 s stają cudzysłowia (") oraz formatowania stringi s jest właśnie drukowane jako zwykłego łańcucha.Teraz powinieneś zobaczyć, że reszta ciągu formatowania s jest po prostu kopią całego programu.

Powiązane problemy