大一暑假实训项目总结(简易计算器C++版)
因为疫情原因,我们这一届的实训就被放在了暑假的尾声进行,也就是线上进行。也是因为快开学了,便于开学后进行项目交流和答辩。
我们组还是和大一上学期一样,那五个老同志。只不过项目不一样了,上次是学生成绩管理系统,而这次是简易计算器的实现。
我们这次的实训项目也确实比上次难一点,因为我们是从网上找到代码,但是又跟它有点不同,我们在它的基础上增加了一个比较的功能,所以我们组大部分时间都在想如何将它实现,确实挺头疼的。
我们这个计算器项目,顾名思义就是实现计算器的相关功能,是用C++语言实现的。当然他跟C语言也没有很大的区别,只要将头文件和输入输出方式更换一下就可以换成C语言版本的。它的功能主要包括加、减、乘、除、乘方、立方、开根号、计算sinx、cosx、tanx等等,还有一个就是我们组一直想实现的功能就是比较功能。
先展示一下运行的图片:
1 简陋的登陆界面
2 功能界面
3 计算功能示例图片
4 判断功能示例图片
5 退出界面
最后上代码,这是的这段时间的成果啊,说多了都是泪,代码中也有注释,可以帮助阅读。
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;
const double pi = 3.14159265; //&&pi = acos(-1)
const double e = 2.718281828459;
const int SIZE = 1000;
typedef struct node//为了处理符号而建立的链表(如: 1+(-2))
{
char data;
node *next;
}node;
typedef struct stack_num//存储 数 的栈
{
double *top;
double *base;
}stack_num;
typedef struct stack_char//存储 运算符号 的栈
{
char *top;
char *base;
}stack_char;
stack_num S_num;//定义
stack_char S_char;//定义
char fu[18] = {'\n', ')', '+', '-', '*', '/', '%', '^',
'Q', 'L', 'C', 'S', 'T', 'c', 's', 't', '('};
int compare[1000];//表现出各运算符号的优先级
double shu[1000];//存储 "数" 的数组
double dai_result;//运算的结果,是为了处理 M 运算(简介函数里有M的定义)
int biao = 0;//和dia_result 一样,为了处理 M 运算
string line;//输入的所要计算的表达式 //&&char line[SIZE];//输入的所要计算的表达式
int judge;//用于判断是算术表达式还是关系表达式
int cnt;
//初始化
void init()
{
compare[fu[0]] = -2;//用数字的大小表现出符号的优先级
compare[fu[1]] = -1;
compare[fu[2]] = 2;
compare[fu[3]] = 2;
compare[fu[4]] = 4;
compare[fu[5]] = 4;
compare[fu[6]] = 4;
compare[fu[7]] = 5;
for(int i = 8; i <= 15; i++)
compare[fu[i]] = 6;
compare[fu[16]] = 7;
S_num.base = (double*)malloc(sizeof(double)*SIZE);//为栈开辟空间
S_char.base = (char*)malloc(sizeof(char)*SIZE);//同上
S_num.top = S_num.base;
S_char.top = S_char.base;
}
//数字进栈
void push_num(double n)
{
* ++S_num.top = n;
}
//运算符号进栈
void push_char(char c)
{
* ++S_char.top = c;
}
//数字出栈
double pop_num()
{
double m = *S_num.top;
S_num.top--;
return m;
}
//运算符号出栈
char pop_char()
{
char cc = *S_char.top;
S_char.top--;
return cc;
}
//得到运算符号的栈中最顶端的运算符号
char get_top_char()
{
return *S_char.top;
}
//对两个数计算(含是双目运算符:如 *, / 等等)
double operate(double y, char c, double x)
{
double r;
if(c == '-')
r = x - y;
else if(c == '+')
r = x + y;
else if(c == '/' && y != 0)
r = x / y;
else if(c == '*')
r = x * y;
else if(c == '^')
{
r = 1;
for(int i = 1; i <= y; i++)
r *= x;
}
else if(c == '%')
{
int r0 = (int)x % (int)y;
r = double(r0);
}
return r;
}
//对一个数运算(含单目运算符:如log(L), sin(S) 等等)
double operate_one(double one, char cc)
{
double r;
if(cc == 'Q')
r = sqrt(one);
else if(cc == 'C')
r = cos(one);
else if(cc == 'S')
r = sin(one);
else if(cc == 'T')
r = tan(one);
else if(cc == 'c')
r = acos(one);
else if(cc == 's')
r = asin(one);
else if(cc == 't')
r = atan(one);
return r;
}
//求对数的值
double operate_L(double a, double b, char dian)
{
double r = log(b) / log(a);
return r;
}
//对整个表达式的计算
double compute()
{
char c;//表示运算符号
int p = 0;//用于shu[++p], 先初始化
int i, j;
init();//进行初始化
push_char('\n');
line[line.size()] = '\n';
line[line.size()+1] = '\0';
if(biao)
push_num(dai_result);//把运算的结果先进栈, 在这个结果的基础上继续进行运算
biao = 0;
for(i = 0; line[i] != '\0';)//把表达式中的数字字符串转化成可计算的数字
{
int flag = 0;
int flag1 = 1;//标记是否是运算符号
// int flag2 = 1;//标记是否出现'_';
double h = 0;
int ge;//位数
int biao_dian = 0;//是否是小数的类型
while(1)
{
flag1 = 1;
for(j = 0; j <= 16; j++)
{
if(line[i] == fu[j])
{
flag1 = 0;
break;
}
}
if(line[i] == '_')
{
break;
}
if(line[i] == '.')
{
i++;
ge = 0;
biao_dian = 1;
}
if(line[i] == 'P')
{
shu[++p] = pi;
i++;
break;
}
if(line[i] == 'E')
{
shu[++p] = e;
i++;
break;
}
if(flag1)
{
h = h * 10 + (line[i] - '0');
flag = 1;
i++;
if(biao_dian)
ge++;
}
else
break;
}
if(flag)
{
if(biao_dian)
{
int r = 1;
for(int k = 1; k <= ge; k++)
r *= 10;
h /= r;
}
shu[++p] = h;//把转化而来的数字存于数组
}
if(line[i] == '+')
shu[++p] = -1;
else if(line[i] == '-')
shu[++p] = -2;
else if(line[i] == '*')
shu[++p] = -3;
else if(line[i] == '/')
shu[++p] = -4;
else if(line[i] == '%')
shu[++p] = -5;
else if(line[i] == '^')
shu[++p] = -6;
else if(line[i] == 'Q')
shu[++p] = -7;
else if(line[i] == 'L')
shu[++p] = -8;
else if(line[i] == 'C')
shu[++p] = -9;
else if(line[i] == 'S')
shu[++p] = -10;
else if(line[i] == 'T')
shu[++p] = -11;
else if(line[i] == 'c')
shu[++p] = -12;
else if(line[i] == 's')
shu[++p] = -13;
else if(line[i] == 't')
shu[++p] = -14;
else if(line[i] == '(')
shu[++p] = -15;
else if(line[i] == ')')
shu[++p] = -16;
else if(line[i] == '\n')
shu[++p] = -17;
i++;
}
i = 1;
while(shu[i] != -17 || get_top_char() != '\n')
{
double m = shu[i];
if(m >= 0)
{
push_num(m);
i++;
}
else
{
if(m == -1)
c = '+';
else if(m == -2)
c = '-';
else if(m == -3)
c = '*';
else if(m == -4)
c = '/';
else if(m == -5)
c = '%';
else if(m == -6)
c = '^';
else if(m == -7)
c = 'Q';
else if(m == -8)
c = 'L';
else if(m == -9)
c = 'C';
else if(m == -10)
c = 'S';
else if(m == -11)
c = 'T';
else if(m == -12)
c = 'c';
else if(m == -13)
c = 's';
else if(m == -14)
c = 't';
else if(m == -15)
c = '(';
else if(m == -16)
c = ')';
else if(m == -17)
c = '\n';
char ch = get_top_char();//得到最顶端运算符号
if(compare[ch] < compare[c])//运算符号级别的比较
{
push_char(c);
i++;
}
else if(ch == '(' && c == ')')
{
pop_char();
i++;
}
else if(compare[ch] >= compare[c] && ch != '(' && ch != '\n')
{
if(ch == 'Q' || ch == 'C' || ch == 'S'|| ch == 'T'
|| ch == 'c' || ch == 's' || ch == 't')
{
double one = pop_num();
char dian = pop_char();
push_num(operate_one(one, dian));
}
else if(ch == 'L')
{
double one_L = pop_num();
double two_L = pop_num();
char dian = pop_char();
push_num(operate_L(two_L, one_L, dian));
}
else
{
double x = pop_num();
double y = pop_num();
char dian = pop_char();
if(dian == '/' && x == 0)//判断是否除了"零"
{
cout<<"由于您除了零,结果将是错误的"<<endl;
}
push_num(operate(x, dian, y));//把进行一次计算的结果入栈
}
}
else
{
push_char(c);
i++;
}
}
}
double result = pop_num();//得到结果
return result;
}
//检查表达式括号是否匹配
int check_kuohao()
{
int i, f = 0;
int kuo[SIZE], key = 1;
memset(kuo, 0, sizeof(kuo));
for(i = 0; line[i] != '\0'; i++)
{
if(line[i] == '(')
kuo[++f] = 1;
else if(line[i] == ')')
{
if(kuo[f] == 1)
{
kuo[f] = 0;
f--;
}
else
{
key = 0;
break;
}
}
}
if(key && f == 0)
return 1;
else
return 0;
}
//检查运算符号是否合法(如: 1 +* 4)
int check_char()
{
int i, ge;
for(i = 0; line[i] != '\0'; )
{
ge = 0;
while(line[i] == '+' || line[i] == '-' || line[i] == '*'
|| line[i] == '/' || line[i] == '%' || line[i] == '^'
|| line[i] == 'Q' || line[i] == 'L' || line[i] == 'S'
|| line[i] == 'C' || line[i] == 'T' || line[i] == 's'
|| line[i] == 'c' || line[i] == 't')
{
ge++;
i++;
}
i++;
}
if(ge >= 3)
return 0;
else
return 1;
}
//输出结果
void output(double result)
{
printf("所得结果是: ");
cout<<result<<endl;
}
//检查表达式是否合法
double check()
{
void introduce();
char cc;//决定计算器按哪种功能进行计算
double result;//结果
void input();//定义
if( check_kuohao() && check_char() )//看是否合法, 合法则计算
{
result = compute();
return result;
}
else//不合法,分两种不合法
{
if(check_kuohao() == 0 && check_char() == 1)
{
cout<<"您所输入的表达式括号不匹配, 请重新输入:"<<endl;
input();//输入表达式
}
else
{
cout<<"您所输入的表达式不合法, 请重新输入:"<<endl;
input();//输入表达式
}
}
}
//处理负号
void tackle_fuhao()
{
node *root, *head, *p, *q, *p1;
root = head = new node;
head->next = NULL;
int i;
for(i = 0; line[i] != '\0'; i++)//建立链表
{
p = new node;
p->data = line[i];
p->next = head->next;
head->next = p;
head = p;
}
// delete p;
q = (node*)malloc(sizeof(node));
head = root;
if(root->next->data == '+' || root->next->data == '-')//处理第一个字符
{
p = new node;
p->data = '0';
p->next = head->next;
head->next = p;
}
if(root->next != NULL)
{
for(q = root->next; q; q = q->next)
{
if(q->data == '(' && (q->next->data == '-' || q->next->data == '+'))
{
p = new node;
p->data = '0';
p->next = q->next;
q->next = p;
}
}
}
// delete q;
p1 = new node;
int qi = -1;
for(p1 = root->next; p1; p1 = p1->next)
{
line[++qi] = p1->data;
}
line[++qi] = '\0';
}
//输入
void input()
{
void introduce();
cin>>judge;
printf("请输入表达式:");
cin>>line;
if(judge==1){
cnt=0;
if(biao == 0)
tackle_fuhao();//处理负号
printf("所得结果:");
cout<<check()<<endl;//检查表达式是否合法
}
if(judge==2){
cnt=1;
int p=0,q=0,t=0,c=0,w;//w为1,2,3,4,5,6分别代表">","<","==","!=",">=","<="
string line1,line2;
double result1,result2;
for(int i=0;i<line.size();i++){
if(!t){
if(line[i]=='>'&&line[i+1]!='='){
t=1;
c=1;
w=1;
i++;
}
if(line[i]=='<'&&line[i+1]!='='){
t=1;
c=1;
w=2;
i++;
}
if(line[i]=='='&&line[i+1]=='='){
t=1;
c=1;
w=3;
i+=2;
}
if(line[i]=='!'&&line[i+1]=='='){
t=1;
c=1;
w=4;
i+=2;
}
if(line[i]=='>'&&line[i+1]=='='){
t=1;
c=1;
w=5;
i+=2;
}
if(line[i]=='<'&&line[i+1]=='='){
t=1;
c=1;
w=6;
i+=2;
}
}
if(!c)
line1+=line[i];
else
line2+=line[i];
}
line=line1;
if(biao == 0)
tackle_fuhao();//处理负号
result1=check();//检查表达式是否合法
line=line2;
if(biao == 0)
tackle_fuhao();//处理负号
result2=check();//检查表达式是否合法
printf("所得结果:");
if(w==1&&result1>result2)
printf("YES\n");
else if(w==2&&result1<result2)
printf("YES\n");
else if(w==3&&result1==result2)
printf("YES\n");
else if(w==4&&result1!=result2)
printf("YES\n");
else if(w==5&&result1>=result2)
printf("YES\n");
else if(w==6&&result1<=result2)
printf("YES\n");
else
printf("NO\n");
}
char cc;
cout<<"输入一个字符'D'或'F',决定是否继续:"<<endl;
while(cin>>cc){
if(cc=='D'){
system("cls");
introduce();
cout<<"计算机已清零!"<<endl<<"1.计算算术表达式"<<endl<<"2.判断关系表达式"<<endl;
cout<<"请输入:";
input();
break;
}
else if(cc=='F'){
system("cls");
cout<<"计算机关闭,谢谢使用!"<<endl;
break;
}
}
}
//对计算器的符号功能的简要介绍
void introduce()
{
cout<<"\t计算器简要介绍"<<endl;
cout<<"\t __________________________________________________________"<<endl;
cout<<"\t| |"<<endl;
cout<<"\t|C(cos) S(sin) T(tan) c(arccos) s(arcsin) |"<<endl;
cout<<"\t|7 8 9 / on t(arctan)|"<<endl;
cout<<"\t|4 5 6 * % L(log) |"<<endl;
cout<<"\t|1 2 3 - F(off) Q(sqrt) |"<<endl;
cout<<"\t|0 . + ^(乘方) Enter(=) |"<<endl;
cout<<"\t|__________________________________________________________|"<<endl<<endl;;
cout<<"\t对于对数输入 L2_5 表示以2为底5的对数"<<endl;
//cout<<"M(在前面结果的基础上继续计算,如:上次结果为10,现输入+10.5*2)"<<endl;
cout<<"\t D (清零并继续输入)"<<endl;
cout<<"\t F (计算机关闭)"<<endl;
cout<<"\t输入 P 就代表输入圆周率, 输入 E 代表输入自然对数"<<endl<<endl;
}
//界面
void print()
{
system("color F7"); //设置默认控制台前景背景色 字体颜色(浅红)
cout<<" 欢迎使用本计算器"<<endl;
cout<<"输入一个字符串 on, 计算器开始启动"<<endl;
}
//是否启动计算器
void if_start()
{
string start;
print();
system("color FC");
while(cin>>start)
{
if(start != "on")
{
cout<<"您所输入的字符无效, 请按照介绍的继续输入:"<<endl;
continue;
}
else
break;
}
if(start == "on")
{
system("color F5"); //设置默认控制台前景背景色 字体颜色(紫)
system("cls"); //清屏函数
}
introduce();//对计算器的简要介绍
cout<<"现在,请输入您所要计算的算术表达式或判断的关系表达式"<<endl;
cout<<"1.计算算术表达式"<<endl<<"2.判断关系表达式"<<endl;
cout<<"请输入:";
input();
}
//主函数
int main()
{
if_start();//调用是否启动计算器函数
return 0;
}