C语言:(旧)用字符串自由输入计算的计算器(加减乘除)
2017-07-28 21:33
459 查看
小学期课里老师曾让写一个能够自由输入并计算的计算器,例如:3-5+2,计算结果为0 第一次尝试不断修改字符串来计算,但是发现十分容易出错
第二次改用读入变量和运算符的方法来计算结果,没学过数据结构,过程略微复杂,目前没发现计算错误,欢迎提出错误~o( ̄▽ ̄)o
!暂不支持输入负数和带()的计算
UPDATE:支持了小数
UPDATE:修正了被除数是小数读取错误的问题,保留小数位数增加
UPDATE:加入了死循环,优化了在Linux终端的体验
存储模式图解:
代码如下:
第二次改用读入变量和运算符的方法来计算结果,没学过数据结构,过程略微复杂,目前没发现计算错误,欢迎提出错误~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); } }
相关文章推荐
- C语言 - 自创题目:字符串输入的计算器(加减乘除计算器)
- 2013年9月华为成都笔试题 输入字符串计算数值(c语言)
- 输入一串字符串形如(2*(1+3)+8)/4 如何使用程序计算出结果 字符串输入计算器
- c语言初学--计算字符串中数字的最大长度并提取 以及输入两个子串 提取分别以这为开头和结尾的字符串
- C语言——计算输入的字符串的长度
- C语言实现输入字符串计算单词个数
- <C语言>实现简单的计算器(循环输入,加减乘除法可选)
- C语言:分别输入两段字符串,并找出其中的最大公共字符串
- 输入一个字符串,计算字符串中子串出现的次数
- C语言:在字符串中找出第一个只出现一次的字符。如输入“abaccdeff”,则输出'b'
- c语言中要输入一个字符串时,必须先初始化
- C语言:将输入的字符串(char* cp)存入字符指针数组(char * spa[])
- C语言实现输入一个字符串后打印出该字符串中字符的所有排列
- C语言的字符串转为OC中的字符串,控制台输入用户名和密码,判断输入的用户名是否是@“Frank”, 密码 是否是 @“lanou”, 如果用户名和密码都正确,则输出登录成功, 否则输出登录失败.
- python计算输入的字符串
- C语言——计算输入的任意数的位数(两种方法)
- C语言 realloc为什么要有返回值,realloc返回值详解/(解决任意长度字符串输入问题)。
- 初学C语言:输入3个字符串,按从小到大的顺序输出
- 开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。
- C语言 对输入的一个字符串进行排序