In che modo questo codice genera la mappa dell'India?


169

Questo codice stampa la mappa dell'India. Come funziona?

#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
È solo offuscato C ... ci sono intere società dedicate a questo tipo di follia.
Segna il


2
#include "Stdio.h": Funziona su tutti i compilatori? Sono sorpreso di vedere che puoi ottenere un codice funzionante con errori. Forse è su Windows (maiuscole e minuscole)
alternativa

2
Per un codice più divertente come quello vedi [The International Obfuscated C Code Contest] [ ioccc.org/] .
DarkDust

12
Basta essere consapevoli del fatto che il codice è intenzionalmente difficile da capire, e non c'è molto da guadagnare dal capirlo, per quanto riguarda l'apprendimento del C da un livello principiante.
Tyler McHenry,

Risposte:


154

La stringa lunga è semplicemente una sequenza binaria convertita in ASCII. La prima foristruzione binizia con 10, e [b+++21]dopo la stringa si ottiene 31. Trattando la stringa come un array, l'offset 31 è l'inizio dei dati "reali" nella stringa (la seconda riga nell'esempio di codice fornito). Il resto del codice scorre semplicemente attraverso la sequenza di bit, convertendo gli 1 e gli 0 in! E negli spazi bianchi e stampando un carattere alla volta.

Versione meno offuscata:

#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;
}

La strana parte intelligente è nelle putchardichiarazioni. Prendi il primo putchar. ASCII 'Z'è 90 in decimale, quindi 90/9 = 10 che è un carattere di nuova riga. Nel secondo, il decimale 33 è ASCII per '!'. Attivare il bit di 33 di ordine inferiore ti dà 32, che è ASCII per uno spazio. Ciò provoca la !stampa se bè dispari e uno spazio vuoto se bè pari. Il resto del codice è semplicemente lì per guidare il "puntatore" aattraverso la stringa.


22
La stringa non è una sequenza di bit (si noti che non ci sono operazioni di spostamento dei bit nel codice). È una codifica della lunghezza dell'immagine.
interjay

89

Fondamentalmente, la stringa è una codifica della lunghezza dell'immagine: i caratteri alternati nella stringa indicano quante volte disegnare uno spazio e quante volte disegnare un punto esclamativo consecutivamente. Ecco un'analisi dei diversi elementi di questo programma:

La stringa codificata

I primi 31 caratteri di questa stringa vengono ignorati. Il resto contiene istruzioni per disegnare l'immagine. I singoli caratteri determinano il numero di spazi o punti esclamativi da disegnare consecutivamente.

Esterno per loop

Questo ciclo supera i caratteri nella stringa. Ogni iterazione aumenta il valore di buno e assegna il carattere successivo nella stringa a.

Interno per anello

Questo loop disegna singoli personaggi e una nuova riga ogni volta che raggiunge la fine della riga. Il numero di caratteri disegnati è a - 64. Il valore di cva da 10 a 90 e si reimposta su 10 quando viene raggiunta la fine della riga.

Il putchar

Questo può essere riscritto come:

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

Disegna il carattere appropriato, a seconda che bsia pari o dispari, o una nuova riga quando necessario.


1
Perché i primi 31 caratteri vengono ignorati?
Pankaj Mahato,

3
@PankajMahato perché binizia alle 10 e l'indice è (b++)+21, che inizia alle 31.
interjay
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.