C++实现控制台计算器


前言

前言:本次使用VS2017 C++实现表达式的运算,支持阶乘,三角函数,反三角函数等函数,基本四则运算,乘法,取余数,取整等运算,另外还有计算平均数,方差,标准差等功能。


一、采用调度场算法直接运算

具体算法可以网上搜索,本次运算解决了前缀的正负运算,以及后缀的阶乘运算。多参数函数的运算以及嵌套,网上最多可扩展到单参数函数。由于采用了double类型,表达式精度可能会有影响,另外,表达式要完全准确,且要注意英文字母都要小写。

二、使用方法

1.函数介绍

函数说明如下:

函数或操作符功能与说明参数个数使用示例
pi常数π
e常数e或10ⁿ如2500可写成2.5e3
+加法或正号
-减法或负号
*乘法
/除法
^乘方
%取余数
\整除
!阶乘如5!
sqr(x)求根号1如sqr(2)
sin(x)求正弦1
cos(x)求余弦1
tan(x)求正切1
asin(x)求反正弦1
acos(x)求反余弦1
atan(x)求反正切1
sinh(x)求双曲正弦1
cosh(x)求双曲余弦1
tanh(x)求双曲正切1
asinh(x)求反双曲正弦1
acosh(x)求反双曲余弦1
atanh(x)求反双曲正切1
ln(x)求自然对数1
log(x)求以10为底的对数1
exp(x)求e的幂1
abs(x)求绝对值1
ceil(x)向下取整1
floor(x)向上取整1
int(x)取整1
round(x)四舍五入取整1
rad(x)度数转弧度1
deg(x)弧度转度数1
max(y,x)求两者的较大值2如max(1,2)
min(y,x)求两者的较小值2如min(1,2)
hypot(y,x)求直角三角形的斜边长2如hypot(3,4)
atan2(y,x)求y/x的辐角2如atan2(3,4)
avg(x1,x2,…)求平均数不定如avg(1,2)或avg(1,2,3)
var(x1,x2,…)求方差不定如var(1,2)或var(1,2,3)
stdev(x1,x2,…)求标准差不定如stdev(1,2)或stdev(1,2,3)

2.完整代码

代码如下(示例):

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <limits>
#include <iomanip>

#define pi 3.14159265358979323846
#define ee 2.7182818284590452354
double Eval(char *ex, int *Err);

int main()
{
	int Err1, s = 1;
	double result;
	char Input[999];
	char d;
	while (s) {
		std::cout << "请输入算术表达式" << std::endl;
		std::cin >> Input;
		result = Eval(Input, &Err1);
		if (Err1)
			std::cout << "输出" << std::setprecision(15)  << result  << std::endl;
		else
			std::cout << "输入错误!" << std::endl;
	sss:
		std::cout << "是否继续:Y/N" << std::endl;
		fflush(stdin);
		std::cin >> d;
		if (d == 'Y' || d == 'y')
			system("cls");
		else if (d == 'N' || d == 'n')
			s = 0;
		else {
			system("cls");
			goto sss;
		}
	}
	return (0);
}


struct P_N {
	double number;
	P_N *next;
};

struct P_F {
	char si;
	P_F *next;
};



int scmp(char s1, char s2) {
	switch (s1) {
	case '+':
	case '-':
		if (s2 == '+' || s2 == '-' || s2 == ',' || s2 == ')' || s2 == '$')
			return (1);
		else
			return (-1);

	case '*':
	case '/':
	case '\\':
	case '%':
	case '^':
	case '0':
	case '1':
		if (s2 == '+' || s2 == '-' || s2 == '*' || s2 == '/' || s2 == '%'
			|| s2 == '\\' || s2 == ',' || s2 == ')' || s2 == '$')
			return (1);
		else
			return (-1);

	case '!':
		if (s2 == '+' || s2 == '-' || s2 == '*' || s2 == '/' || s2 == '%'
			|| s2 == '\\' || s2 == '^' || s2 == '!' || s2 == ',' || s2 == ')'
			|| s2 == '$')
			return (1);
		else
			return (2);
	case '\0':
		return (2);
	case '$':
		if (s2 == ',' || s2 == ')')
			return (2);
		else if (s2 == '$')
			return (0);
		else
			return (-1);

	case ',':
		if (s2 == ')')
			return (3);
		else if (s2 == '$')
			return (2);
		else
			return (-1);

	case 'f':
	case 'g':
	case 'h':
	case 'E':
	case 'F':
	case 'G':
	case 'K':
		if (s2 == ')')
			return (0);
		else if (s2 == '$')
			return (2);
		else
			return (-1);

	default:
		if (s2 == ')')
			return (0);
		else if (s2 == ',' || s2 == '$')
			return (2);
		else
			return (-1);
	}
}

void cut(char **argmt, int n) {
	*argmt = *argmt + n;
}

double lib(char **argmt, int *argtest) {
	long double g;
	char c;
	char wa[3] = "\0";
	int df = 0;
	int dk = 0;
	c = **argmt;
	if (c == 'p') {
		strncpy_s(wa, *argmt, 2);
		if (strcmp(wa, "pi") == 0) {
			cut(argmt, 2);
			g = pi;
		}
		return (g);
	}
	if (c == 'e') {
		cut(argmt, 1);
		g = ee;
		c = **argmt;
		if ((c <= 57 && c >= 48) || c == '.')
			*argtest = 0;
		return (g);
	}
	if ((c > 57 || c < 48) && c != '.')
		*argtest = 0;
	g = atof(*argmt);
	if (c == '.') {
		cut(argmt, 1);
		df = 1;
		c = **argmt;
		if (c == 'e' || c == 'E')
			*argtest = 0;
	}
	while (c <= 57 && c >= 48) {
		cut(argmt, 1);
		c = **argmt;
		if (dk == 0)
			if (c == 'e' || c == 'E') {
				dk = 1;
				cut(argmt, 1);
				c = **argmt;
				if (c == '-' || c == '+') {
					cut(argmt, 1);
					c = **argmt;
					if (c > 57 || c < 48)
						*argtest = 0;
				}
				else if (c > 57 || c < 48)
					*argtest = 0;
			}
		if (df == 0 && dk == 0)
			if (c == '.') {
				cut(argmt, 1);
				df = 1;
				c = **argmt;
				if (c == 'e' || c == 'E') {
					dk = 1;
					cut(argmt, 1);
					c = **argmt;
					if (c == '-' || c == '+') {
						cut(argmt, 1);
						c = **argmt;
						if (c > 57 || c < 48)
							*argtest = 0;
					}
					else if (c > 57 || c < 48)
						*argtest = 0;
				}
			}
		if (df == 1 || dk == 1)
			if (c == '.')
				*argtest = 0;
		if (dk == 1)
			if (c == 'e' || c == 'E')
				*argtest = 0;
	}
	return (g);
}


void push_f(P_F ** argflag, int *argp_f, int *argtes, char cf) {
	P_F *p = new P_F;
	(*argp_f)++;
	p->si = cf;
	p->next = *argflag;
	*argflag = p;
	*argtes = 1;
}

char pop_f(P_F ** argflag, int *argp_f, int *argtest) {
	char c;
	P_F *p = *argflag;
	if (p != NULL) {
		(*argp_f)--;
		c = p->si;
		*argflag = (*argflag)->next;
		delete p;
		return (c);
	}
	else {
		*argtest = 0;
		return ('\0');
	}
}

void push_n(P_N ** argnum, int *argp_n, int *argtes, double cn) {
	P_N *p = new P_N;
	(*argp_n)++;
	p->number = cn;
	p->next = *argnum;
	*argnum = p;
	*argtes = 0;
}

double pop_n(P_N ** argnum, int *argp_n, int *argtest) {
	double c;
	P_N *p = *argnum;
	if (p != NULL) {
		(*argp_n)--;
		c = p->number;
		*argnum = (*argnum)->next;
		delete p;
		return (c);
	}
	else {
		*argtest = 0;
		return (0.0);
	}
}

char fd(char dw, char **argmt) {
	char wt[5] = "\0";
	char wd[4] = "\0";
	char wk[6] = "\0";
	char wa[7] = "\0";

	switch (dw) {
	case 's':
		strncpy_s(wt, *argmt, 4);
		strncpy_s(wk, *argmt, 5);
		strncpy_s(wa, *argmt, 6);
		if (strcmp(wt, "sin(") == 0) {
			cut(argmt, 4);
			return ('s');
		}
		else if (strcmp(wt, "sqr(") == 0) {
			cut(argmt, 4);
			return ('q');
		}
		else if (strcmp(wk, "sinh(") == 0) {
			cut(argmt, 5);
			return ('a');
		}
		else if (strcmp(wa, "stdev(") == 0) {
			cut(argmt, 6);
			return ('G');
		}
		else {
			return ('\0');
		}

	case 'c':
		strncpy_s(wt, *argmt, 4);
		strncpy_s(wk, *argmt, 5);
		if (strcmp(wt, "cos(") == 0) {
			cut(argmt, 4);
			return ('c');
		}
		else if (strcmp(wk, "cosh(") == 0) {
			cut(argmt, 5);
			return ('b');
		}
		else if (strcmp(wk, "ceil(") == 0) {
			cut(argmt, 5);
			return ('H');
		}
		else {
			return ('\0');
		}

	case 't':
		strncpy_s(wt, *argmt, 4);
		strncpy_s(wk, *argmt, 5);
		if (strcmp(wt, "tan(") == 0) {
			cut(argmt, 4);
			return ('t');
		}
		else if (strcmp(wk, "tanh(") == 0) {
			cut(argmt, 5);
			return ('d');
		}
		else {
			return ('\0');
		}


	case 'l':
		strncpy_s(wd, *argmt, 3);
		strncpy_s(wt, *argmt, 4);
		if (strcmp(wd, "ln(") == 0) {
			cut(argmt, 3);
			return ('l');
		}
		else if (strcmp(wt, "log(") == 0) {
			cut(argmt, 4);
			return ('n');
		}
		else {
			return ('\0');
		}

	case 'e':
		strncpy_s(wt, *argmt, 4);
		if (strcmp(wt, "exp(") == 0) {
			cut(argmt, 4);
			return ('e');
		}
		else {
			return ('\0');
		}

	case 'm':
		strncpy_s(wt, *argmt, 4);
		if (strcmp(wt, "max(") == 0) {
			cut(argmt, 4);
			return ('f');
		}
		else if (strcmp(wt, "min(") == 0) {
			cut(argmt, 4);
			return ('g');
		}
		else {
			return ('\0');
		}

	case 'h':
		strncpy_s(wa, *argmt, 6);
		if (strcmp(wa, "hypot(") == 0) {
			cut(argmt, 6);
			return ('h');
		}
		else {
			return ('\0');
		}

	case 'v':
		strncpy_s(wt, *argmt, 4);
		if (strcmp(wt, "var(") == 0) {
			cut(argmt, 4);
			return ('F');
		}
		else {
			return ('\0');
		}

	case 'f':
		strncpy_s(wa, *argmt, 6);
		if (strcmp(wa, "floor(") == 0) {
			cut(argmt, 6);
			return ('I');
		}
		else {
			return ('\0');
		}

	case 'i':
		strncpy_s(wt, *argmt, 4);
		if (strcmp(wt, "int(") == 0) {
			cut(argmt, 4);
			return ('J');
		}
		else {
			return ('\0');
		}

	case 'r':
		strncpy_s(wt, *argmt, 4);
		strncpy_s(wa, *argmt, 6);
		if (strcmp(wt, "rad(") == 0) {
			cut(argmt, 4);
			return ('i');
		}
		else if (strcmp(wa, "round(") == 0) {
			cut(argmt, 6);
			return ('D');
		}
		else {
			return ('\0');
		}

	case 'd':
		strncpy_s(wt, *argmt, 4);
		if (strcmp(wt, "deg(") == 0) {
			cut(argmt, 4);
			return ('j');
		}
		else {
			return ('\0');
		}

	case 'a':
		strncpy_s(wt, *argmt, 4);
		strncpy_s(wk, *argmt, 5);
		strncpy_s(wa, *argmt, 6);
		if (strcmp(wt, "abs(") == 0) {
			cut(argmt, 4);
			return ('u');
		}
		else if (strcmp(wt, "avg(") == 0) {
			cut(argmt, 4);
			return ('E');
		}
		else if (strcmp(wk, "asin(") == 0) {
			cut(argmt, 5);
			return ('v');
		}
		else if (strcmp(wk, "acos(") == 0) {
			cut(argmt, 5);
			return ('w');
		}
		else if (strcmp(wk, "atan(") == 0) {
			cut(argmt, 5);
			return ('x');
		}
		else if (strcmp(wa, "asinh(") == 0) {
			cut(argmt, 6);
			return ('A');
		}
		else if (strcmp(wa, "acosh(") == 0) {
			cut(argmt, 6);
			return ('B');
		}
		else if (strcmp(wa, "atanh(") == 0) {
			cut(argmt, 6);
			return ('C');
		}
		else if (strcmp(wa, "atan2(") == 0) {
			cut(argmt, 6);
			return ('K');
		}
		else {
			return ('\0');
		}

	default:
		return ('\0');
	}
}


char getn(char **argmt, int *argtrs, double *argnu, int *argtest, int *argtes) {
	char c;
	char sj;
	c = **argmt;
	*argnu = 0.0;
	*argtrs = 0;
	if (c == '*' || c == '/' || c == '(' || c == ')' || c == '^'
		|| c == '%' || c == '!' || c == '\\' || c == ',' || c == '$') {
		if (c == '(')
			if (*argtes == 0)
				*argtest = 0;
		if (c == '!')
			if (*argtes == 1)
				*argtest = 0;
		*argtrs = 1;
		cut(argmt, 1);
		return (c);
	}
	else if (c == '+' && *argtes) {
		*argtrs = 1;
		cut(argmt, 1);
		return ('0');
	}
	else if (c == '-' && *argtes) {
		*argtrs = 1;
		cut(argmt, 1);
		return ('1');
	}
	else if (c == '+' || c == '-') {
		*argtrs = 1;
		cut(argmt, 1);
		return (c);
	}
	else {
		sj = fd(c, argmt);
		if (sj != '\0') {
			if (*argtes == 0)
				*argtest = 0;
			*argtrs = 1;
			return (sj);
		}
		*argnu = lib(argmt, argtest);
		return ('\0');
	}
}

double max(double a, double b) {
	return fmax(a, b);
}

double min(double a, double b) {
	return fmin(a, b);
}

double avg(double *an, int l) {
	double tmp = 0;
	int i;
	for (i = 0; i < l; i++)
		tmp += *(an + i);
	return (tmp / l);
}

double var(double *an, int l) {
	double tmp = 0;
	double tmp2 = 0;
	int i;
	tmp2 = avg(an, l);
	for (i = 0; i < l; i++)
		tmp += (*(an + i) - tmp2) * (*(an + i) - tmp2);
	return (tmp / l);
}

double stdev(double *an, int l) {
	return (sqrt(var(an, l)));
}

double fint(double x) {
	if (x == x) {
		if (x >= 0)
			return (floor(x));
		else
			return (ceil(x));
	}
	else
		return (x);
}


double op(char mk, double dd) {
	switch (mk) {
	case 'A':
		return (asinh(dd));
	case 'B':
		return (acosh(dd));
	case 'C':
		return (atanh(dd));
	case 'D':
		return (round(dd));
	case 'a':
		return (sinh(dd));
	case 'b':
		return (cosh(dd));
	case 'd':
		return (tanh(dd));
	case 'e':
		return (exp(dd));
	case 'i':
		return (dd / 180 * pi);
	case 'j':
		return (dd / pi * 180);
	case 's':
		return (sin(dd));
	case 'c':
		return (cos(dd));
	case 't':
		return (tan(dd));
	case 'q':
		return (sqrt(dd));
	case 'l':
		return (log(dd));
	case 'n':
		return (log10(dd));
	case 'u':
		return (fabs(dd));
	case 'v':
		return (asin(dd));
	case 'w':
		return (acos(dd));
	case 'x':
		return (atan(dd));
	case '!':
		return (tgamma(dd + 1));
	case '1':
		return (-dd);
	case 'H':
		return (ceil(dd));
	case 'I':
		return (floor(dd));
	case 'J':
		return (fint(dd));
	default:
		return (dd);
	}
}



double fop(char mk, P_N ** argnum, int *argp_n, int mpa, int *argtest) {
	double a;
	double b;
	double *an;
	double ret;
	int i;
	switch (mk) {
	case 'f':
	{
		if (mpa == 1) {
			a = pop_n(argnum, argp_n, argtest);
			b = pop_n(argnum, argp_n, argtest);
			return (max(b, a));
		}
		else {
			*argtest = 0;
			return (0);
		}
	}

	case 'g':
	{
		if (mpa == 1) {
			a = pop_n(argnum, argp_n, argtest);
			b = pop_n(argnum, argp_n, argtest);
			return (min(b, a));
		}
		else {
			*argtest = 0;
			return (0);
		}
	}

	case 'h':
	{
		if (mpa == 1) {
			a = pop_n(argnum, argp_n, argtest);
			b = pop_n(argnum, argp_n, argtest);
			return (hypot(b, a));
		}
		else {
			*argtest = 0;
			return (0);
		}

	case 'K':
	{
		if (mpa == 1) {
			a = pop_n(argnum, argp_n, argtest);
			b = pop_n(argnum, argp_n, argtest);
			return (atan2(b, a));
		}
		else {
			*argtest = 0;
			return (0);
		}
	}


	case 'E':
	{
		an = new double[mpa + 1];
		for (i = 0; i < mpa + 1; i++)
			*(an + mpa - i) = pop_n(argnum, argp_n, argtest);
		ret = avg(an, mpa + 1);
		delete an;
		return (ret);
	}

	case 'F':
	{
		an = new double[mpa + 1];
		for (i = 0; i < mpa + 1; i++)
			*(an + mpa - i) = pop_n(argnum, argp_n, argtest);
		ret = var(an, mpa + 1);
		delete an;
		return (ret);
	}
	case 'G':
	{
		an = new double[mpa + 1];
		for (i = 0; i < mpa + 1; i++)
			*(an + mpa - i) = pop_n(argnum, argp_n, argtest);
		ret = stdev(an, mpa + 1);
		delete an;
		return (ret);
	}
	}

	default:
		*argtest = 0;
		return (0);
	}
}

double zhi(double d1, double d2, char v) {
	switch (v) {
	case '+':
		return (d1 + d2);
	case '-':
		return (d1 - d2);
	case '*':
		return (d1 * d2);
	case '/':
		return (d1 / d2);
	case '%':
		return fmod(d1, d2);
	case '\\':
		return fint(d1 / d2);
	default:
		return (pow(d1, d2));
	}
}

double Eval(char *ex, int *Err) {
	char *mt = NULL;
	int p_n = -1;
	int p_f = -1;
	P_N *num = NULL;
	P_F *flag = NULL;
	int tes = 1;
	double nu = 0.0;
	int trs = 0;
	int test = 1;
	int length = strlen(ex);
	char *exi = new char[length + 10];
	char sym;
	double a, b, retnum;
	int i, j;
	int mpa = 0;
	char sy;
	for (i = 0; i < length; i++) {
		exi[i] = *(ex + i);
		if (exi[i] == '$')
			test = 0;
	}

	exi[i] = '$';
	exi[i + 1] = '\0';
	mt = exi;
	push_f(&flag, &p_f, &tes, '$');
	sym = getn(&mt, &trs, &nu, &test, &tes);
	while ((sym != '$' || flag->si != '$') && test) {
		if (trs == 0) {
			if (tes == 0)
				test = 0;
			push_n(&num, &p_n, &tes, nu);
			sym = getn(&mt, &trs, &nu, &test, &tes);
		}
		else {
			j = scmp(flag->si, sym);
			if (j == -1) {
				push_f(&flag, &p_f, &tes, sym);
				if (sym == '!')
					tes = 0;
				sym = getn(&mt, &trs, &nu, &test, &tes);
			}
			else if (j == 0) {
				if (flag->si == 'f' || flag->si == 'g' || flag->si == 'h'
					|| flag->si == 'E' || flag->si == 'F' || flag->si == 'G'
					|| flag->si == 'K') {
					sy = pop_f(&flag, &p_f, &test);
					push_n(&num, &p_n, &tes, fop(sy, &num, &p_n, mpa, &test));
					mpa = 0;
				}
				else {
					sy = pop_f(&flag, &p_f, &test);
					a = pop_n(&num, &p_n, &test);
					push_n(&num, &p_n, &tes, op(sy, a));
				}
				sym = getn(&mt, &trs, &nu, &test, &tes);
			}
			else if (j == 1)
				if (flag->si == '0' || flag->si == '1' || flag->si == '!') {
					a = pop_n(&num, &p_n, &test);
					sy = pop_f(&flag, &p_f, &test);
					push_n(&num, &p_n, &tes, op(sy, a));
				}
				else {
					a = pop_n(&num, &p_n, &test);
					b = pop_n(&num, &p_n, &test);
					sy = pop_f(&flag, &p_f, &test);
					push_n(&num, &p_n, &tes, zhi(b, a, sy));
				}
			else if (j == 3) {
				mpa++;
				pop_f(&flag, &p_f, &test);
			}
			else
				test = 0;
		}
	}

	if (p_n == 0 && test == 1)
		retnum = num->number;
	else {
		test = 0;
		retnum = 0.0;
	}
	*Err = test;
	delete exi;
	while (p_f >= 0)
		pop_f(&flag, &p_f, &test);
	while (p_n >= 0)
		pop_n(&num, &p_n, &test);
	return (retnum);
}

总结

本次实现了使用C++完成对表达式的计算,是否有其他的问题可以说明,由于是四五年前写的代码,所以没有什么注释,也写的比较混乱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值