C语言_通过链表和栈实现简易计算器

声明:我太菜了,求轻喷qwq

题目

这个是作业9的第五题

代码

/*
1 算式的输入
	1.1 输入方式:从控制台键入一行字符串
	1.2 支持数据类型:双精度浮点数(负数,如-x,请写为(0-x))
	1.3 支持运算符:
		1.3.1 加减乘除(注:+ - * /)
		1.3.2 小括号
		1.3.3 sin(x) cos(x) tan(x)(注:三角函数后面须带括号)
	1.4 注意:程序没有进行对算式合法性的判断,所以请务必输入合法的算式,以免出现奇怪结果
	1.5 样例输入输出
		输入:sin(3.14/2*3)+2*3
		输出:5
2 代码实现方式
	2.1 加减乘除&括号:通过栈将算式转化为后缀表达式,使用链表储存(复制粘贴题目中的enum, union和struct)
	2.2 三角函数;通过傻逼方法实现(对啊我就是菜)
*/

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<iostream>

enum eType { DOUBLE, CHAR };

union uSymbol {
	double Number;
	char szOperator;
};

struct Node {
	enum eType Type;
	union uSymbol Symbol;
	struct Node* next = NULL;
};

void Add(union uSymbol symbol, struct Node** head, struct Node** tail, enum eType type) {
	//printf("BegAdd\n");
	if (*head == NULL) {
		struct Node* now;
		if ((now = (struct Node*)malloc(sizeof(Node))) == NULL)exit(1);
		*head = now;
		*tail = now;
		(*tail)->next = NULL;
		now->Type = type;
		now->Symbol = symbol;
		//printf("endAddNULL\n");
		return;
	}
	struct Node* now;
	if ((now = (struct Node*)malloc(sizeof(Node))) == NULL)exit(1);
	(*tail)->next = now;
	*tail = now;
	(*tail)->next = NULL;
	now->Type = type;
	now->Symbol = symbol;
//	printf("endAdd\n");
}

double Getnum(char** s) {
	double ans = 0;
	while (**s >= '0' && **s <= '9') {
		ans = ans * 10 + **s - '0';
		(*s)++;
	}
	if (**s != '.')return ans;
	double now = 0.1;
	(*s)++;
	while (**s >= '0' && **s <= '9') {
		ans += now * ((double)**s - '0');
		now *= 0.1;
		(*s)++;
	}
	return ans;
}

int Priority(char c) {
	if (c == '+' || c == '-')return 1;
	if (c == '*' || c == '/')return 2;
	return 0;
}

double Cal(char* s) {
	struct Node* head = NULL;
	struct Node* tail = NULL;
	char stack[100];
	int top = -1;
	while (*s) {
		int Pri = Priority(*s);
		if (*s >= '0' && *s <= '9') {
			double num = Getnum(&s);
			union uSymbol now;
			now.Number = num;
			enum eType type = DOUBLE;
			Add(now, &head, &tail, type);
		}
		else if (Pri) {
			if (top == -1) { stack[++top] = *s; }
			else {
				while (top >= 0 && Priority(stack[top]) >= Pri) {
					union uSymbol now;
					now.szOperator = stack[top];
					enum eType type = CHAR;
					Add(now, &head, &tail, type);
					top--;
				}
				stack[++top] = *s;
			}
			s++;
		}
		else if (*s == '(') {
			stack[++top] = *s;
			s++;
		}
		else if (*s == ')') {
			while (top >= 0 && Priority(stack[top])) {
				union uSymbol now;
				now.szOperator = stack[top];
				enum eType type = CHAR;
				Add(now, &head, &tail, type);
				top--;
			}
			top--;//弹出左括号
			s++;
		}
		else if (*s == 's' || *s == 'c' || *s == 't') {
			char tag = *s;
			//printf("in!\n");
			int tot = 0, num = 0;
			s += 3;
			char* p = s;
			char ss[100];
			do{
				ss[num++] = *p;
				if (*p == '(')tot++;
				if (*p == ')')tot--;
				p++;
			} while (tot);
			ss[num] = '\0';
			//printf("NowCalkid %s\n",s);
			double kid = Cal(ss);
			//printf("OKNowCalkid %lf\n",kid);
			switch (tag) {
			case 's':kid = sin(kid); break;
			case 'c':kid = cos(kid); break;
			case 't':kid = tan(kid); break;
			}
			union uSymbol now;
			now.Number = kid;
			enum eType type = DOUBLE;
			Add(now, &head, &tail, type);
			s = p;
		}
	}
	while (top>=0) {
		union uSymbol now;
		now.szOperator = stack[top];
		enum eType type = CHAR;
		Add(now, &head, &tail, type);
		top--;
	}
	//std::cout << top << std::endl;
	struct Node* now = head;
	double tocal[100];
	int topcal = -1;
	while(1) {
		//printf("whilebegin\n");
		if (now == NULL)return tocal[topcal];//若算式不合法,就炸了
		//printf("returned\n");
		if (now->Type == DOUBLE) {
			//std::cout << "hahaddd\n";
			tocal[++topcal] = now->Symbol.Number;
			//printf("%g\n", tocal[topcal]);
		}
		else if (now->Type == CHAR) {
			//std::cout << "hahaccc\n";
			char c = now->Symbol.szOperator;
			//printf("%c\n", c);
			switch (c) {
			case '+':tocal[topcal - 1] = tocal[topcal - 1] + tocal[topcal]; break;
			case '-':tocal[topcal - 1] = tocal[topcal - 1] - tocal[topcal]; break;
			case '*':tocal[topcal - 1] = tocal[topcal - 1] * tocal[topcal]; break;
			case '/':tocal[topcal - 1] = tocal[topcal - 1] / tocal[topcal]; break;
			}
			topcal--;
			//printf("%g\n", tocal[topcal]);
		}
		//std::cout << "hahaout\n";
		now = now->next;
	}
}

int main() {
	char s[100];
	scanf("%s", s);
	printf("%g\n", Cal(s));
}
posted @ 2021-12-18 11:16  Y15BeTa  阅读(185)  评论(0编辑  收藏  举报