C程序无限一元运算不工作

jrcvhitl  于 2023-02-07  发布在  其他
关注(0)|答案(2)|浏览(103)

我有三个c程序double.c,用于将整数加倍,root.c用于取整数的平方根,square用于取整数的平方

./root 9
output:3
./square 9
81
./double 3
ouput:6

我想将这些操作链接起来,如模式将从左到右

./square root square double 8
pattern = double(square(root(square(8))))

也可以是这样的

./root square 8
pattern = square(root(8))

我尝试的是

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

double operate(char * operation, double operand) {
    if (strcmp(operation, "square") == 0) {
        return pow(operand, 2);
    } else if (strcmp(operation, "root") == 0) {
        return sqrt(operand);
    } else if (strcmp(operation, "double") == 0) {
        return 2 * operand;
    }
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <operand> <operation1> <operation2> ...\n", argv[0]);
        return 1;
    }
    double operand = atof(argv[1]);
    for (int i = 2; i < argc; i++) {
        operand = operate(argv[i], operand);
    }
    printf("Result: %.2f\n", operand);
    return 0;
}

工作就像

gcc main.c -o main
./main 8 square root double
output = Works fine

但这是一种不同的方式,而且在实施之前存在一些限制以下是限制
·如果您的实现导致进程之间的父子关系,则父进程必须等待其子进程退出
系统调用和库函数您只能使用下面提到的API来实现此问题

- fork
 - exec* family
 - str* family
 - ato* family
 - printf, sprintf
 - round

但我无法掌握这是如何与过程和它将如何做请指导我一些正确的方向,这样我就可以完成这一点。

pod7payv

pod7payv1#

我想把这些操作链接起来,就像从左到右的模式一样

./square root square double 8
pattern = double(square(root(square(8))))

假设这样的链接可以从这三个操作中的任何一个开始,那么你的每个程序都需要知道如何进行这样的链接,而且,正如你所认识到的,你所呈现的代码不符合要求,因为它使用了一个单独的命令来运行这个链接。
让我们考虑一下约束,父进程必须等待其子进程的要求(实际的和明确的),再加上允许列表中忽略了任何允许父进程这样做的函数,这意味着fork()是一个转移注意力的问题,你不能使用fork(),因为你不被允许等待。
另外,pow()sqrt()都不在允许的函数列表中。无论如何,x * x是比pow()更好的求平方方法,但是如果你想避免sqrt(),那么你需要实现一种数值方法来计算平方根。例如,你可以执行二进制搜索来求根,或者应用Newton's method
至于链接,我看到有两种主要的实现方法:
1.* * 所有的程序都是 * 相同的 * 程序**,它根据启动的名称(argv[0])来识别序列中的第一个操作。它读取数值参数,然后从参数0开始依次应用每个操作。当没有更多的操作要执行时,它打印结果。

      • 这三个程序各自特定于一个操作**。运行时,它们从最后一个参数中选取数字操作数,并对其执行特定操作。然后,
  • 如果没有其他参数(argc == 2),则打印结果;
  • 否则,它们将结果格式化为字符串,并使用execve()(没有分叉)对中间结果运行操作链的尾部。

细节是留给他们的演习是注定的。

rdrgkggo

rdrgkggo2#

你可以这样做,而不是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

double operate(char * operation, double operand) {
    if (strcmp(operation, "square") == 0) {
        return operand * operand;
    } else if (strcmp(operation, "root") == 0) {
        return sqrt(operand);
    } else if (strcmp(operation, "double") == 0) {
        return 2 * operand;
    }
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <operand> <operation1> <operation2> ...\n", argv[0]);
        return 1;
    }
    double operand = atof(argv[argc - 1]);
    for (int i = argc - 2; i > 1; i--) {
        operand = operate(argv[i], operand);
    }
    printf("Result: %.2f\n", operand);
    return 0;
}

就像在评论中说的,你需要从最后一个参数开始,所以你从argc - 2开始,这将是倒数第二个。
另外,似乎不允许使用pow,所以只使用operand * operandsqrt也不在您的列表中,但我猜这是个错误。如果没有,您可以使用一些近似值。
在不使用sqrt函数的情况下计算平方根的最简单方法是使用Newton's method求函数的正根

#define EPSILON 0.001

double simple_abs(double x)
{
    return x > 0 ? x : -x;
}

double simple_sqrt(double x)
{
    double previous = 0;
    double guess = x;

    while (simple_abs(guess - previous) > EPSILON)
    {
        previous = guess;
        guess = previous - (previous * previous - x) / (2 * previous);
    }

    return guess;
}

这不是最优的解决方案,但却是我发现的最简单的解决方案。

相关问题