Nap*_*don 1 c functional-programming sicp
在阅读了计算机程序的结构和解释(SICP)之后,我决定找到一种方法来使用C实现其中一些函数式编程技术.我试着编写一个程序,它创建了一对,其第一个参数是函数的名称,第二个是arg是任何带有一个arg并返回一个arg的函数.使用下面的实现我期望看到如下输出:
fact(7) = 5040
fib(7) = 13
Run Code Online (Sandbox Code Playgroud)
但相反,我得到了
fact(7) = 5040
fib(7) = 0
Run Code Online (Sandbox Code Playgroud)
以及警告
$ cc map.c
map.c: In function ‘main’:
map.c:41:17: warning: assignment from incompatible pointer type [enabled by default]
maps[0].f_ptr = &fact;
^
map.c:43:17: warning: assignment from incompatible pointer type [enabled by default]
maps[1].f_ptr = &fib;
^
map.c:47:7: warning: passing argument 1 of ‘maps[i].f_ptr’ makes pointer from integer without a cast [enabled by default]
ans = (int) maps[i].f_ptr((int) num);
^
map.c:47:7: note: expected ‘void *’ but argument is of type ‘int’
map.c:47:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
ans = (int) maps[i].f_ptr((int) num);
^
map.c:52:7: warning: passing argument 1 of ‘maps[i].f_ptr’ makes pointer from integer without a cast [enabled by default]
ans2 = (int) maps[i].f_ptr((int) num);
^
map.c:52:7: note: expected ‘void *’ but argument is of type ‘int’
map.c:52:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
ans2 = (int) maps[i].f_ptr((int) num);
Run Code Online (Sandbox Code Playgroud)
在编译期间.看看代码我没有看到问题,但是我在很长一段时间内都没有使用过C语言.有没有更好的方法来实现这样的结构,为什么fib(7)打印0而不是13?
这是我的代码:
struct Map
{
char* name;
void* (*f_ptr)(void*);
};
int fact(int a) {
if (a == 0)
return 0;
if (a == 1)
return 1;
return a * fact (a-1);
}
int fib(int a) {
if (a == 0)
return 0;
if (a == 1)
return 1;
return fib(a-1) + fib(a-2);
}
int findFunc (char* str, struct Map map)
{
if (map.name == str)
return 1;
return 0;
}
int main()
{
int i = 0;
int ans = 0;
int ans2 = 0;
int num = 7;
struct Map maps[2];
maps[0].name = "fact";
maps[0].f_ptr = &fact;
maps[1].name = "fib";
maps[1].f_ptr = &fib;
for (i; i < (sizeof(maps)/sizeof(maps[0])); i++) {
if (findFunc("fact", maps[i]))
ans = (int) maps[i].f_ptr((int) num);
}
for (i; i < (sizeof(maps)/sizeof(maps[0])); i++) {
if (findFunc("fib", maps[i]))
ans2 = (int) maps[i].f_ptr((int) num);
}
printf("fact(%d) = %d\n", num, ans);
printf("fib(%d) = %d", num, ans2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不是你在C中进行字符串比较的方式.
if (map.name == str)
Run Code Online (Sandbox Code Playgroud)
这是你在C中进行字符串比较的方法.
if (0 == strcmp(map.name, str))
Run Code Online (Sandbox Code Playgroud)
因为在C字符串是仅用于指向字符,map.name == str检查是否map.name与str相同的指针(指向的存储器中的相同块),它们指向什么不是否是相同的.
您的代码可能正在报告,fib(7) = 0因为它无法找到fib.一个可能的罪魁祸首是我提到的字符串比较问题.但是,你的for循环语法也很奇怪:
for (i; i < (sizeof(maps)/sizeof(maps[0])); i++) {
Run Code Online (Sandbox Code Playgroud)
你没有设置i任何东西,所以这意味着,"从我碰巧的任何地方开始,做以下......"
要遍历所有地图,请使用以下命令:
for (i = 0; i < (sizeof(maps)/sizeof(maps[0])); i++) {
Run Code Online (Sandbox Code Playgroud)
正如@alk在评论中所说,你得到所有这些警告的原因是你已经声明了一个函数类型void* (*f_ptr)(void*);,即使你的函数是int (*)(int).如果你想继续使用void*以允许不同的类型,并且你对你的类型足够小心以使其工作,那么你可以添加强制转换以使警告静音.
maps[0].f_ptr = (void *(*)(void*)) &fact;
ans2 = (int) maps[i].f_ptr((void*) num);
Run Code Online (Sandbox Code Playgroud)
等等.
映射函数到名称的"真实"实现将使用哈希表,而不是线性搜索匹配的名称.在C中实现哈希表会增加复杂性,并且可能不值得进行此练习.