Fork() 无法计算命令行参数的最后几位

发布于 2024-08-19 18:12:19 字数 1135 浏览 1 评论 0原文

我正在尝试计算从终端输入的一行命令参数的总和。到目前为止,我已经达到了它将打印出所有内容直到最后几位数字的程度。我必须利用 fork() 来完成我的配套程序的所有计算。主程序无法对最终总和进行任何计算。我尝试通过创建一个新的动态数组来提取最后几位数字,但如果碰巧有 100 个或更多个位数字,则这是无用的。

后,它将从终端打印出来

执行 ./coordinator 3 4 3 2 1 4 5 4 3 2 4 3 2 **** 开始操作 ****

进程 ID: 5642 计算:3 和 4 之和为 7

进程 ID:5643 计算:3 和 2 之和为 5

进程 ID:5644 计算:1 和 4 之和为 5

进程 ID:5645 计算:5 和 4 之和为 9

进程 ID:5646 计算:3 和 2 之和为 5

进程 ID:5647 计算:4 和 3 之和为 7

进程 ID:5648 计算:2 和 0 之和为 2

**** 中间操作 ****

ProcessID 5649: 计算:7 和 5 之和为 12

ProcessID 5650: 计算:5 和 9 之和为 14

ProcessID 5651: 计算:5 和 7 之和为 12

ProcessID 5652: 计算:2 和 0 之和为 2

**** 结束操作 ****

ProcessID 5654: 计算:12 和 14 之和为 26

ProcessID 5656: 计算:12 和 2 之和为 14

return_array[0]: 12
return_array[1]: 14
返回数组[2]:12
return_array[3]: 2
return_array[4]: 26
return_array[5]: 14

如果有一行奇数,事情就会变得复杂,因此您必须在计算的任何点添加零。所以你可以再次使集合均匀,从而允许计算继续。

例如这一行: ProcessID 5652: Calculation: Sum of 2 and 0 is 2

如果我让数字更复杂(一开始的数字更多),“结束操作”之后的部分就会变得更大,从而使其更难拉取最后几项总和最终得到一笔总和。我无法提取这些数字。

I' m trying to calculate the total sum of a line of command arguments entered in from the terminal. Thus far, I've gotten to the point where it will print out everything until the very last few digits. I have to make use of fork() to do all of the computation with my companion program. The main program is unable to do any computation for the final sum. I've tried to pull out the last few digits by creating a new dynamic array, but this is useless if there happens to be 100 or more single digits for example.

It will print out from the terminal after doing ./coordinator 3 4 3 2 1 4 5 4 3 2 4 3 2

**** BEGINNING OPERATIONS ****

Process ID: 5642
Calculation: Sum of 3 and 4 is 7

Process ID: 5643
Calculation: Sum of 3 and 2 is 5

Process ID: 5644
Calculation: Sum of 1 and 4 is 5

Process ID: 5645
Calculation: Sum of 5 and 4 is 9

Process ID: 5646
Calculation: Sum of 3 and 2 is 5

Process ID: 5647
Calculation: Sum of 4 and 3 is 7

Process ID: 5648
Calculation: Sum of 2 and 0 is 2

**** MIDDLE OPERATIONS ****

ProcessID 5649:
Calculation: Sum of 7 and 5 is 12

ProcessID 5650:
Calculation: Sum of 5 and 9 is 14

ProcessID 5651:
Calculation: Sum of 5 and 7 is 12

ProcessID 5652:
Calculation: Sum of 2 and 0 is 2

**** ENDING OPERATIONS ****

ProcessID 5654:
Calculation: Sum of 12 and 14 is 26

ProcessID 5656:
Calculation: Sum of 12 and 2 is 14

return_array[0]: 12
return_array[1 ]: 14
return_array[2]: 12
return_array[3]: 2
return_array[4]: 26
return_array[5]: 14

Things get complicated where there are a line of odd numbers, so you must add a zero at any in point the computation. So you can make the set even again, thus allowing the computation to continue.

Such as this line: ProcessID 5652: Calculation: Sum of 2 and 0 is 2

If I make the numbers more complicated(more digits at the very beginning), the part after 'ending operations' get BIGGER and thus makes it even harder to pull the very last few sums out to end up with one total sum. I'm unable to pull these digits out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

美煞众生 2024-08-26 18:12:19

看起来您正在构建一个递归程序。我不知道你为什么将逻辑分为开始、中间和结束操作?

我建议您将其实现为 head::tail 递归,其中每个调用将第一个参数添加到其余参数上运行的结果中,或者如果没有参数则返回零:

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
print@ARGV&&(shift(@ARGV)+‘$0 @ARGV‘)||0

虽然这是用 Perl 编写的,并不是每个人都能阅读,而且 Perl 在幕后为我们做了很多工作,但它演示了实现递归头的方法::使用 fork 和 exec 的尾部求和函数。

这是使用退出代码的 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< /code>) 被 NULL 终止。然而,它可以工作,并且演示了在 c 中使用 fork、exec 和 exit 代码的递归。运行未注释的调试 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

如您所见,我没有使用任何树或列表 - 我只是每次重新调用该程序,将参数列表指针移动 1。

这是分而治之的版本:

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 的内容克隆到新的、足够大且以 null 结尾的数组中。在我的示例中,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

这清楚地表明问题被分成越来越小的两半。

Looks like you are building a recursive program. I'm not sure why you have divided the logic into beginning, middle and end operations?

I suggest you either implement this as head::tail recursion, where each invocation adds the first argument to the result of running on the remaining ones, or returns zero if it has no arguments:

Program -> 0
Program head,... -> head + program ...

OR divide and conquer, where each invocation either returns it's single argument, zero for none, or forks two sub-invocations, each with half of the remaining arguments:

Program -> 0
Program x -> x
Program (N args) -> Program (N+1/2 args) + Program (remaining args) 

No complex internal data structures are required, just some light array handling:

I should point out that it's a bad idea to communicate value through exit codes, since exit codes have a very limited set of values (256) available for this use, and if your program fails for some reason it may return a surprising value.

Here's a perl version that doesn't use exit code:

#!/usr/bin/perl
print@ARGV&&(shift(@ARGV)+‘$0 @ARGV‘)||0

While this is in perl, which not everyone can read, and perl is doing a lot of work behind the scenes for us, it demonstrates the way you can implement a recursive head::tail sum function using fork and exec.

Here's the c version that uses exit codes:

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
}

Please note that this code is NOT SAFE, and it uses undocumented features such as the main argument array argv (a) being NULL terminated. However, it works, and demonstrates recursion using fork, exec and exit codes in c. Running with the debug printf uncommented:

$ 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

As you can see, I haven't used any trees or lists - I just re-invoke the program each time, moving the argument list pointer along by one.

Here's the divide-and-conquer version:

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
}

I would like to recommend that you don't use my code; it's ugly, unsafe and deliberately compacted to form a small example for posting here. You should re-write using functional decomposition, error checking and comments, as well as cloning the contents of argv into new, large enough and null terminated arrays. Also the third argument to execve is misleading in my example.

Uncommenting the debug printf:

int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");

we get:

$ ./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

Which clearly shows the problem being split into increasingly small halves.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文