MFC计算器

  MFC计算器主要分为以下三个部分:

1、去括号

2、字符串规范化

3、计算结果


一、去括号

  首先建立一个结构体作为括号匹配的栈

typedef struct tagINDEXSTACK  /*括号下标*/
	{
		int data[StackSize]; /*存取字符串中'('与')'的下标*/
		int top;
	}IndexStack;
然后利用栈原理进行括号匹配

二、字符串规范化

  首先除去所有无效字符,然后判断第一个字符是否为'-',如果是,则在字符串头上加上'0'

  然后处理连续的负号

  然后处理连续的运算符(第一个+ - * /,第二个是 -)

然后取出字符串中的运算数与运算符,分别保存到下面结构体的两个数组

typedef struct tagEXPRESS
	{
		double numget[20];
		char charget[10];
		int lengthget;
		CString str_16;
	}EXPRESS;

三、计算结果

  根据运算数与运算符数组,按照运算规则计算出结果

下面是相关函数

/***********************************************************************************************************************/
/*************************************堆栈处理函数**********************************************************************/
void CCalculatorDlg::IndexInitial(IndexStack *S) /*置栈空*/
{
	S->top = -1;
}
int CCalculatorDlg::IndexIsEmpty(IndexStack *S) /*判断栈是否为空*/
{
	return S->top == -1;
}
int CCalculatorDlg::IndexIsFull(IndexStack *S) /*判断栈是否为满*/
{
	return S->top == StackSize - 1;
}
void CCalculatorDlg::IndexPush(IndexStack *S, int x) /*进栈*/
{
	if (IndexIsFull(S))
	{
		exit(1);
	}
		S->data[++S->top] = x;
}
int CCalculatorDlg::IndexPop(IndexStack *S) /*出栈*/
{
	if (IndexIsEmpty(S))
	{
		return -1;
	}
	return S->data[S->top--];
}
int CCalculatorDlg::IndexTop(IndexStack *S) /*取栈顶元素*/
{
	if (IndexIsEmpty(S))
	{
		exit(1);
	}
	return S->data[S->top];
}
/*************************************************堆栈处理函数结束******************************************************/
/***********************************************************************************************************************/





/**********************************************字符串处理函数***********************************************************/
/***********************************************************************************************************************/
double CCalculatorDlg::GetaStr(CString str) /*如果一个字符串是一个纯数字,则返回对应的double型数字*/
{
	int i = 0;
	double rate = 10.0, itemp = 0.0;

	for (i = 0; i < str.GetLength(); i++)
	{
		if (isdigit(str.GetAt(i))) /*判断字符str.GetAt(i)是否是0-9*/
		{
			if (rate == 10.0) /*整数部分*/
				itemp = itemp * rate + (str.GetAt(i) - '0'); /*获得整数*/
			else /*小数部分*/
			{
				itemp = itemp + rate * (str.GetAt(i) - '0'); /*获得小数*/
				rate /= 10;
			}
		}
		else
		if (str.GetAt(i) == '.') /*如果str.GetAt(i)是小数点*/
			rate = 0.1;
	}

	return itemp;
}

int CCalculatorDlg::DelChar(char *data, char ch, int len) /*删除字符串中的所有特定字符,返回新字符串的长度*/
{
	int i = 0, k = 0;

	for (i = 0; i < len; i++)
	{
		if (data[i] != ch)
			data[k++] = data[i];
	}
	data[k] = '\0';

	return k;
}
int CCalculatorDlg::DelaChar(char *data, int index, int len) /*删除字符串中的某个位置字符,返回新字符串的长度*/
{
	int i = 0, k = 0;

	if (index >= len)exit(1);

	for (i = index; i < len; i++)
	{
		data[i] = data[i + 1];
	}
	data[len - 1] = '\0';

	return len - 1;
}


void CCalculatorDlg::GetStr(char *str, EXPRESS *fp)
{
	int i = 0, j = 0, len = 0, k = 0, z = 0;
	int indexnum[20], flag = 0;/*用于处理连续的运算符*/
	char specstr[512] = "";
	int t = 1;
	double rate = 10.0, itemp = 0.0;
	for (i = 0; i < 20; i++)
		fp->numget[i] = 1000000.0; /*对数组numget[20]初始化*/
	for (i = 0; i < 10; i++)
		fp->charget[i] = ' '; /*对数组charget[10]初始化*/
	for (i = 0; i < 20; i++)
		indexnum[i] = 0; /*对数组numget[20]初始化*/
	printf("原始数据%s\n", str);
	for (i = 0; i < strlen(str); i++)
	{
		if (isdigit(str[i]) || str[i] == '.' || str[i] == '+' || str[i] == '-' ||
			str[i] == '*' || str[i] == '/')
			specstr[len++] = str[i];
	}
	printf("除去无效字符%s\n", specstr);
	if (specstr[0] == '-')
	{
		len++;
		for (k = len - 1; k > 0; k--)
			specstr[k] = specstr[k - 1];
		specstr[0] = '0';
	}
	printf("开始有负号%s\n", specstr);
	len = DelChar(specstr, ' ', len); /*除去多余的空格*/
	printf("除去多余的空格%s\n", specstr);

	k = 0;
	for (i = 1; i < len; i++) /*如果有连续的‘-’*/
	{
		if (specstr[i] == '-')
		{
			j = i;
			t = isdigit(specstr[i - 1]) || specstr[i - 1] == '.';
			while (specstr[j] == '-')
			{
				k++;
				specstr[j++] = ' ';
			}
			i = j;
			if (k % 2) specstr[j - 1] = '-';
			else if (t) specstr[j - 1] = '+';
			k = 0;
		}
	}
	printf("除去连续的负号%s\n", specstr);

	len = DelChar(specstr, ' ', len); /*除去多余的空格*/
	printf("除去多余的空格%s\n", specstr);

	k = 0;
	for (i = 0; i < len - 1; i++)
	{
		if (specstr[i] == '*' || specstr[i] == '/' || specstr[i] == '+' || specstr[i] == '-')
		{
			flag++; /*运算符计数*/
			if (specstr[i + 1] == '-')
			{
				indexnum[k++] = flag; /*记录连续运算符在所有运算符中的位置*/
				len = DelaChar(specstr, i + 1, len);
			}
		}
	}
	printf("处理连续的运算符%s\n连续运算符在所有运算符中的位置", specstr);
	for (i = 0; i < k; i++)
		printf("%d ", indexnum[i]);
	printf("\n");

	for (i = 0; i < len; i++)
	{
		if (isdigit(specstr[i])) /*如果字符串specstr[i]的内容是整数*/
		{
			if (rate == 10.0) /*整数部分*/
				itemp = itemp * rate + (specstr[i] - '0'); /*获得整数*/
			else /*小数部分*/
			{
				itemp = itemp + rate * (specstr[i] - '0'); /*获得小数*/
				rate /= 10;
			}

		}
		else
			switch (specstr[i])
		{
			case '.': /*如果str.GetAt(i)是小数点*/
				rate = 0.1;
				break;
			case '+': /*如果str.GetAt(i)是加号*/
				fp->numget[z++] = itemp;
				itemp = 0; /*把itemp的值放入双精度数组numget中,并把itemp的值改为0*/
				fp->charget[z++] = '+';
				rate = 10.0; /*把10赋给rate,确保读取下个数字时,先计算整数部分*/
				break;
			case '-':
				fp->numget[z++] = itemp;
				itemp = 0;
				fp->charget[z++] = '-';
				rate = 10.0;
				break;
			case '*':
				fp->numget[z++] = itemp;
				itemp = 0;
				fp->charget[z++] = '*';
				rate = 10.0;
				break;
			case '/':
				fp->numget[z++] = itemp;
				itemp = 0;
				fp->charget[z++] = '/';
				rate = 10.0;
				break;
		}
	}
	fp->numget[z] = itemp; /*把最后一个整数itemp的值放入双精度数组a中*/
	fp->lengthget = z + 1;
#if 0
	for (i = 0; i < 20; i++)
	{
		if (indexnum[i] != 100)
		{
			fp->numget[indexnum[i] + 1] *= -1.0;
			printf("%lf\n", fp->numget[indexnum[i] + 1]);
		}
	}
#endif

	k = 0;
	for (i = 0; i < fp->lengthget; i++)
	{
		if (fp->charget[i] == '+' || fp->charget[i] == '-' || fp->charget[i] == '*' || fp->charget[i] == '/')
		{
			k++;
			for (j = 0; j < 20; j++)
			if (k == indexnum[j])
				fp->numget[i + 1] *= -1.0;
		}
	}
	printf("长度为 %d\n", fp->lengthget);
	for (i = 0; i < fp->lengthget; i++)
	{
		printf("%lf ", fp->numget[i]);
	}
	printf("\n");
	for (i = 0; i < fp->lengthget; i++)
	{
		printf("%c ", fp->charget[i]);
	}
	printf("\n");
}

double CCalculatorDlg::GetResult(EXPRESS *fp)
{
	int i = 0, x = 0, y = 1, t = 0, z = 1;

	for (i = 0; i <= fp->lengthget; i++)  /*把所有除法运算都改为乘法计算*/
	{
		if (fp->charget[i] == '/') /*当循环遇到除号时*/
		{
			fp->numget[i + 1] = 1 / fp->numget[i + 1]; /*把numget[i+1]的值改为1/numget[i+1]*/
			fp->charget[i] = '*'; /*把charget[i]的值改为乘号*/
		}
	}

	for (i = 0; i <= fp->lengthget; i++) /*对所有乘法进行计算*/
	{
		if (fp->charget[i] == '*') /*当循环遇到乘号时*/
		{
			if (i - t == 2)
			{
				fp->numget[t - z] = fp->numget[t - z] * fp->numget[i + 1]; /*进行乘法运算,把结果保存在前面的数组元素中*/
				z += 2; /*这里引进变量z,可以解决很多数连续相乘的问题,比如 2*2*2*2*2*2 */
			}
			else
				fp->numget[i - 1] = fp->numget[i - 1] * fp->numget[i + 1]; /*碰到乘号后把乘号前后2个数字相乘,结果保存在前面的数组元素*/
			fp->numget[i + 1] = 1000000.0; /*对乘号后面的数字初始化为0.0*/
			fp->charget[i] = ' '; /*对乘号初始化为空格*/

			t = i;
		}
	}

	for (i = 0; i < fp->lengthget; i++)
	{
		if (fp->numget[i] != 1000000.0)
		{
			fp->numget[x] = fp->numget[i];
			x += 2;
		}
		if (fp->charget[i] != ' ')
		{
			fp->charget[y] = fp->charget[i];
			y += 2;
		}
	}

	for (i = 0; i <= y - 2; i++) /*进行最后的加减法运算,这里i的上限小于等于y-2,可以保证不进行多余的运算*/
	{
		if (fp->charget[i] == '+')
			fp->numget[0] = fp->numget[0] + fp->numget[i + 1];
		if (fp->charget[i] == '-')
			fp->numget[0] = fp->numget[0] - fp->numget[i + 1];
	}
	printf("处理结果%lf\n\n", fp->numget[0]);
	return fp->numget[0];
}


double CCalculatorDlg::BracketMatch(char *expr) /*括号匹配*/
{
	IndexStack S; /*括号下标*/
	char allstr[512] = ""; /*处理掉括号以后的字符串*/
	EXPRESS alldate; /*处理掉括号以后的用于匹配运算符的结构体*/
	int i, j, length = strlen(expr), barcketcount = 0;
	double barckettemp[32] = { 0 }; /*存取每个括号内的计算结果*/

	IndexInitial(&S);

	for (i = 1; i <= length; i++) /*处理所有括号*/
	{
		if (expr[i - 1] == '(')
		{
			IndexPush(&S, i);
		}
		else if (expr[i - 1] == ')')
		{
			j = IndexPop(&S);
			if (j == -1)
			{
				exit(1);
			}
			else
			{
				EXPRESS dataget; /*计算两括号之间的字符串的值*/
				char Bracketstr[512] = ""; /*存取两括号之间的字符串*/
				int k = 0;

				for (k = j; k <= i - 2; k++)
				{
					if (expr[k] == '_')
					{
						char strtemp[16] = "";
						sprintf(strtemp, "%.1f", barckettemp[expr[k++ + 1] - '0']);
						strcat(Bracketstr, strtemp);
					}
					else
					{
						char temp[16] = "";
						sprintf(temp, "%c", expr[k]);
						strcat(Bracketstr, temp);
						strcpy(temp, "");
					}
				}
				GetStr(Bracketstr, &dataget);
				expr[j - 1] = '_';
				expr[j] = barcketcount + '0';
				barckettemp[barcketcount++] = GetResult(&dataget);

				for (k = j + 1; k <= i - 1; k++)
					expr[k] = ' ';
			}
		}
	}

	for (i = 0; i < length; i++)
	{
		if (expr[i] == '_')
		{

			char strtemp[16] = "";
			sprintf(strtemp, "%.1f", barckettemp[expr[i++ + 1] - '0']);
			strcat(allstr, strtemp);
		}
		else
		{
			char temp[16] = "";
			sprintf(temp, "%c", expr[i]);
			strcat(allstr, temp);
			strcpy(temp, "");
		}
	}	

	GetStr(allstr, &alldate);
	
	return(GetResult(&alldate));

}



void CCalculatorDlg::int_16(int n) /*十进制转化为十六进制*/
{
	CString str1;
	int x;
	if ((n / 16) != 0) /*如果n大于等于16*/
		int_16(n / 16); /*把n除以16,进行递归调用*/
	x = n % 16; /*把n除以16的余数赋给x*/
	if (x >= 0 && x <= 9) /*如果x在0到9之间*/
	{
		str1.Format("%d", x);
		str_16 += str1;
	}
	else
		str_16 += char(x + 55); /*把x的值加55(利用ASCII码)再转化为字符型加在str_16上*/
}
/*************************************************字符串处理函数结束****************************************************/
/***********************************************************************************************************************/


程序运行结果



  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值