C语言:字符串 -带括号的加减乘除运算

本文介绍了一种用于解析和计算数学表达式的算法,通过处理括号配对、乘除和加减运算,实现了对复杂数学表达式的正确计算。算法首先进行乘除运算,然后处理加减,同时支持括号内的递归计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

示例代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>


//去空格 下标方法
void space(char* str);

//去空格或任意字符 ,指针方法
void eatspace(char* str, char ch);

//判断字符是否是数字  0:是 |  1:否
int is_number(char ch);

//获取数据  [参数:str=字符串 ;index=下标]
double get_number(char* str, int* vptr_index);

//expression_analysis  算式分析:加减发
double expression_analysis_addorsub(char* str);
//expression_analysis  算式分析:乘除发
double expression_analysis_mutordiv(char* str, int* vptr_index);

//处理括号配对 算式分析 
char* bracket_analysis(char* str, int* vptr_index);

void main()
{
	printf("请输入算式:\n");
	char str[128] = { 0 };
	scanf("%[^\n]", str);
	printf("要计算 :%s\n", str);

	eatspace(str, ' ');
	printf("去空格后 :%s\n", str);

	int index = 0;
	double value = get_number(str, &index);

	printf("获取第一个数字为 :%f \n", value);

	double res = expression_analysis_addorsub(str);

	printf("加法结果 :%f \n", res);

	system("pause");
}

//乘除法:str=算式 ; vptr_index=下标
double expression_analysis_mutordiv(char* str, int* vptr_index)
{
	double value = 0.0;
	value = get_number(str, vptr_index);
	while (1)
	{
		if (*(str + (*vptr_index)) == '*')//如果是乘号
		{
			(*vptr_index)++; //下标向前移动
			value *= get_number(str, vptr_index);//计算乘法
		}
		else if (*(str + (*vptr_index)) == '/') //如果是除号
		{
			(*vptr_index)++; //下标向前移动
			value /= get_number(str, vptr_index);//计算乘法
		}
		else
		{
			break;
		}
	}
	return value;
}


//加减法
double expression_analysis_addorsub(char* str)
{
	double value = 0.0;
	int index = 0;
	value = expression_analysis_mutordiv(str, &index);
	while (1)
	{
		char ch = *(str + index);
		index++;//循环遍历

		switch (ch)
		{
		case '\0':
			return value;
		case '+':
			value += expression_analysis_mutordiv(str, &index);
			break;
		case '-':
			value -= expression_analysis_mutordiv(str, &index);
			break;
		default:
			break;
		}

	}

}

//处理括号配对分析
char* bracket_analysis(char* str, int* vptr_index)
{
	char* pbarstr = NULL;
	int num = 0;//记录包含括号的对数
	int left_bar = *vptr_index;//左括号位置(下标)

	do
	{

		switch (*(str + (*vptr_index)))//处理括号字符
		{
			case '(':
				num++;
				break;
			case ')':
				if (num==0)
				{
					(*(vptr_index))++;//移动到括号的后面
					pbarstr = malloc(sizeof(char) * (*vptr_index - left_bar));
					if (pbarstr != NULL)
					{
						strncpy_s(pbarstr, *vptr_index - left_bar, str + left_bar, *vptr_index - left_bar - 1);//拷贝字符串
						printf("拆解:%s\n", pbarstr);
						return pbarstr;
					}
					else
					{
						return NULL;
					}
					
				}
				else
				{
					num--;
				}
				break;
			default:
				break;
		}
	} while (*(str + (*vptr_index)++) != '\0');//字符串没有结束,继续循环

}

//获取数据  [参数:str=字符串 ;index=下标]
double get_number(char* str, int* vptr_index)
{
	double result = 0.0;
	int index = *vptr_index;

	//括号配对处理:

	while (*(str + index) == '(')
	{
		char* psubstr = NULL;//取出字符串
		*vptr_index = ++index;//下标跳到括号的后面
		psubstr = bracket_analysis(str, vptr_index);//获取括号中的字符串
		if (psubstr != NULL)
		{
			result = expression_analysis_addorsub(psubstr);
			free(psubstr);//释放内存
			psubstr = NULL;
		}
		return result;
	}

	/*---------------------------------------------------------------*/
	while (is_number(*(str + index)))
	{
		result = result * 10 + (str[index] - '0');//字符转数字
		index++;//下标向前
	}

	if (*(str + index) == '.')
	{
		double decimals = 1.0;
		while (is_number(*(str + ++index)))//循环到小数位后面的非数字位置
		{
			decimals /= 10;//小数
			result += decimals * (*(str + index) - '0');
		}
	}
	*vptr_index = index;//保存下标位置
	return result;
}

//判断字符是否是数字
int is_number(char ch)
{
	int flag = 0;
	if (ch >= '0' && ch <= '9')
	{
		flag = 1;
	}
	return flag;
}

void space(char* str)
{
	int i = 0;
	int j = 0;
	while (str[i] != '\0')
	{
		str[i] = str[j];
		if (str[i] != ' ')
		{
			i++; //有条件的下标前进
		}
		j++; //一定要前进
	}

	/*
	 //简化写法
	while (str[i] = str[j++]!='\0')
	{
		if (str[i] != ' ')
		{
			i++;
		}
	}

	*/

}

/*
 去掉字符串中指定字符

*/
void eatspace(char* str, char ch)
{
	char* vptr1 = str;
	char* vptr2 = str;

	while (*vptr1 != '\0')
	{
		*vptr1 = *vptr2;
		if (*vptr1 != ch)
		{
			vptr1++;
		}
		vptr2++;
	}

	/*while (*vptr1=*(vptr2++)!='\0')
	{
		if (*vptr1 != ch)
		{
			vptr1++;
		}
	}*/
}

在这里插入图片描述
算法思想:先算乘除再算加减。计算时检测括号把匹配成对的括号字符串挖出再递归计算,直到括号拆解完,在递归加减乘除运算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值