之前已經寫過一個計算器,每次回顧都覺得很複雜,一直在考慮重新寫一個
- 支持小數運算
- 存儲數據改爲了double類型
- 支持整數次方
- 運算中乘法可以用x或者*表示,兩個都支持
- 平臺visual 存儲數據改爲了double類型
- 平臺visual studio 2015通過,macOS上gcc通過
- 另外:輸入的時候輸入法最好是英文狀態另外:輸入的時候輸入法最好是英文狀態
公式讀入後存儲模式如下:
大概說一下計算流程:
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\n", 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");//如果你是linux或者macos,可能需要去掉這句
return 0;
}
測試數據不多,有錯誤歡迎指出^^