【问题标题】:Addition of two functions添加两个功能
【发布时间】:2014-07-09 19:27:02
【问题描述】:

我在 C++ 中做一个解析函数,它接受一个字符串和一个双精度作为参数,并返回字符串的“值”。

代码如下:

double evaluate (char * toParse, int length, double x)
{

    // Case 'x'
    if ((toParse[0] == 'x') &&
        (length == 1))
    {
        return x;
    }

    // Case value
    char * endptr;
    double num = strtod(toParse, &endptr);
    if(endptr - toParse == length)
    {
        return num;
    }

    // Parsing
    int nBrackets = 0;
    for (int i = 0; i < length; i++)
    {
        if (toParse[i] == '(')
        {
            nBrackets++;
        }
        else if (toParse[i] == ')')
        {
            nBrackets--;
        }

        // Remove brackets.
        double _x = (toParse[0] == '(' && toParse[i-1] == ')' ) ?
                        evaluate(&toParse[1], i-2, x) : evaluate(toParse, i, x);
        double _y = (toParse[i+1] == '(' && toParse[length-1] == ')' ) ?
                        evaluate(&toParse[i+2], length - (i+1) - 2, x) : evaluate (&toParse[i+1] , length - (i+1), x);

        // Supports +, -, * and /
        if (nBrackets == 0 &&
            toParse[i] == '+')
        {
            return _x + _y;
        }
        else if (nBrackets == 0 &&
            toParse[i] == '-')
        {
            return _x - _y;
        }
        else if (nBrackets == 0 &&
            toParse[i] == '*')
        {
            return _x * _y;
        }
        else if (nBrackets == 0 &&
            toParse[i] == '/')
        {
            return _x / _y;
        }
    }
    return 0.;
}

int main()
{
    cout << evaluate("((4*x)+7)-x", 11, 5.) << endl;
    // Outputs 22, which sounds correct.
    return 0;
}

它远非完美无缺(运算符没有优先级,如果字符串包含太多括号等则不起作用),但我想删除双 x 参数,并直接处理函数。 (因为我想绘制函数,如果我不处理函数,我将不得不为 x 的每个值解析相同的字符串...)

有可能吗?我的意思是,做类似的事情:

double (double) operator+ (double f(double), double g(double))
{
    double h (double x)
    {
        return f(x)+g(x);
    }
    return h;
}

但它当然不起作用。有任何想法吗 ? (类等)

谢谢。

【问题讨论】:

  • 在 C++11 中使用字符串字面量调用该函数是非法的。
  • C 和 C++ 都允许将指针传递给其他函数。
  • 您好,谢谢三位! @chris:我不能只使用 std::string 来遵守 C++11 吗?我不介意改变它!
  • @Jongware:你能解释一下吗?我实际上看不到应该将哪个指针传递给哪个函数:(
  • return [=](double x) {return f(x)+g(x);}; 可以是std::function 之类的,但只有当一种类型是用户定义的类型时,才能重载运算符。

标签: c++ c++11


【解决方案1】:

您可以为此使用函数指针。如果你也想要一个函数指针作为参数,我不太明白,但你可以这样做:

typedef double (*handler) (double);


double add(handler x, handler y);
double sub(handler x, handler y);
double func1(double n);
double func2(double n);

int main()

{

    double (*funcPtr[256]) (double);

    funcPtr['+'] = func1;
    funcPtr['-'] = func2;

    double answer = funcPtr['+'](2));
}

double func1(double n)
{
    return n;
}

double func2(double n)
{
    return n;
}

double add(handler x, handler y) 
{ 
    return x(2) + y(2);
}
double sub(handler x, handler y) 
{ 
    return x(4) - y(2);
}

如果不是您要查找的内容,但类似以下代码的内容,请告诉我,我将编辑我的答案:

funcPtr[toParse[i]](2, 2); // toParse[i] is '+' it will then call add(2,2)

256 大小的funcPtr 数组是相对于sizeof(char)。您应该确保index 是数组中的实际值,否则您将访问越界。

【讨论】:

    【解决方案2】:

    我想到了一个 lambda。不幸的是,我认为从捕获函数参数的函数返回 lambda 是未定义的行为。 您也不能重载函数指针等类型的构建。 你可以这样做:

    #include <iostream>
    #include <functional>
    
    struct CombinedFunction{
        enum class Operator{ add, subtract, multiply, divide } op;
        CombinedFunction(std::function<double(double)> f1, std::function<double(double)> f2, Operator op) : f1(std::move(f1)), f2(std::move(f2)), op(op){
        }
        std::function<double(double)> f1, f2;
        double operator()(double d){
            switch (op){
            case Operator::add:
                return f1(d) + f2(d);
                break;
            case Operator::subtract:
                //...
                break;
                //...
            }
        }
    };
    
    std::function<double(double)> operator+ (std::function<double(double)> f, std::function<double(double)> g){
        return CombinedFunction(f, g, CombinedFunction::Operator::add);
    }
    
    double f(double x){
        return 2 * x;
    }
    double g(double x){
        return 3 * x;
    }
    
    int main(){
        auto h = std::function<double(double)>(f) + g;
        std::cout << h(2);
        auto h2 = f + h + g;
        std::cout << h2(2);
    }
    

    它不能很好地扩展并且效率不高。也许有一个模板解决方案可以在编译时完成所有这些。

    【讨论】:

    • 嗨,我使用了你的解决方案,一切都很好!我不太了解“double operator() (double d)”和“return CombinedFunction(...);”背后的魔力,但无论如何 :) 我会改变我的 std::function评估 (char * toParse, int length) 原型到:std::function 评估 (std::string toParse) 稍后,所以它会更多 C++ ! :) 谢谢!
    • 我认为这个答案有点过于复杂:coliru.stacked-crooked.com/a/f3e3b18ff464a97f
    猜你喜欢
    • 1970-01-01
    • 2022-07-24
    • 1970-01-01
    • 2020-10-25
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2010-12-04
    相关资源
    最近更新 更多