首页 > 其他分享 >C语言实现对函数求积分(终端输入函数型)

C语言实现对函数求积分(终端输入函数型)

时间:2025-01-07 15:33:59浏览次数:3  
标签:node Node return 函数 积分 pos C语言 num exp

本文只提供源码,不会进行代码讲解,如需部分讲解,请前往我的另一篇文章C语言对各类复杂函数精确求导(在终端解析字符串并求导)_c语言导数函数-CSDN博客

支持 + - * / exp() sin() cos() tan() cot() ^ arc函数  log(底数,真数)

输入格式为:JF <函数> dx

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

// 定义节点类型
typedef enum 
{
    O_num,   // 数字
    O_x,     // 变量 'x'
    O_do,    // 操作符
    O_fun    // 函数
} NodeType;

// 定义节点结构体
typedef struct Node 
{
    NodeType type;
    union 
    {
        double num;       // 数字节点
        char op;          // 操作符节点
        char func[10];    // 函数节点
    } value;
    struct Node *l;       // 左子节点
    struct Node *r;       // 右子节点
} Node;

// 前向声明函数原型
Node* f_exp(const char *exp, size_t *pos);
Node* f_Term(const char *exp, size_t *pos);
Node* f_fac(const char *exp, size_t *pos);
Node* f_Pri(const char *exp, size_t *pos);
Node* integrate(Node *node);            // 符号积分函数
void PrintOutexp(Node *node, int is_needKuohao);    // 打印表达式函数
Node* simplify(Node *node);             // 表达式简化函数

// 创建节点的辅助函数
Node* c_num(double num) 
{
    Node *node = (Node *)malloc(sizeof(Node));
    if (node == NULL) 
    {
        exit(1);
    }
    node->type = O_num;
    node->value.num = num;
    node->l = node->r = NULL;
    return node;
}

Node* c_x() 
{
    Node *node = (Node *)malloc(sizeof(Node));
    if (node == NULL) 
    {
        exit(1);
    }
    node->type = O_x;
    node->l = node->r = NULL;
    return node;
}

Node* c_do(char op, Node *l, Node *r) 
{
    Node *node = (Node *)malloc(sizeof(Node));
    if (node == NULL) 
    {
        exit(1);
    }
    node->type = O_do;
    node->value.op = op;
    node->l = l;
    node->r = r;
    return node;
}

Node* c_fun(const char *func, Node *a1, Node *a2) 
{
    Node *node = (Node *)malloc(sizeof(Node));
    if (node == NULL) 
    {
        exit(1);
    }
    node->type = O_fun;
    snprintf(node->value.func, sizeof(node->value.func), "%s", func);
    node->l = a1;
    node->r = a2;
    return node;
}

// 辅助函数:创建绝对值表达式 |expr|
Node* c_abs(Node *expr)
{
    return c_fun("abs", expr, NULL);
}

// 释放节点及其子节点
void freeN(Node *node) 
{
    if (node != NULL) 
    {
        freeN(node->l);
        freeN(node->r);
        free(node);
    }
}

// 判断是否为操作符
int is_op(char c) 
{
    return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}

// 获取操作符的优先级
int get_f(char op) 
{
    if (op == '+' || op == '-') return 1;
    if (op == '*' || op == '/') return 2;
    if (op == '^') return 3;
    return 0;
}

// 解析表达式(加法和减法)
Node* f_exp(const char *exp, size_t *pos) 
{
    Node *node = f_Term(exp, pos);
    while (is_op(exp[*pos]) && (exp[*pos] == '+' || exp[*pos] == '-')) 
    {
        char op = exp[(*pos)++];
        Node *r = f_Term(exp, pos);
        node = c_do(op, node, r);
    }
    return node;
}

// 解析项(乘法和除法)
Node* f_Term(const char *exp, size_t *pos) 
{
    Node *node = f_fac(exp, pos);
    while (is_op(exp[*pos]) && (exp[*pos] == '*' || exp[*pos] == '/')) 
    {
        char op = exp[(*pos)++];
        Node *r = f_fac(exp, pos);
        node = c_do(op, node, r);
    }
    return node;
}

// 解析因子(幂运算)
Node* f_fac(const char *exp, size_t *pos) 
{
    Node *node = f_Pri(exp, pos);
    while (exp[*pos] == '^') 
    {
        (*pos)++;
        Node *r = f_Pri(exp, pos);
        node = c_do('^', node, r);
    }
    return node;
}

// 解析初级表达式(数字、变量、括号、函数)
Node* f_Pri(const char *exp, size_t *pos) 
{
    // 忽略空白字符
    while (isspace(exp[*pos])) (*pos)++;

    if (isdigit(exp[*pos]) || exp[*pos] == '.') 
    {
        char *end;
        double num = strtod(exp + *pos, &end);
        *pos += end - (exp + *pos);
        return c_num(num);
    } 
    else if (exp[*pos] == 'x') 
    {
        (*pos)++;
        return c_x();
    } 
    else if (exp[*pos] == '(') 
    {
        (*pos)++;
        Node *node = f_exp(exp, pos);
        if (exp[*pos] != ')') 
        {
            fprintf(stderr, "括号不匹配,请检查表达式!\n");
            exit(1);
        }
        (*pos)++;
        return node;
    } 
    else if (strncmp(exp + *pos, "sqrt", 4) == 0) 
    {
        (*pos) += 4;
        if (exp[*pos] != '(') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        Node *arg = f_exp(exp, pos);
        if (exp[*pos] != ')') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        return c_fun("sqrt", arg, NULL);
    } 
    else if (strncmp(exp + *pos, "sin", 3) == 0) 
    {
        (*pos) += 3;
        if (exp[*pos] != '(') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        Node *arg = f_exp(exp, pos);
        if (exp[*pos] != ')') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        return c_fun("sin", arg, NULL);
    } 
    else if (strncmp(exp + *pos, "cos", 3) == 0) 
    {
        (*pos) += 3;
        if (exp[*pos] != '(') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        Node *arg = f_exp(exp, pos);
        if (exp[*pos] != ')') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        return c_fun("cos", arg, NULL);
    } 
    else if (strncmp(exp + *pos, "tan", 3) == 0) 
    {
        (*pos) += 3;
        if (exp[*pos] != '(') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        Node *arg = f_exp(exp, pos);
        if (exp[*pos] != ')') 
        {
            fprintf(stderr, "函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        return c_fun("tan", arg, NULL);
    } 
    else if (strncmp(exp + *pos, "log", 3) == 0) 
    {
        (*pos) += 3;
        if (exp[*pos] != '(') 
        {
            fprintf(stderr, "log函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        Node *base = f_exp(exp, pos);
        if (exp[*pos] != ',') 
        {
            fprintf(stderr, "log函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        Node *num = f_exp(exp, pos);
        if (exp[*pos] != ')') 
        {
            fprintf(stderr, "log函数格式错误!\n");
            exit(1);
        }
        (*pos)++;
        return c_fun("log", base, num);
    } 
    else if (strncmp(exp + *pos, "e", 1) == 0) 
    {
        (*pos)++;
        return c_num(M_E);
    }
    else 
    {
        fprintf(stderr, "非法的表达式格式!\n");
        exit(1);
    }
}

// 符号积分函数
Node* integrate(Node *node) 
{
    if (node->type == O_x) 
    {
        return c_do('/', c_do('^', c_x(), c_num(2)), c_num(2));
    }
    else if (node->type == O_num) 
    {
        return c_do('*', node, c_x());
    }
    else if (node->type == O_do) 
    {
        switch (node->value.op) 
        {
            case '+':
                return c_do('+', integrate(node->l), integrate(node->r));
            case '-':
                return c_do('-', integrate(node->l), integrate(node->r));
            case '*':
                // 处理乘法的情况
                if (node->l->type == O_num && node->r->type == O_x)
                    return c_do('*', node->l, c_do('/', c_do('^', c_x(), c_num(2)), c_num(2)));
                else if (node->l->type == O_x && node->r->type == O_num)
                    return c_do('*', node->r, c_do('/', c_do('^', c_x(), c_num(2)), c_num(2)));
                else
                    return c_do('*', integrate(node->l), integrate(node->r));
            case '/':
                // 处理除法的情况
                if (node->l->type == O_x && node->r->type == O_num)
                    return c_do('/', c_do('/', c_do('^', c_x(), c_num(-1)), c_num(-1)), node->r);
                else
                    return c_do('/', integrate(node->l), node->r);
            case '^':
                // 处理幂的情况
                if (node->l->type == O_x && node->r->type == O_num)
                    return c_do('/', c_do('*', c_do('^', c_x(), c_do('+', node->r, c_num(1))), node->r), c_do('+', node->r, c_num(1)));
                else
                    return c_do('*', integrate(node->l), c_do('^', c_x(), node->r));
        }
    }
    else if (node->type == O_fun) 
    {
        if (strcmp(node->value.func, "sin") == 0) 
        {
            return c_do('-', c_fun("cos", node->l, NULL), NULL);
        }
        else if (strcmp(node->value.func, "cos") == 0) 
        {
            return c_do('+', c_fun("sin", node->l, NULL), NULL);
        }
        else if (strcmp(node->value.func, "tan") == 0) 
        {
            // 使用绝对值函数处理 tan 的积分
            Node *cos_l = c_fun("cos", node->l, NULL);
            Node *one = c_num(1);
            Node *abs_expr = c_abs(c_do('-', one, cos_l));
            Node *log_expr = c_fun("log", abs_expr, NULL);
            // 返回减法表达式,并提供右子节点为常量 0
            return c_do('-', log_expr, c_num(0));
        }
        else if (strcmp(node->value.func, "log") == 0) 
        {
            return c_do('*', node, c_x());
        }
        else if (strcmp(node->value.func, "sqrt") == 0) 
        {
            return c_do('*', c_do('/', c_num(2), c_num(3)), c_do('^', node->l, c_do('/', c_num(3), c_num(2))));
        }
    }
    return NULL;
}

// 表达式简化函数
Node* simplify(Node *node) 
{
    if (node == NULL) return NULL;

    // 递归简化左右子树
    node->l = simplify(node->l);
    node->r = simplify(node->r);

    if (node->type == O_do) 
    {
        switch (node->value.op) 
        {
            case '*':
                // 简化乘法
                if (node->l->type == O_num && node->r->type == O_num) 
                {
                    double result = node->l->value.num * node->r->value.num;
                    freeN(node->l);
                    freeN(node->r);
                    return c_num(result);
                }
                break;
            case '/':
                // 简化除法
                if (node->l->type == O_num && node->r->type == O_num) 
                {
                    double result = node->l->value.num / node->r->value.num;
                    freeN(node->l);
                    freeN(node->r);
                    return c_num(result);
                }
                break;
            case '^':
                // 简化幂运算
                if (node->l->type == O_x && node->r->type == O_num) 
                {
                    if (node->r->value.num == 2) 
                    {
                        Node *new_node = c_do('*', c_x(), c_x());
                        freeN(node->l);
                        freeN(node->r);
                        return new_node;
                    }
                    else if (node->r->value.num == 3) 
                    {
                        Node *new_node = c_do('*', c_do('*', c_x(), c_x()), c_x());
                        freeN(node->l);
                        freeN(node->r);
                        return new_node;
                    }
                }
                break;
        }
    }

    return node;
}

// 打印表达式函数
void PrintOutexp(Node *node, int is_needKuohao) 
{
    if (node == NULL) 
    {
        return;
    }

    if (node->type == O_num) 
    {
        printf("%g", node->value.num);
    } 
    else if (node->type == O_x) 
    {
        printf("x");
    } 
    else if (node->type == O_do) 
    {
        if (is_needKuohao) 
        {
            printf("(");
        }
        PrintOutexp(node->l, 1);
        printf(" %c ", node->value.op);
        PrintOutexp(node->r, 1);
        if (is_needKuohao) 
        {
            printf(")");
        }
    } 
    else if (node->type == O_fun) 
    {
        printf("%s(", node->value.func);
        PrintOutexp(node->l, 0);
        if (node->r != NULL) 
        {
            printf(", ");
            PrintOutexp(node->r, 0);
        }
        printf(")");
    }
}

// 主函数
int main() 
{
    char input[256];
    printf("请输入表达式: ");
    fgets(input, sizeof(input), stdin);

    // 去掉换行符
    input[strcspn(input, "\n")] = 0;

    // 检查输入格式
    if (strncmp(input, "JF ", 3) != 0 || strstr(input, " dx") == NULL) 
    {
        fprintf(stderr, "输入格式错误!请按照 JF <函数> dx 格式输入。\n");
        return 1;
    }

    // 提取表达式部分
    char *expr_start = input + 3;
    char *dx_pos = strstr(expr_start, " dx");
    *dx_pos = '\0';

    size_t pos = 0;
    Node *root = f_exp(expr_start, &pos);

    // 进行积分
    Node *integral = integrate(root);

    // 简化积分结果
    Node *simplified_integral = simplify(integral);

    // 输出积分结果
    printf("积分结果: ");
    PrintOutexp(simplified_integral, 0);
    printf(" +C")
    printf("\n");

    // 释放内存
    freeN(root);
    freeN(integral);
    freeN(simplified_integral);

    return 0;
}

标签:node,Node,return,函数,积分,pos,C语言,num,exp
From: https://blog.csdn.net/ChaoJihtd/article/details/144986400

相关文章

  • React函数组件中与生命周期相关Hooks详解
    React函数组件及其钩子渲染流程是React框架中的核心概念之一。以下是对该流程的详细解析:一、React函数组件基础定义:React函数组件是一个接收props作为参数并返回React元素的函数。它们通常用于表示UI的一部分,并且不保留内部状态(除非使用React的Hooks)。......
  • Python 中的三种字符串格式化方式:% 格式化字符、str.format方法、f-string函数
    Python中的三种字符串格式化方式:%格式化字符、str.format方法、f-string函数Python中的三种字符串格式化方式:%格式化字符、str.format()方法和f-string(f函数)1.格式化字符(%格式化)1.1优缺点,使用场景1.2%格式化字符详细说明1.3什么是宽度?1.4格式化字符语法1.......
  • 如何把先验知识引入到深度学习的损失函数中
    可以根据具体问题和领域知识构建带有物理约束的损失函数,以进一步指导模型的优化调整。这种物理约束可以以多种形式融入损失函数中。例如,可以通过引入与物理规律相关的物理引导项,用于约束模型输出与物理规律一致。这样的物理引导项可以基于已知的物理方程、领域专家知识(经验知识......
  • C语言指针数组
    1. 指针数组的定义指针数组是数组,其元素为指针。定义格式为 数据类型*数组名[数组大小] 。例如,定义一个能存放5个指向 int 类型数据的指针数组: cint*ptrArray[5];  2. 初始化-方式一:直接初始化 cintnum1=10,num2=20;int*ptrArray[]={&num......
  • 深入解析IPoIB网络设备的驱动实现:net_device_ops与ipoib_open函数
    在Linux内核中,网络设备的驱动实现通常通过net_device_ops结构体来定义设备的各种操作函数。本文将以IPoverInfiniBand(IPoIB)设备的驱动实现为例,深入分析net_device_ops结构体的定义以及ipoib_open函数的实现细节。通过这段代码,我们可以了解如何在内核中实现网络设备的初始化、......
  • C#版OpenCv常用函数大全
    OpenCvSharp是OpenCV的NET封装,提供了丰富的图像处理和计算机视觉功能。以下是一些常用函数及其详细说明。1.图像读取与显示Cv2.ImRead功能:读取图像文件并返回一个Mat对象。用法:Matimage=Cv2.ImRead("path/to/image.jpg");Cv2.ImShow功能:在窗口中显示图像。用法:C......
  • 微积分基本公式汇总
    微积分基本公式汇总若\(f(x)=x^n\),有\(f'(x)=nx^{n-1}\).\(\frac{d}{dx}(g(x)+h(x))=\frac{dg}{dx}+\frac{dh}{dx}\).\(\frac{d}{dx}(g(x)h(x))=g(x)h'(x)+h(x)g'(x)\)(左乘右导,右乘左导).\(\frac{d}{dx}(g(h(x)))=\frac{dg}{dh}(h(x))......
  • 位向量系统函数
    1基本概念$countbits( expression , list_of_control_bits )$countones( expression )$onehot( expression )$onehot0( expression )$isunknown( expression )2示例1$countbits        Thefunction $countbits countsthenumberofbi......
  • C语言的学习路线
    C语言的学习路线C语言是一种广泛使用的编程语言,它以其高效、灵活和接近底层的特性被广泛应用于系统编程、嵌入式系统、操作系统和众多应用程序开发中。对于初学者来说,学习C语言不仅是了解计算机编程的一个良好起点,同时也为后续学习其他编程语言打下坚实的基础。本文将详细......
  • Objective-C语言的数据结构
    Objective-C语言中的数据结构Objective-C是一种面向对象的编程语言,其在苹果公司的软件开发中得到了广泛应用。它主要用于开发macOS和iOS应用程序。虽然Objective-C有许多丰富的特性,但在程序设计中,数据结构仍然是构建任何应用程序的基础。本文将探讨Objective-C中的几种常见......