中缀式转换为逆波兰表达式

捣腾了一天,总算有个雏形了,先发上来吧,已知的BUG:1.直接输入回车会溢出,2.表达式不完整会溢出,3.多余的)会造成未知的结果,但是如果是在式子的最后是没有问题的,4.中文的字符会报错。

目前已知的就这么多了吧

下面上代码:

#include 
#include 
#include 

struct __stack
{
	double number;
	char symbol;
	struct __stack *next;
	struct __stack *prev;
};
typedef struct __stack* p_list;
// cdecl.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
bool priority(const char a, const char b)
{
	if ((a == '+' || a == '-') && (b == '*' || b == '/'))
		return 1;
	else if ((a == '+' || a == '-') && (b == '-' || b == '+'))
		return 0;
	else if ((a == '*' || a == '/') && (b == '*' || b == '/'))
		return 0;
	else
		return 0;
}
void BeEmpty(p_list head)				//释放空间,不需要人为调用
{
	p_list temp = head;
	for (; temp != NULL; head = temp)
	{
		temp = head->next;
		free(head);
	}
}				
void frist_time(p_list &head)		//首次创建头节点时使用
{
	head = (p_list)malloc(sizeof(struct __stack));
	head->next = NULL;
	head->prev = NULL;
}
void creat_list(p_list &node)		//创建其余节点时使用
{
	node->next = (p_list)malloc(sizeof(struct __stack));
	node->next->prev = node;
	node = node->next;
	node->next = NULL;
}
double calc(p_list head)			//用于计算最后的结果,其中判断运算模式可以自行按照需要修改
{
	p_list stuck = NULL, temp, h_temp;
	double sum;
	for (h_temp = head; h_temp != NULL; h_temp = h_temp->next)
	{
		if (h_temp->symbol == 0)
		{
			if (stuck == NULL)
			{
				frist_time(stuck);
				temp = stuck;
			}
			else
				creat_list(temp);
			temp->number = h_temp->number;
		}
		else
		{
			if (h_temp->symbol == '+')
			{
				temp->prev->number += temp->number;
				p_list t_temp = temp->prev;
				free(temp);
				temp = t_temp;
			}
			else if (h_temp->symbol == '-')
			{
				temp->prev->number -= temp->number;
				p_list t_temp = temp->prev;
				free(temp);
				temp = t_temp;
			}
			else if (h_temp->symbol == '*')
			{
				temp->prev->number *= temp->number;
				p_list t_temp = temp->prev;
				free(temp);
				temp = t_temp;
			}
			else if (h_temp->symbol == '/')
			{
				temp->prev->number /= temp->number;
				p_list t_temp = temp->prev;
				free(temp);
				temp = t_temp;
			}
			else
			{
				printf("\n******Unexpect symbol******\n");
				BeEmpty(head);
				BeEmpty(stuck);
				exit(1);
			}
		}
	}
	sum = stuck->number;
	stuck->next = NULL;
	BeEmpty(stuck);
	BeEmpty(head);
	return sum;
}
p_list scan_list()				//输入中缀表达式
{
	p_list t_head = NULL, pl_temp;
	char c_temp = '#', str_temp[10];
	printf("Input the calculation method:");
	for (; c_temp != '\n';)
	{
		if (!scanf_s("%[0-9]", str_temp, 10))
		{


			if ((c_temp = getchar()) == '\n');
			else
			{
				if (t_head == NULL)
				{
					frist_time(t_head);
					pl_temp = t_head;
				}
				else
					creat_list(pl_temp);
				pl_temp->symbol = c_temp;
				pl_temp->number = (double)0xcccccccccccccccc;
			}
		}
		else
		{
			if (t_head == NULL)
			{
				frist_time(t_head);
				pl_temp = t_head;
			}
			else
				creat_list(pl_temp);
			pl_temp->number = atoi(str_temp);
			pl_temp->symbol = 0;
		}
	}
	return t_head;
}
void print_list(const p_list head)		//打印链表
{
	p_list temp = head;
	for (; temp != NULL; temp = temp->next)
	{
		if (temp->number == (double)0xcccccccccccccccc)
			printf("%c ", temp->symbol);
		else
			printf("%f ", temp->number);
	}
}
p_list m_bracket(p_list p_temp,p_list &temp, char *stuck_symbol, int i, bool(*p_function)(const char a, const char b))		
						//遇到括号时调用的函数
{
	char *temp_stuck_symbol = stuck_symbol + i;																//其中第一个参数对应中缀式节点,第二个对应后缀式节点
	int t_i = 0;
	for (p_temp = p_temp->next; p_temp->symbol != ')'; p_temp = p_temp->next)												//第三个是符号栈,第四个是地址偏移量
	{
		if (p_temp->symbol == '(')																	//第五个是优先级判断函数,此函数需要用户按照需求自定义
		{
			p_temp = m_bracket(p_temp, temp, temp_stuck_symbol, t_i, p_function);											//递归调用括号中遇到括号时的情况
			if (p_temp->symbol == ')')
				break;
		}
		if (p_temp->symbol == 0)
		{
			if (temp == NULL)
				frist_time(temp);
			else
				creat_list(temp);
			temp->number = p_temp->number;
			temp->symbol = 0;
			continue;
		}
		if (t_i == 0 || p_function(stuck_symbol[t_i - 1], p_temp->symbol))
		{
			temp_stuck_symbol[t_i] = p_temp->symbol;
			++t_i;
		}
		else
		{
			for (--t_i; t_i >= 0 && !p_function(temp_stuck_symbol[t_i], p_temp->symbol); --t_i)
			{
				creat_list(temp);
				temp->symbol = temp_stuck_symbol[t_i];
				temp->number = (double)0xcccccccccccccccc;
			}
			++t_i;
			temp_stuck_symbol[t_i] = p_temp->symbol;
			++t_i;
		}
	}
	for (--t_i; t_i >= 0; --t_i)
	{
		creat_list(temp);
		temp->symbol = temp_stuck_symbol[t_i];
		temp->number = (double)0xcccccccccccccccc;
	}
	p_temp = p_temp->next;
	return p_temp;
}
p_list Excange(p_list head,bool (*p_function)(const char a, const char b))									//中缀转换后缀主函数,函数指针为优先级判断函数,此函数需要用户按照需求自定义
{		
	p_list p_temp = head, t_head = NULL, temp;
	temp = t_head;
	char stuck_symbol[1024];
	int i = 0;
	for (; p_temp != NULL; p_temp = p_temp->next)
	{
		if (p_temp->symbol == '(')																			//遇到括号时
			if (temp == t_head)
			{
				p_temp = m_bracket(p_temp, t_head, stuck_symbol, i, p_function);
				temp = t_head;
				for (; t_head->prev != NULL; t_head = t_head->prev);
				if(p_temp == NULL)
					break;
				if (p_temp->symbol == ')')																	//当调用结束后的反括号处理(跳过对这个符号的处理)
					break;
			}
			else
			{
				p_temp = m_bracket(p_temp, temp, stuck_symbol, i, p_function);
				if (p_temp == NULL)
					break;
				if (p_temp->symbol == ')')
					break;
			}
		if (p_temp->symbol == 0)
		{
			if (t_head == NULL)
			{
				frist_time(t_head);
				temp = t_head;
				t_head->number = p_temp->number;
				t_head->symbol = 0;
				continue;
			}
			else
				creat_list(temp);
			temp->number = p_temp->number;	
			temp->symbol = 0;
			continue;
		}
		if (i == 0 || p_function(stuck_symbol[i-1], p_temp->symbol))
		{
			stuck_symbol[i] = p_temp->symbol;
			++i;
		}
		else
		{
			for (--i; i >=0&&!p_function(stuck_symbol[i], p_temp->symbol); --i)
			{
				creat_list(temp);
				temp->symbol = stuck_symbol[i];
				temp->number = (double)0xcccccccccccccccc;
			}
			++i;
			stuck_symbol[i] = p_temp->symbol;
			++i;
		}
	}
	for (--i; i >= 0; --i)																						//清空符号栈
	{
		creat_list(temp);
		temp->symbol = stuck_symbol[i];
		temp->number = (double)0xcccccccccccccccc;
	}
	BeEmpty(head);
	return t_head;
}
int main(void)
{
	double sum;
	p_list head;
	head = scan_list();
	head = Excange(head,priority);
	print_list(head);
	sum = calc(head);
	printf("\nsum is : %f", sum);
    return 0;
}


大概的思路如图:

中缀式转换为逆波兰表达式_第1张图片

(资料出处:https://zh.wikipedia.org/wiki/调度场算法)

遇到括号时,当作输入了一个新的中缀表达式处理即可,此时符号栈偏移到之前原本占未使用的部分,并且重新定义指针,让括号处理函数误认为这个是一个新的符号栈

这样最后总转换函数出栈是没有问题的



以上提到的BUG会尽快修复更新,谢谢!

你可能感兴趣的:(C语言初学)