您的位置:首页 > 编程语言 > C语言/C++

C语言:(旧)用字符串自由输入计算的计算器(加减乘除)

2017-07-28 21:33 459 查看
小学期课里老师曾让写一个能够自由输入并计算的计算器,例如:3-5+2,计算结果为0 第一次尝试不断修改字符串来计算,但是发现十分容易出错

第二次改用读入变量和运算符的方法来计算结果,没学过数据结构,过程略微复杂,目前没发现计算错误,欢迎提出错误~o( ̄▽ ̄)o

暂不支持输入负数和带()的计算

UPDATE:支持了小数

UPDATE:修正了被除数是小数读取错误的问题,保留小数位数增加

UPDATE:加入了死循环,优化了在Linux终端的体验

存储模式图解:



已测试数据:
数据                      结果
5+5                          10.000
5+5*2                        15.000
5+5/2                         7.500
5+5*2+4/8                    15.500
2*2*2+6/3+7-5                12.000
6-4+5*6                      32.000
20+10*5*2+10/5*6            132.000
6-2*2                         2.000
10-2*5/2                      5.000
56+2-44-6/3*5-7+10*2/4        2.000
6/40*3.1-100+799/3          166.798
330/99*10+90*3.2-20/8.2     318.894
4.4/2.2                       2.000


代码如下:

#include<stdio.h>
#include<stdlib.h>
#define dataNums 300

struct calculator
{//以运算符为中心,存储左右两边的值
double leftData;
char operators;
double rightData;
};
int *Book;//用于记录废弃的结构体变量,大小由运算符个数决定
int getNumbersOfoperators(char *string)
{//数出运算符的个数,以此申请内存
int i=0,count=0;
while (string[i] != '\0')
{
if (string[i] == '+' || string[i] == '-' || string[i] == '*' || string[i] == '/')
++count;

++i;
}
return count;
}
double StringToDouble(char *string,int hasDot)
{
int i = 0;
double num = 0;
double times = 1;

if (hasDot == 1)
{
while (string[i] != '.')
{
++i;
}
}
else
{
while (string[i] != '\0')
{
++i;
}
}
--i;
while (string[i] >= '0'&&string[i] <= '9')
{
num += (string[i] - 48)*times;
times *= 10;
--i;
}
if (hasDot == 1)
{
times = 0.1;
i = 0;
while (string[i] != '.')
{
++i;
}
++i;
while (string[i] != '\0')
{
num += (string[i] - 48)*times;
times /= 10;
++i;
}
}

return num;
}
double getFrontNumber(int calplace, char *string)
{//找到运算符后读取其前一位数字
int i = calplace - 1;
int j = 0;
int hasDot = 0;
char tempNum[50];

while (string[i] >= 48 && string[i] <= 57 || string[i] == '.')
--i;
++i;
for (j = 0; string[i] >= 48 && string[i] <= 57 ||string[i]=='.'; j++,i++)
{
if (string[i] == '.')
{
hasDot += 1;
if (hasDot > 1)
{
puts("Data error!");
d271

system("pause");
exit(0);
}
}
tempNum[j] = string[i];
}
tempNum[j] = '\0';

return StringToDouble(tempNum, hasDot);
}
double getAfterNumber(int calplace, char *string)
{//读取其后一位数字
int i = calplace + 1;
int j;
char tempNum[50];
int hasDot = 0;

for (j = 0; string[i] >= 48 && string[i] <= 57 || string[i] == '.'; j++, i++)
{
if (string[i] == '.')
{
hasDot += 1;
if (hasDot > 1)
{
puts("Data error!");
system("pause");
exit(0);
}
}
tempNum[j] = string[i];
}
tempNum[j] = '\0';

return StringToDouble(tempNum, hasDot);
}
struct calculator *getData(char *string,int pairSize)
{//把输入字符串里的数字存入申请的结构体里,例如2+5*2,存为2 + 5, 5 * 2
struct calculator *pairNums;
int i = 0;
int j = 0;

pairNums = (struct calculator *)calloc(pairSize, sizeof(struct calculator));//申请内存
Book=(int *)calloc(pairSize,sizeof(int));//申请记录废弃变量的数组

for (i = 0; string[i] != '\0'; i++)
{
if (string[i] == '+' || string[i] == '-' || string[i] == '*' || string[i] == '/')
{//每个运算符左右两侧都有值,找出并存入结构体变量里
pairNums[j].operators = string[i];

pairNums[j].leftData = getFrontNumber(i, string);
pairNums[j].rightData = getAfterNumber(i, string);

++j;
}
}
return pairNums;
}
float getResult(struct calculator *pairNums,int pairSize)
{//计算并返回最终结果
double tempResult=0;
double temp;//单次计算结果
int i;
int j;
int flag=0;//记录是否需要更改前后结构体的值
int setZero=0;//单次结果是否归零

for(i = 0;i<pairSize;i++)//优先计算*/有关的数组
{
temp=0;
if(pairNums[i].operators=='*')
{
flag=1;
temp= pairNums[i].leftData *1.0* pairNums[i].rightData;
}
if(pairNums[i].operators=='/')
{
flag=1;
temp= pairNums[i].leftData*1.0/pairNums[i].rightData;
}

if(flag==1)//每次/*计算后需要改变前后数组的变量值
{
flag=0;//归零
if(i-1!=-1)//改变前一个数组的值,条件:非首位
{
j=i-1;
while(Book[j]==1)//找到最近一个未被废弃的数组
{
--j;
}
if(pairNums[j].operators=='+')
{
pairNums[j].rightData=0;
}
else if(pairNums[j].operators=='-')
{
pairNums[j].rightData=temp; //+和-的操作不同
Book[i]=1;//给出i位置的计算结果并赋给前一个未废弃且带'-'号的数组
setZero=1;//临时的计算结果temp归零为真
}

}
if(i+1!=pairSize)//改变后一个数组的left值,条件:非末位
{
j=i+1;
while(Book[j]==1)
{
++j;
}
if(pairNums[j].operators!='*' && pairNums[j].operators!='/')
{
pairNums[j].leftData=0;//将下一个数组(非*/计算)的leftdata归零
}
else
{
pairNums[j].leftData=temp;//如果为*/计算,则赋予temp计算内容
Book[i]=1;//废弃当前数组
setZero=1;//单次计算结果归零
}
}

}
if(setZero==1)//是否需要归零当前数组单次计算的结果
{
setZero=0;
temp=0;
}
tempResult+=temp;//将单次的计算结果汇入总结果
}
for(i = 0;i<pairSize;i++)//计算+-运算
{
if(pairNums[i].operators=='+')
{
tempResult += pairNums[i].leftData+pairNums[i].rightData;
flag=1;
}
if(pairNums[i].operators=='-')
{
tempResult += pairNums[i].leftData-pairNums[i].rightData;
flag=1;
}
if(flag==1)
{
flag=0;

if(i+1!=pairSize)
{
if(pairNums[i+1].operators=='+' || pairNums[i+1].operators=='-')
{
pairNums[i+1].leftData=0;
}
}
}

}
return tempResult;//返回计算结果
}
int main()
{
float result;
struct calculator *pairNums;
char inputData[dataNums];
int count_Calculators = 0;//记录运算符个数
puts("input your formula and  'q' to quit!");
while(1)
{
scanf("%s",inputData);//输入字符串(计算式)
if(inputData[0]=='q')//唯一退出出口
{
free(Book);
free(pairNums);
return 0;
}

count_Calculators = getNumbersOfoperators(inputData);//得到运算符个数
pairNums = getData(inputData,count_Calculators);//将字符串中的数组两两一组汇入结构体数组里
result=getResult(pairNums,count_Calculators);//计算结果

printf("Result=%.6lf\n",result);

free(Book);
free(pairNums);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐