看起来你正在构建一个递归程序。我不确定你为什么将逻辑分为开始,中间和结束操作?
我建议你要么实现此作为头::尾递归,其中每个调用添加的第一个参数上,其余的正在运行的结果,或返回零,如果它没有参数:
Program -> 0
Program head,... -> head + program ...
或分而治之,其中每个调用或者返回它的一个参数,因为没有零,或叉两个子调用,每次半的其余参数:
Program -> 0
Program x -> x
Program (N args) -> Program (N+1/2 args) + Program (remaining args)
,不需要复杂的内部数据结构,只是一些光阵列处理:
我应该指出,通过退出代码传递值是一个坏主意,因为退出代码有一个非常有限的值(256)可用于此用途,并且如果您的程序由于某种原因失败,它可能会返回一个令人惊讶的价值。
下面是不使用退出代码的perl版本:
#!/usr/bin/perl
[email protected]&&(shift(@ARGV)+‘$0 @ARGV‘)||0
虽然这是perl,它不是每个人都可以阅读,和Perl是做了很多幕后工作,对于我们来说,演示了如何使用fork和exec实现递归head :: tail sum函数的方式。
下面是一个使用退出代码C版本:
int forkexec(char**oldargv,char**newargv,char**endargv)
{
if(!fork())
execve(newargv[0]=oldargv[0],newargv,endargv[0]=0);
int b;
wait(&b);
return b>>8;
}
main(int c, char** a)
{
int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");
exit(!(c-1)?0 // empty head returns 0
:atoi(a[1])+ // convert the head into a number
forkexec(a,a+1,a+c)); // re-invoke on the remaining arguments
}
请注意,此代码是不是安全,它使用无证的功能,如main
参数数组argv
(a
)被NULL终止。然而,它的工作原理,并演示递归使用fork,exec和退出代码在c中。与调试的printf注释掉运行:
$ gcc sum.c
$ ./a.out 1 2 3 4 5; echo RESULT $?
./a.out 1 2 3 4 5
./a.out 2 3 4 5
./a.out 3 4 5
./a.out 4 5
./a.out 5
./a.out
RESULT 15
正如你所看到的,我没有使用任何树木或名单 - 我只是每次都重新调用程序,沿着一个运动参数列表指针。
这里的分而治之的版本:
int forkexec(char**oldargv,char**newargv,char**endargv)
{
if(!fork())
execve(newargv[0]=oldargv[0],newargv,endargv[0]=0);
int b;
wait(&b);
return b>>8;
}
main(int c, char** a)
{
//int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");
exit(!(c-1)?0: // empty leaf is 0
!(c-2)?atoi(a[1]): // leaf returns value
forkexec(a,a,a+1+c/2)+ // Sum left half of children
forkexec(a,a+c/2,a+c)); // Sum right half of children
}
我想推荐你不使用我的代码;这是丑陋,不安全,故意压缩形成一个小例子在这里张贴。您应该使用功能分解,错误检查和注释来重新编写代码,以及将argv的内容克隆到新的,足够大和空终止的数组中。另外execve
的第三个参数在我的例子中是误导性的。
取消对调试的printf:
int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");
我们得到:
$ ./a.out 1 2 3 4 5 6 7 8; echo RESULT $?
./a.out 1 2 3 4 5 6 7 8
./a.out 1 2 3 4
./a.out 1 2
./a.out 1
./a.out 2
./a.out 3 4
./a.out 3
./a.out 4
./a.out 5 6 7 8
./a.out 5 6
./a.out 5
./a.out 6
./a.out 7 8
./a.out 7
./a.out 8
RESULT 36
,清楚地显示问题被分裂成越来越小的一半。
你应该考虑发布你的代码。 – 2010-02-03 08:56:06
我发布了迄今为止我所拥有的内容。 – foobiefoob 2010-02-03 09:01:49
什么能阻止你迭代argv数组?家庭作业标签也许? – 2010-02-03 13:06:19