【问题标题】:How does this code generate the map of India?此代码如何生成印度地图?
【发布时间】:2011-04-01 19:01:23
【问题描述】:

此代码打印印度地图。它是如何工作的?

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

【问题讨论】:

  • 它只是被混淆了 C......整个社会都致力于这种疯狂。
  • #include "Stdio.h" :这适用于所有编译器吗?我很惊讶地看到你可以得到带有错误大写的工作代码。也许它在 Windows 上(不区分大小写的 FS)
  • 更多有趣的代码见[国际混淆C代码竞赛][ioccc.org/].
  • 请注意,代码故意难以理解,而且从初学者的水平学习C而言,弄清楚它并没有太多收获.

标签: c obfuscation


【解决方案1】:

长字符串只是一个转换为 ASCII 的二进制序列。第一个for 语句使b 从10 开始,而字符串后面的[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;
}

strange 的巧妙之处在于putchar 语句。取第一个putchar。 ASCII 'Z' 是十进制的 90,所以 90 / 9 = 10 是换行符。在第二个中,十进制 33 是​​'!' 的 ASCII。切换 33 的低位会得到 32,这是空格的 ASCII。如果b 是奇数,这将导致打印!,如果b 是偶数,则打印一个空格。剩下的代码只是用来让“指针”a 穿过字符串。

【讨论】:

  • 字符串不是位序列(注意代码中没有位移操作)。它是图像的行程编码。
【解决方案2】:

基本上,字符串是图像的run-length encoding:字符串中的交替字符表示绘制空格的次数,以及连续绘制感叹号的次数。下面是对这个程序的不同元素的分析:

编码字符串

忽略此字符串的前 31 个字符。其余部分包含绘制图像的说明。各个字符决定了要连续绘制多少个空格或感叹号。

外部for循环

这个循环遍历字符串中的字符。每次迭代都会将b 的值加一,并将字符串中的下一个字符分配给a

内部 for 循环

此循环绘制单个字符,并在到达行尾时换行。抽取的字符数为a - 64c 的值从 10 变为 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 是偶数还是奇数,或者在需要时换行来绘制适当的字符。

【讨论】:

  • 为什么忽略前 31 个字符?
  • @PankajMahato 因为b 从 10 开始,索引是 (b++)+21,从 31 开始。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 2017-12-01
相关资源
最近更新 更多