C語言:四則計算器(支持小數,括號和次方冪 組合輸入計算)

之前已經寫過一個計算器,每次回顧都覺得很複雜,一直在考慮重新寫一個

  1. 支持小數運算
  2. 存儲數據改爲了double類型
  3. 支持整數次方
  4. 運算中乘法可以用x或者*表示,兩個都支持
  5. 平臺visual 存儲數據改爲了double類型
  6. 平臺visual studio 2015通過,macOS上gcc通過
  7. 另外:輸入的時候輸入法最好是英文狀態另外:輸入的時候輸入法最好是英文狀態

公式讀入後存儲模式如下:
這裏寫圖片描述

大概說一下計算流程:
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;
}

測試數據不多,有錯誤歡迎指出^^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章