이 코드는 어떻게 인도의지도를 생성합니까?


169

이 코드는 인도의지도를 인쇄합니다. 어떻게 작동합니까?

#include <stdio.h>
main()
{
    int a,b,c;
    int count = 1;
    for (b=c=10;a="- FIGURE?, UMKC,XYZHello Folks,\
    TFy!QJu ROo TNn(ROo)SLq SLq ULo+\
    UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^\
    NBELPeHBFHT}TnALVlBLOFAkHFOuFETp\
    HCStHAUFAgcEAelclcn^r^r\\tZvYxXy\
    T|S~Pn SPm SOn TNn ULo0ULo#ULo-W\
    Hq!WFs XDt!" [b+++21]; )
    for(; a-- > 64 ; )
    putchar ( ++c=='Z' ? c = c/ 9:33^b&1);
    return 0;
}

63
그것은 C를 난독 화했습니다 ...이 종류의 광기에 전념 한 사회가 있습니다.
Mark


2
#include "Stdio.h": 모든 컴파일러에서 작동합니까? 잘못된 캡으로 작업 코드를 얻을 수 있다는 사실에 놀랐습니다. 어쩌면 Windows에서 (대소 문자를 구분하지 않는 FS)
대안

2
이와 같은 재미있는 코드는 [International Obfuscated C Code Contest] [ ioccc.org/] 를 참조하십시오 .
DarkDust

12
코드가 의도적 으로 이해하기 어렵고 초보자 수준에서 C를 배우는 한 코드 를 이해하면 얻을 수있는 것이 많지 않습니다.
Tyler McHenry

답변:


154

긴 문자열은 ASCII로 변환 된 이진 시퀀스입니다. 첫 번째 for명령문은 b10에서 시작하고 그 [b+++21]이후 문자열은 31입니다. 문자열을 배열로 취급하면 오프셋 31은 문자열에서 "실제"데이터의 시작입니다 (제공 한 코드 샘플의 두 번째 줄). 나머지 코드는 단순히 비트 시퀀스를 반복하여 1과 0을!와 공백으로 변환하고 한 번에 한 문자 씩 인쇄합니다.

덜 난독 화 된 버전 :

#include "stdio.h"
int main (void) {
    int a=10, b=0, c=10;
    char* bits ="TFy!QJu ROo TNn(ROo)SLq SLq ULo+UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^NBELPeHBFHT}TnALVlBLOFAkHFOuFETpHCStHAUFAgcEAelclcn^r^r\\tZvYxXyT|S~Pn SPm SOn TNn ULo0ULo#ULo-WHq!WFs XDt!";
    a = bits[b];
    while (a != 0) {
        a = bits[b];
        b++;
        while (a > 64) {
            a--;
            if (++c == 'Z') {
                c /= 9;
                putchar(c);
            } else {
                putchar(33 ^ (b & 0x01));
            }
        }
    }
    return 0;
}

이상한 영리한 부분은에 putchar문. 첫 번째를 가져 가라 putchar. ASCII 'Z'는 10 진수 90이므로 개행 문자 인 90/9 = 10입니다. 두 번째에서 10 진수 33은의 ASCII입니다 '!'. 33의 하위 비트를 토글하면 32는 공간의 ASCII입니다. 이 원인은 !경우 인쇄 할 b홀수이며, 경우 빈 공간을 인쇄 할 수 b도있다. 코드의 나머지 부분은 단순히 a문자열을 통해 "포인터"를 걷는 것 입니다.


22
문자열은 비트 시퀀스가 ​​아닙니다 (코드에 비트 시프트 연산이 없음). 이미지의 길이 인코딩입니다.
interjay

89

기본적으로 문자열은 이미지 의 런타임 길이 인코딩 입니다. 문자열의 대체 문자는 공백을 그리는 횟수와 느낌표를 연속해서 그리는 횟수를 나타냅니다. 다음은이 프로그램의 다양한 요소에 대한 분석입니다.

인코딩 된 문자열

이 문자열의 처음 31자는 무시됩니다. 나머지는 이미지를 그리는 지침을 포함합니다. 개별 문자는 연속적으로 그릴 공백 또는 느낌표의 수를 결정합니다.

외부 for 루프

이 루프는 문자열의 문자를 넘어갑니다. 반복 할 때마다 값이 b1 씩 증가 하고 문자열의 다음 문자를에 할당합니다 a.

내부 for 루프

이 루프는 줄 끝에 도달 할 때마다 개별 문자와 줄 바꿈을 그립니다. 그려진 문자 수는 a - 64입니다. 값은 c10에서 90으로 바뀌고 줄 끝에 도달하면 10으로 다시 설정됩니다.

그만큼 putchar

이것은 다음과 같이 다시 작성할 수 있습니다.

++c;
if (c==90) {       //'Z' == 90
    c = 10;        //Note: 10 == '\n'
    putchar('\n');
}
else {
    if (b % 2 == 0)
        putchar('!');
    else
        putchar(' ');
}

b짝수인지 홀수 인지 또는 필요할 때 줄 바꿈 에 따라 적절한 문자를 그립니다 .


1
처음 31자가 무시되는 이유는 무엇입니까?
Pankaj Mahato

3
@PankajMahato b는 10시에 시작하고 인덱스는 (b++)+2131에 시작 하기 때문에 .
interjay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.