C语言之四则运算表达式求值(链栈)—支持浮点型数据,负数, 整型数据运算

 运算符间的优先级关系:

 

链栈结构体定义:

数据域使用字符串长度为20的字符数组(故需要注意判断读取的字符串是运算符还是数值)

可支持浮点型数据负数 整型数据的运算

 

float EvaluateExpression() 函数实现步骤:

1)初始化OPTR栈和OPND栈,将表达式起始符 “#” 压入OPTR栈。

2)扫描表达式,读入第一个字符串str,如果表达式没有扫描完毕至 "#" 或压入OPTR的栈顶元素不为 "#" 时,则循环执行以下操作:

  ——>使用  str_to_float() 函数判断输入的字符串str是否是运算符

    ——>如果str不是运算符,则压入OPND栈,读取下一个字符串str

    ——>如果字符串str是运算符,使用 Precede() 函数获取OPTR栈顶元素的运算符和字符串str的运算符的优先级:

      ——>若是 ‘<’ ,则字符串str压入OPTR栈,读入下一个字符串str

      ——>若是 ‘>’ ,则弹出OPTR栈顶的运算符字符串,从OPND栈弹出两个数值字符串,使用 Operate() 函数对两个字符串进行运算,将得到的浮点型运算结果使用  float_to_str() 函数转换成字符串型数据,压入OPND栈

      ——>若是 ‘=’ ,则OPTR的栈顶元素是 "(" 且 str 是 ")" ,这时弹出OPTR栈顶的 "(" ,相当于括号匹配成功,然后读入下一字符串str

3)OPND栈顶元素记为表达式求值结果,输出运算结果。

 

实现代码(.cpp后缀文件)

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<math.h>
  5 
  6 #define inf float(0x3f3f3f3f)
  7 #define MAXSIZE 100
  8 
  9 char priority[7] = {'+', '-', '*', '/', '(', ')', '#'};
 10 
 11 char priority_relationship[7][7] = {
 12     {'>', '>', '<', '<', '<', '>', '>'}, 
 13     {'>', '>', '<', '<', '<', '>', '>'}, 
 14     {'>', '>', '>', '>', '<', '>', '>'}, 
 15     {'>', '>', '>', '>', '<', '>', '>'}, 
 16     {'<', '<', '<', '<', '<', '=', ' '}, 
 17     {'>', '>', '>', '>', ' ', '>', '>'}, 
 18     {'<', '<', '<', '<', '<', ' ', '='} 
 19 }; // 各个运算符之间的优先级关系
 20 
 21 int get_index(char str[])
 22 {// 获取相应运算符的索引
 23     for(int i = 0; i < 7; i++)
 24     {
 25         if(str[0] == priority[i]) return i;
 26     }
 27     printf("未找到匹配的字符\n");
 28 }
 29 
 30 char Precede(char inside_data[], char input_data[])
 31 {// 获取两个运算符之间的优先级关系
 32     int inside_index = get_index(inside_data);
 33     int input_index = get_index(input_data);
 34 
 35     return priority_relationship[inside_index][input_index];
 36 }
 37 
 38 typedef struct StackNode
 39 {
 40     char data[MAXSIZE];   // 压入栈里面的数据都是字符型,在进行运行时,记得将字符型数字转换为浮点型数字
 41     struct StackNode *next;
 42 }StackNode, *LinkStack;
 43 
 44 void InitStack(LinkStack &S)
 45 {// 构造一个空栈S,栈顶指针置空
 46     S = NULL;
 47 }
 48 
 49 void Push(LinkStack &S, char data[])
 50 {// 在栈顶插入元素data
 51     StackNode *p;
 52 
 53     p = (StackNode *)malloc(sizeof(StackNode));  // 生成新的结点
 54     strcpy(p->data, data);  // 将新结点的数据域置为data
 55     p->next = S;    // 将新结点插入栈顶
 56     S = p;    // 修改栈顶指针为p
 57 }
 58 
 59 char *Pop(LinkStack &S)
 60 {// 删除S的栈顶元素, 用data返回其值
 61     char data[MAXSIZE];
 62     if(S == NULL) printf("错误!!!\n栈为空, 无法执行删除命令...");
 63     else
 64     {
 65         StackNode *p;
 66 
 67         strcpy(data, S->data);  // 将栈顶元素赋给data
 68         p = S;   // 用p临时保存栈顶元素的空间,以备释放
 69         S = S->next;   //修改栈顶指针 
 70         free(p);    // 释放原栈顶元素的空间
 71         return data;
 72     }
 73 }
 74 
 75 char *GetTop(LinkStack &S)
 76 {// 获取栈顶元素
 77     if(S != NULL)
 78         return S->data;
 79     else
 80     {
 81         printf("错误!!!\n栈顶为空");
 82         return "0";
 83     }
 84 }
 85 
 86 float str_to_float(char *str)
 87 {// 将字符串数据转换成浮点型数据
 88     float num = 0;
 89     int state_1 = 0;  // 用于判断是否读取到小数点的状态值, 0代表还没有读取到
 90     int state_2 = 0; //用于判断是否读取到负号的状态值, 0代表还没有读取到
 91     while(( *str != '\0' && *str >= '0' && *str <= '9') || *str == '.' || (*str == '-' && *(str + 1) != '\0'))
 92     {// 注意判断小数点和负号
 93         if(*str == '.') state_1 = 1;  // 当读取到小数点的时候, 状态值state_1赋值为1
 94         else if(*str == '-') state_2 = 1;  // 当读取到负号的时候, 状态值state_2赋值为1
 95         else
 96         {
 97             if(state_1 == 0) num = num * 10 + (*str - '0');
 98             else
 99             {
100                 num += (*str - '0') * pow(0.1, state_1);
101                 state_1++;
102             }
103         }
104         str++;
105     }
106     if(*str != '\0') return inf;
107     else if(state_2 == 1)
108     {
109         return num * -1;
110     }
111     else return num;
112 }
113 
114 char *float_to_str(float num)
115 {// 将浮点型数据装换成字符串数据,保留浮点型数据小数点后4位的值
116     char str[MAXSIZE];
117     sprintf(str, "%.4f", num);  // 保留小数点后4位
118     return str;
119 }
120 
121 
122 float Operate(char a[], char theta[], char b[])
123 {//执行运算
124     float a_num = str_to_float(a);
125     float b_num = str_to_float(b);
126 
127     if(theta[0] == '+') return a_num + b_num;
128     else if(theta[0] == '-') return a_num - b_num;
129     else if(theta[0] == '*') return a_num * b_num;
130     else if(theta[0] == '/') return a_num / b_num;
131     else printf("错误!!!\n无该运算符");
132 }
133 
134 void EvaluateExpression()
135 {
136     StackNode *OPND, *OPTR;
137     char str[MAXSIZE];
138     char theta[MAXSIZE];
139     char a[MAXSIZE];
140     char b[MAXSIZE];
141 
142     InitStack(OPND);  // 初始化栈 OPND
143     InitStack(OPTR);  // 初始化栈 OPTR
144     Push(OPTR, "#");  // 将 "#" 压入栈OPTR
145 
146     printf("请输入算术表达式(支持负数,浮点型数据),每个值用空格隔开输入,并以#结束\n");
147     scanf("%s", str);
148     while(str[0] != '#' || GetTop(OPTR)[0] != '#')
149     {
150         if(str_to_float(str) != inf)
151         { // 如果str不是运算符,则压入OPND栈,读取下一个字符串str
152             Push(OPND, str);  // 将字符串str压入OPTR栈
153             scanf("%s", str);  // 读入下一个字符串str
154         }
155         else
156         { // 如果字符串str是运算符,使用 Precede() 函数获取OPTR栈顶元素的运算符和字符串str的运算符的优先级
157             switch (Precede(GetTop(OPTR), str))  // 使用 Precede() 函数获取相应优先级
158             {
159             case '<':
160                 Push(OPTR, str);  // 将字符串str压入OPTR栈
161                 scanf("%s", str);  // 读入下一个字符串str
162                 break;
163             case '>':
164                 strcpy(theta, Pop(OPTR));  // 弹出OPTR栈顶的运算符字符串并赋值给变量 theta
165                 strcpy(b, Pop(OPND));   // 弹出OPND栈顶的数值字符串并赋值给变量 b
166                 strcpy(a, Pop(OPND));   // 弹出OPND栈顶的数值字符串并赋值给变量 a
167                 char temp_str[MAXSIZE];
168                 strcpy(temp_str, float_to_str(Operate(a, theta, b))); // 根据相应的三个字符串进行运算,把结果赋给temp_str
169                 Push(OPND, temp_str);  // 将运算结果 temp_str 压入OPND栈
170                 break;
171             case '=':
172                 Pop(OPTR);  // 弹出OPTR栈顶的运算符字符串
173                 scanf("%s", str);  // 读入下一个字符串str
174                 break;
175             default:
176                 printf("错误!!!\n该优先级不存在!!!");
177             }
178         }
179     }
180     printf("%s\n", GetTop(OPND));
181 }
182 
183 int main(void)
184 {
185     EvaluateExpression();
186 
187     system("pause");
188     return 0;
189 }

 

 

运行结果:

posted @ 2019-11-16 16:41  Jony-2018  阅读(2248)  评论(0编辑  收藏  举报