大一无聊,只学了c,没学数据结构之类的东西。所以就裸写了个C语言控制台的小计算器。
1、支持加减乘除、括号输入
2、支持整数、浮点数。
2、支持空格输入
3、支持括号前省略乘号
目前错误输入还有待完善,但功能绝对没问题。
没有涉及堆栈知识(没学)。
#include"stdio.h"
#include"windows.h"
#include"ctype.h"
#define N 200
int t2f = -1;//判断字符,用在输入
int end,testResult,doit;
int leftBracket,rightBracket;
double numEntered[N];
char operatorEnter[N],operatorCopy[N];
const char legalCharacter[9]={'\0','+','-','*','/','(',')','='};
const double max = 10E16;
int record_bracket[N]={0,0};/**记录原始式子中,记录一对括号的位置。
*下标为右括号位置。下标对应的成员为左括号位置*/
double calculateTwoNumbers(char c,double n1,double n2)
{
double r=0.0;
switch(c)
{
case'*':
r=n1*n2;
break;
case'/':
r=n1/n2;
break;
}
return r;
}
/**初始化各数组、变量*/
void initialize()
{
int i;
//默认输入的东西也包围在一个括号里
for(i=0;i<N;i++)
{
operatorEnter[i]='\0';
operatorCopy[i]='\0';
numEntered[i]=0; //字符数组初始化
record_bracket[i]=0;
}
operatorEnter[0]='(';
end = 0;
testResult = 0;
doit = 0;
leftBracket = 0;
rightBracket = 0;
printf("\n 请输入计算式:\n\t");
}
//输入函数,输入正常完成返回一个数组长度的正值,停止字符返回-1,超规格返回-2
int input()
{
int i,j;
char c;
for(i=1;i<N;i++)
{
c = getchar();
if(c != '\n')
{
if(isdigit(c)!= 0)
{
ungetc(c,stdin);//将c退回标准输入流中
scanf("%lf",&numEntered[i]);
}
else
{
operatorEnter[i] = c;
}
}
else
break;
if(operatorEnter[i]=='#') //停止字符的检查;
return -1;
if(i+1 >= N)
{
while(getchar()!='\n') ;//超规格输入的返回提示
return -2;
}
if((operatorEnter[i]=='='))
{
while(j=getchar()!='\n')
if(t2f==-1)
t2f = j;//判断等号后有无字符
break;
}
}
return i;
}
//检查合法性的函数,返回0就含failure,返回1就pass,
int testLegalityOfEnteredChar()
{
int i, j;
for(i=0;i<end;i++)
{
for(j=0;j<9;j++)
{
if(operatorEnter[i]==legalCharacter[j]){break;}
}
if(j>=8)
{
return 0;
}
else
{
operatorCopy[i]=operatorEnter[i];
}
}
return 1;
}
//删除空格
void deleteSpace()
{
int i;int j;
for(i = end; i >= 0;i--)
{
if(operatorEnter[i] == 32)
{
for(j = i;j < end;j++)
{
operatorEnter[j] = operatorEnter[j+1];
numEntered[j] = numEntered[j+1];
}
end--;
}
}
}
//添加省略掉的乘号
void addMultiplySign()
{
for(int i =end-1;i > 0;i--)
{
//如果numEntered[i]存有输入的数,那么operatorEnter[i]= '\0';
if((operatorEnter[i]=='\0'&&operatorEnter[i-1]==')')||
(operatorEnter[i]=='('&&operatorEnter[i-1]=='\0')||
(operatorEnter[i]=='('&&operatorEnter[i-1]==')'))
{
for(int j = end ; j >= i ; j--)
{
operatorEnter[j+1]=operatorEnter[j];
numEntered[j+1] = numEntered[j];
numEntered[j] = 0;
}
operatorEnter[i] = '*';
end++;
}
}
}
/**处理空格,和数字与括号间无符号的更正处理情况,给它添加乘号。*/
void editFormat()
{
deleteSpace();
addMultiplySign();
}
//打印数组
void printArrays(char operatorEnter[N],double numEntered[N])
{
for(int i = 0;i <= end;i++)
{
printf("operatorEnter[%d] = %c @%d\n",i,operatorEnter[i],operatorEnter[i]);
printf(" numEntered[%d] =%lf \n",i,numEntered[i]);
printf("-------------\n");
}
}
void findRightBrackets()
{
for(int a=leftBracket;a<=rightBracket;a++)//从左括号的位置向右检测右括号
{
if(operatorEnter[a]==')')
{ //此步条件不成立则rightBracket=end
rightBracket=a;
record_bracket[a]=leftBracket; //记录右括号对应的左括号位置
operatorEnter[a]='\0'; //完成记录后消去当前检测到的括号
break;
}
} /**当前括号位置为operatorEnter[leftBracket],operatorEnter[rightBracket] */
}
//计算乘除法,若除数为零返回-1.
int MultiplicationAndDivision()
{
/**从右到左、检测括号里乘除号*/
for(int b=rightBracket;b>=leftBracket;b--)
{
if(operatorEnter[b]=='*'||operatorEnter[b]=='/')
{
if(operatorEnter[b]=='/'&&numEntered[b+1]==0)
{
return -1;
}
/*测试用*///printf("\n当前符号位置为位置为%d\n",b);
if(operatorCopy[b-1]==')')
{//这里是为了考虑三个以上括号间乘法的问题
int d=record_bracket[b-1];
numEntered[d]=calculateTwoNumbers(operatorEnter[b],numEntered[d],numEntered[b+1]);
numEntered[b+1]=0; // printf("\n此次%c运算结果为%lf\n",operatorEnter[b],numEntered[d]);//测试用*/
operatorEnter[b]='\0'; //消去乘除号
}
else
{
numEntered[b-1]=calculateTwoNumbers(operatorEnter[b],numEntered[b-1],numEntered[b+1]);
numEntered[b+1]=0; //printf("\n此次%c运算结果为%lf\n",operatorEnter[b],numEntered[b-1]);
operatorEnter[b]='\0'; //消去乘除号
}
}
}
return 1;
}
//减法
void subtraction()
{
for(int c=rightBracket;c>=leftBracket+1;c--)
{
if(operatorEnter[c]=='-')
{ // /*测试用*/printf("减号位于ch[%d]",c);
numEntered[c+1]=(-1)*numEntered[c+1];
operatorEnter[c]='\0';
}
}
}
//括号内所有数的和
void sum()
{
for(int a=leftBracket;a<=rightBracket;a++)
{
numEntered[leftBracket]+=numEntered[a];
numEntered[a]=0.0; /*测试用*//*printf("\nn[%d]===%lf\n",a,numEntered[a]);*/
}
}
//分析计算所输入式子的函数,结果存于numEntered[0],除数为0返回0;
int calculate(){
/*
从右到左检测运算符号,
每次运算结果存于numEntered[]左括号对应位置。
*/
int j,temp=0;
for(int i=end;i>=0;i--)//
{
rightBracket=end; //初始化右括号的位置在最后
if(operatorEnter[i]=='(')
{
leftBracket=i;
operatorEnter[i]='\0';//记录后消去括号
findRightBrackets();
temp = MultiplicationAndDivision();//计算括号内的所有乘除法
if(temp<0) return 0;//除数为0
subtraction();//减法
sum();//括号内容总和
}
}
return 1;
}
//信息提示框
void messege_Box(int n)
{
switch(n)
{
case 1:
break;
case 2:
MessageBox( NULL, "您的输入含有非法字符,请检查", "错误", MB_OK | MB_ICONINFORMATION );
printf(" 错误:您的输入含有非法字符,请检查!\n");
break;
case 3:
MessageBox( NULL, "抱歉,您所输入除数无意义", "错误!", MB_OK | MB_ICONINFORMATION );
printf(" 错误:抱歉,您所输入除数无意义。\n");
break;
case 4:
MessageBox( NULL, "十分抱歉,错误原因未知,\n联系QQ1462468257\n在此再次向您致以诚挚的抱歉\n", "error", 0 );
break;
case 5:
MessageBox( NULL, "该输入数据过大,不能保证其计算结果的正确性", "注意!", MB_OK | MB_ICONINFORMATION );
printf(" 注意:该输入数据过大,不能保证其计算结果的正确性.\n");
break;
case 6:
MessageBox( NULL, "输入不能超过200个字符\n请重新输入", "警告!", MB_OK | MB_ICONINFORMATION );
printf(" 警告:输入不能超过200个字符!\n请重新输入!");
}
}
void printTitle()
{
printf(" ---------------四则运算计算器--------------\t\n"
"\n 注:\t1.所有符号输入必须为英文\t\n\t2.等于号回车键结束输入\t\n"
"\t3.输入“#”回车结束运行\n"
"\n -------------------------------------------\n");
}
//无聊玩玩,这个没啥用
void endProgram(void)
{
int i;
for(i=1;i<15;i=i+3)
{
printf(".");
Sleep(i*100);
}
printf("程序结束\n");
Sleep(500);
}
int main(){
printTitle();
while(1){
initialize();//初始化
end=input();//输入
if(end == -1)
{
endProgram();
break;
}
else if(end == -2)
{
messege_Box(6);
continue;
}
editFormat();//修正输入格式
//printArrays(operatorEnter,numEntered);
testResult=testLegalityOfEnteredChar();//检查输入合法性
if(testResult!=1)
{
messege_Box(2);
continue;
}
doit=calculate();//计算
if(doit==1)//输出部分
{
printf("\t--------\n 结果为\t%lf\n",numEntered[0]);
if(t2f != -1)
{
printf("注意:您的输入等号后不为空,该计算结果仅为等号前式子的计算值\n");
t2f = -1;
}
}
else if(doit==0)
{
messege_Box(3);
continue;
}
else
{
messege_Box(4);
break;
}
if(numEntered[0] > max)
messege_Box(5);
printf("\n ----------------LITTLEKIDS8----------------\n\n");
}
return 0;
}