本文只提供源码,不会进行代码讲解,如需部分讲解,请前往我的另一篇文章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