基本上我在互联网上发现的问题是:“我们如何在不使用循环和条件的情况下将数字从1打印到100?”在答案中,我被卡在下面标有粗体的一些线上。任何人都可以解释我是什么? 我认为下面的总代码是用我的知识用C语言编写的。
#include <stdio.h>
#include <stdlib.h>
void foo(int);
void f1(int x)
{
printf ("%d\n", x + 1);
foo (x + 1);
}
void f2(int x) //why we have used this fumction
{}
void (*tab[])(int) = { f1, f2 }; // what is this
void foo(int x)
{
tab[!(x < 100)](x); // what is this
}
int main()
{
foo(0);
return 0;
}
答案 0 :(得分:4)
tab
是一个包含两个函数指针的数组。
由于您不允许使用if
,而是使用函数数组,并使用!(x < 100)
比较结果对其进行索引。如果这是真的,则评估为1
,因此您在tab[1]
中调用该函数,即f2()
。如果它为false,则评估为0
,因此您调用tab[0]
,即f1
。所以它实际上与:
if (x < 100) {
f1(x);
} else {
f2(x);
}
f1(x)
打印x+1
,然后递归调用foo(x+1)
。 f2(x)
没有做任何事情,所以当你到达时,递归就会结束。
答案 1 :(得分:2)
void (*tab[])(int) = { f1, f2 }; // what is this
将是一个带有int参数的函数指针数组。
tab[!(x < 100)](x); // what is this
这意味着您正在访问函数0或1,具体取决于条件的评估(false - 0或true - 1)
代码似乎是一个递归调用,它将停止在100
答案 2 :(得分:2)
这个怎么样:
#include <stdio.h>
int p(int n) {
return printf("%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n",
n+1, n+2, n+3, n+4, n+5, n+6, n+7, n+8, n+9, n+10);
}
int main() {
return p(0), p(10), p(20), p(30), p(40), p(50), p(60), p(70), p(80), p(90), 0;
}
或者这个更紧凑的版本,使用非明显的终止测试一次打印一个数字:
#include <stdio.h>
int p(int n) {
return printf("%d\n", n++) - 4 && p(n);
}
int main() {
return p(1);
}
顺便说一下,人们可以用这种方式使它更加神秘:
#include <stdio.h>
int main(int argc, char *argv[]) {
return printf("%d\n", argc++) - 4 && main(argc, argv);
}
上面的两个版本仍然使用测试,而不是if
语句。
这是一个将OP代码的想法与上述方法相结合的变体:
#include <stdio.h>
#include <stlib.h>
static void p(int n);
static void (*f[5])(int) = { p, p, p, p, exit };
static void p(int n) {
f[printf("%d\n", n + 101)](n + 1);
}
int main(int argc, char *argv[]) {
p(-100);
}
function p
取整数n
并打印n + 101
的值,然后调用其指针位于数组f
中的偏移量的函数由printf
输出的字节数,将n + 1
传递给此函数。
第一个调用获取-100
作为参数,因此打印1
和换行符。 printf
返回2,因此p
以值-99
递归调用自身。
第二个调用打印2
,并以-98
递归调用自身。
此过程一直重复,直到printf
返回4:f[4]
调用的函数为exit
,并且printf
首次打印数字100
时返回4 ,exit
获取值0
并以退出状态0
终止该程序,这意味着成功。
没有循环,没有条件,根本没有测试。
答案 3 :(得分:1)
这依赖于递归(在函数f1
中)和动态数组查找(在函数foo
中),而不是使用循环或条件。
void f2(int x) //why we have used this fumction
{}
f2
函数不执行任何操作,并在x >= 100
时调用,从而在达到最大值时终止序列。
void (*tab[])(int) = { f1, f2 }; // what is this
这是一个数组初始化。 tab
是一个指向int
参数的函数的指针数组。数组的两个元素是指向函数f1
和f2
的指针。
tab[!(x < 100)](x); // what is this
在这种情况下,这与条件相同。这会调用tab
中的第一个或第二个函数,具体取决于x < 100
是否为x < 100
。
当!(x < 100)
时,数组下标!true
等于0
,或int
转换为tab[0]
时。 f1
是数组的第一个元素,即函数f1
。 foo
函数打印并递增数字,然后再次调用x >= 100
进行递归,从而继续执行序列。
当tab[1]
,f2
被调用时,它是数组的第二个元素f2
。由于x >= 100
不执行任何操作,因此序列在Client
时结束。
答案 4 :(得分:0)
f1
负责打印并实际递增计数,并依赖于foo
的来回弹跳。
tab
是由两个函数f1
和f2
组成的数组。请注意,在foo
中,此数组由布尔表达式索引,该表达式最终转换为执行f1(count)
,直到count
大于或等于100 。 / p>
因此,
foo
,tab
,f1
和f2
只是支持和终止递归的一种方式。
执行程序时,调用堆栈看起来像这样:
main()
foo(0)
f1(0) -> print 1
foo(1)
f1(1) -> print 2
foo(2)
f1(2) -> print 3
....
foo(99)
f1(99) -> print 100
foo(100)
f2(100) -> do nothing
<---------------------------------------