看起來你正在構建一個遞歸程序。我不確定你爲什麼將邏輯分爲開始,中間和結束操作?
我建議你要麼實現此作爲頭::尾遞歸,其中每個調用添加的第一個參數上,其餘的正在運行的結果,或返回零,如果它沒有參數:
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