之前已经写过一个计算器,每次回顾都觉得很复杂,一直在考虑重新写一个
支持小数运算
存储数据改为了double类型
支持整数次方
运算中乘法可以用x或者*表示,两个都支持
平台visual studio 2015
另外:输入的时候输入法最好是英文状态
这次的存储模式如下:
大概说一下计算流程:
1:将输入的文本提取出运算符,数字,次方和等级四类
2:每次运算找到当前的最高等级,先计算次方,再计算四则运算
3:计算结果覆盖至第二个aNum结构体的data,并废弃第一个结构体
4:2、3循环输入的公式拆分成data,oper(operator)和class三类 data:即为公式中的每个数字 oper:+-*/运算符
class:符号的运算等级(类似于优先级)讲一下我构造class的这个思路:
在括号外的公式中,+-的运算等级(class)为1,*/的运算等级为2
在括号内的公式中,+-对应等级为3(大于括号外的/等级),而/的等级为4在这次的计算中,我把计算单独拿了出来
函数:float compute(float num1, float num2, char opt)
一次只运算一对数字,而每对计算的先后顺序就根据class等级值每一个struct aNum用了链表来连接,利于计算后的数据处理
例:
3+5x(2+1)-7
第一次运算时,找到最高的class,即存储“data=2,oper=’+’,class=3”的struct,2+1=3,而当前struct就不能再留下了,此时就把结果3覆盖到下一个struct的data上,然后抛弃当前存储“data=2”的struct,即p_front->next=p->next;每次计算如此循环
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define INIT_STRING_SIZE 100
#define True 1
#define False 0
int saved_class[4] = { 0, 0, 0, 0 };
typedef struct aNum {
double data;
char oper;
int dataClass;
int power;
struct aNum *next;
}num;
typedef struct {
char *formula;
int length;
}string;
void setNULL(char *num)//清空一个字符串
{
int i = 0;
while (i<5)
{
num[i] = NULL;
++i;
}
}
int countOperators(string *input, int &counter)//processing step 1
{//计算运算符个数
int i = 0;
while (input->formula[i] != '\0')
{
switch (input->formula[i++])
{
case '+':
case '-':
case '*':
case '/':++counter; break;
default:break;
}
++input->length;
}
return 1;
}
int getData(string *input, num *nums)//processing step 2
{//把数字,符号和class存入nums的结构体
int i = 0; //counter of input->formula
int k = 0; //counter of temp;
int power = 0;
char temp[5];
int inBracket = False;
num *p = nums;
num *body;
while (i <= input->length)
{
if ((input->formula[i]<'0' || input->formula[i]>'9')&&input->formula[i]!='.'&&input->formula[i]!='^')
{//进入此处时数据已经收集完毕
if (input->formula[i] == '(')
{
inBracket = True;
++i;
continue;
}
if (input->formula[i] == ')')
{
inBracket = False;
++i;
continue;
}
body = (num *)calloc(1, sizeof(num));
body->data = atof(temp); //得到数字
setNULL(temp); //归零temp
k = 0;
switch (input->formula[i])
{
case '+':body->dataClass = inBracket == False ? 1 : 3; //计算当前运算符的等级
++saved_class[body->dataClass - 1]; //在等级数组里记录一次
body->oper = input->formula[i]; //得到运算符
break;
case '-':body->dataClass = inBracket == False ? 1 : 3;
++saved_class[body->dataClass - 1];
body->oper = input->formula[i];
break;
case 'x':
case '*':body->dataClass = inBracket == False ? 2 : 4;
++saved_class[body->dataClass - 1];
body->oper = input->formula[i];
break;
case '/':body->dataClass = inBracket == False ? 2 : 4;
++saved_class[body->dataClass - 1];
body->oper = input->formula[i];
break;
default:break;
}
if (power != 0)
{
body->power = power;
power = 0;
}
p->next = body;
p = p->next;
}
else if (input->formula[i] == '^')
{
power = input->formula[++i] - 48;
}
else
{
temp[k++] = input->formula[i];
}
++i;
}
return 1;
}
double compute(double num1, double num2, char opt)
{//每次运算单独提取
double result;
switch (opt)
{
case '-':result = num1 - num2; break;
case '+':result = num1 + num2; break;
case 'x':
case '*':result = num1 * num2; break;
case '/':result = num1 / num2; break;
}
return result;
}
int processingData(num *nums)//processing step 3
{//nums作为头结点是没有数据的
int s = 3;//saved_class
int i = 0;
num *p = nums;
num *p_front;
while (saved_class[s] == 0&&s>0)
--s;
while (p->next->next != NULL)//class oper next 都可以
{
if (p->next->dataClass != s + 1)
{
p = p->next;
continue;
}
p_front = p;
p = p->next;//p此时指向待计算的第一个struct aNUm
if(p->power != 0)
{
p->data = pow(p->data, p->power);
p->power = 0;
}
if (p->next->power != 0)
{
p->next->data = pow(p->next->data, p->next->power);
p->next->power = 0;
}
p->next->data = compute(p->data, p->next->data, p->oper);
p_front->next = p->next;
free(p);
--saved_class[s];
while (saved_class[s] == 0&&s!=0)
--s;
p = nums;
}
if (nums->next->power != 0)//处理单个数字输入的情况,比如2^2
{
nums->next->data = pow(nums->next->data, nums->next->power);
}
printf("result=%lf", nums->next->data);
return 1;
}
int main()
{
int counter = 0;
num *nums = NULL;
string *input;
input = (string *)calloc(1, sizeof(string));
input->formula = (char *)calloc(INIT_STRING_SIZE, sizeof(string));
puts("Input formula:");
scanf("%s", input->formula);
//得到运算符和运算符个数
countOperators(input, counter);
//根据运算符个数申请存储数字的空间
nums = (num *)calloc(1, sizeof(num));
//存储数字和运算符
getData(input, nums);
processingData(nums);
free(input->formula);
free(input);
free(nums->next);
free(nums);
system("pause");
return 0;
}
测试数据不多,有错误欢迎指出^^