“作弊” ;-) 但很短的解决方案是
#include <cstdio>
int main() {
puts("I\nIN\nIND\nINDI\nINDIA\nINDIA\nINDI\nIND\nIN\nI\n");
}
基于TonyK的绝妙想法的另一个解决方案(适用于 C 和 C++):
#include <stdio.h>
int main() {
for (int i = 1; i < 11; ++i)
printf("%.*s\n", i < 6 ? i : 11 - i, "INDIA") ;
}
更新:(在 TonyK 发表评论后):
如果你想要空格,然后printf
用这个替换上面的
printf("%.*s\n", 2*(i < 6 ? i : 11 - i), "I N D I A ");
更新:没有循环的解决方案:
#include <stdio.h>
int main(int i, char**) {
return printf("%.*s\n", i < 6 ? i : 11 - i, "INDIA") - 1 && main(i + 1, 0);
}
以下为初学者的利益的详细解释。
最重要的一点是,这是一个“学术”练习。代码晦涩难懂,应该避免编写这样的严肃代码。
该标准没有为 function 修复特定的签名main
。它只是说它必须返回一个int
并且编译器必须接受两种特定的形式:
int main();
int main(int argc, char** argv);
我正在使用第二个。更流行的形式int main(int argc, char* argv[])
等价于(2)。实际上,通常,用作函数参数的 T 数组被隐式转换为指向 T的指针。在这个例子中,是一个指向 charchar* argv[]
的指针数组,它变成了指向 char的指针。上面的程序虽然没有使用第二个参数(它要么被忽略,要么被赋予 NULL,即 0 值)。
程序不是循环,而是main
递归调用。实际上,这是非法的,但主要编译器对此视而不见(如果您要求它使用选项 -Wpedantic 迂腐,最多 GCC 会发出警告)。当从没有参数的命令行调用程序时,操作系统调用main
传递1
(即1
+ 参数的数量)和指向 char 的指针的指针,如前所述,该程序将忽略该指针。因此,i = 1
在第一次通话时。
随后,每次都main
可能称自己为递增。i
总而言之,main
依次调用i
being 1
, 2
, 3
, 4
, ...
很容易看出,对于 的这个值序列i
,表达式的计算i < 6 ? i : 11 - i
结果为1
, 2
, 3
, 4
, 5
, 5
, 4
, 3
, 2
, 1
, 0
, ...保存一行;-) 这些数字是每次应显示的“印度”字符数5.5 - abs(5.5 - i)
。#include <cmath>
调用printf("%.s\n", j, "INDIA")
,其中j = i < 6 ? i : 11 - i
,显示j
“印度”的第一个字符,后跟一个新行,并返回有效打印的字符数(包括新行),即j + 1
。带走1
收益j
。
a && b
我们现在回忆一下, 对于整数a
和的语义的一个重要点b
。如果a == 0
,b
则不计算。否则,b
被评估。对我们来说,a = printf("%.*s\n", j, "INDIA") - 1
(即a = j
)和b = main(i + 1, 0)
。
现在,让我们把这些部分放在一起。
1.最初,i = 1
和j = 1
。调用printf
输出 "I\n" 并返回2
. 带走1
,给a = 1 != 0
。因此,b = main(2, 0)
被评估(main(2, 0)
即被调用)。
2.好吧,对于第二次调用main
,我们有i = 2
,j = 2
,printf
显示“IN\n”,a = 2 != 0
并被b = main(3, 0)
评估。
重复这个论点,每次调用main
我们都有:
3. i = 3
, j = 3
, "IND\n" 被打印,a = 3 != 0
并被main(4, 0)
调用。
4. i = 4
, j = 4
, "INDI\n" 被打印,a = 4 != 0
并被main(5, 0)
调用。
5. i = 5
, j = 5
, "INDIA\n" 被打印,a = 5 != 0
并被main(6, 0)
调用。
6. i = 6
, j = 5
, "INDIA\n" 被打印,a = 5 != 0
并被main(7, 0)
调用。
7. i = 7
, j = 4
, "INDI\n" 被打印,a = 4 != 0
并被main(8, 0)
调用。
...
10. i = 10
, j = 1
, "I\n" 被打印,a = 1 != 0
并被main(11, 0)
调用。
11. i = 11
, j = 0
, "\n" 被打印出来, a = 0
. 现在main(12, 0)
不执行,main
返回
请注意,main
在第 1 步中调用第 2 步,main
在第 2main
步中调用3
,...main
在第 11 步中调用。因此,main
在第 11 步中返回到main
第 10 步,main
在第 9 步中返回,...,在第 9 步中main
返回步骤1。最后,main
在步骤1中返回操作系统。
如果您对更加模糊的代码感兴趣,请查看IOCCC的现在和过去的获奖者。享受!