• 加/减/乘/除四则混合运算(C 语言)


       逆波兰表达式(也称为后缀表达式) C 语言简单实现

      本示例旨在展示逆波兰表达式原理,作简单的混合运算,不作容错处理也不保证结果。若混合运算字符串中有{ [ %] } 等,自行调试解决 

      列如计算: -20.5 + ( 100 - ( 3 + 2 ) * 8 ) / ( 8 - 5 ) - 10

      后缀表达式为:-20.5 100 3 2 + 8 * - 8 5 - / + 10 - 

      C  语言代码如下:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #define CNT 1000
      6 
      7 struct node{
      8    float num;   //数字
      9    char op;     //操作符
     10 };
     11 
     12 struct node datas[CNT];  //后缀表达式
     13 int data_top = -1;       //栈顶索引
     14 
     15 char ops[CNT];          //操作符
     16 int op_top = -1;        //栈顶索引
     17  
     18 char nums[100];        //数字字符串
     19 int num_top = -1;      //栈顶索引
     20 int minus_tag = 1;     //负数标记
     21 //数字入栈
     22 void push_num(){
     23   if(num_top > -1){
     24      datas[++data_top].num = atof(nums) * minus_tag;
     25      datas[data_top].op = 0;
     26      num_top = -1;
     27      minus_tag = 1;
     28      memset(nums, 0, sizeof(nums));  
     29   }
     30 }
     31 //中缀转后缀
     32 void mtoe(const char* str){
     33   char *tmp;
     34   tmp = (char*)str;
     35   int last_tag = 1; //上一个字符是否是运算符,默认是,用于处理负数
     36   while(*tmp != ''){
     37     char ch = *tmp;
     38     ++tmp;
     39     if(ch == ' ') continue;
     40    
     41     if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '('){
     42       push_num();
     43       if( (ch == '-') && last_tag ){
     44          minus_tag = -1;//负数标记
     45          last_tag = 0;
     46          continue;
     47       }
     48       last_tag = 1;
     49       while(op_top > -1){
     50         if(ch == '(') break;
     51         char op = ops[op_top];
     52         if(op == '(') break;
     53         if(ch == '+' || ch == '-'){
     54           datas[++data_top].op = op;
     55           --op_top;    
     56         }else{
     57           if(op == '+' || op == '-') break;
     58           else{
     59             datas[++data_top].op = op;
     60             --op_top;  
     61           }
     62         }  
     63       }
     64       ops[++op_top] = ch;
     65     }else if(ch == ')'){
     66       push_num();
     67       last_tag = 0;
     68       while(ops[op_top] != '('){
     69         datas[++data_top].op = ops[op_top];
     70         --op_top;
     71       }
     72       --op_top; 
     73     }else{  
     74       last_tag = 0;
     75       nums[++num_top] = ch;
     76     }
     77   }// end of while *tmp 
     78   push_num();//最后的数据入栈
     79   while(op_top > -1){//最后的操作符入栈
     80      datas[++data_top].op = ops[op_top];
     81      --op_top;   
     82   } 
     83     
     84 }
     85 //计算值
     86 float calculating(){
     87   if(data_top < 0) return 0; 
     88   float stack[CNT] = {0};
     89   int top = -1;
     90   int i = 0;
     91   while(i <= data_top){
     92     char op = datas[i].op;
     93     if(op == 0){
     94        stack[++top] = datas[i].num;
     95     }else{
     96       float a = stack[top -1];
     97       float b = stack[top];
     98       --top;
     99       float c = 0;
    100       if(op == '+') c = a + b;
    101       else if(op == '-') c = a -b;
    102       else if(op == '*') c = a * b;
    103       else if(op == '/') c = a / b;
    104       stack[top] = c;
    105     }
    106    ++i;
    107   }
    108   if(top < 0) return 0;
    109   else return stack[top]; 
    110 }
    111 
    112 int main(int argc, char *argv[]){
    113   char *parms = "-20.5+(100-(3+2)*8)/(8-5) - 10";
    114   //char *parms = "10+100/2*5";
    115   data_top = -1;
    116   op_top = -1;
    117   num_top = -1;
    118   mtoe(parms);
    119   printf("
    ");
    120   printf("%s = ",parms);
    121   printf("%f
    ",calculating());
    122   int i = 0;
    123   for(i = 0; i <= data_top; i++){
    124      if(datas[i].op) printf("%c ", datas[i].op); 
    125      else printf("%f ",datas[i].num); 
    126   }
    127   printf("
    
    ");
    128   return 0;
    129 }
    显示代码

      执行结果:

      -20.5+(100-(3+2)*8)/(8-5) - 10 = -10.500000
      -20.500000 100.000000 3.000000 2.000000 + 8.000000 * - 8.000000 5.000000 - / + 10.000000 -

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 #define CNT 1000
     6 
     7 float datas[CNT];        //数字栈
     8 int data_top = -1;       //栈顶索引
     9 
    10 char nums[100];        //数字字符串
    11 int num_top = -1;      //栈顶索引
    12 int minus_tag = 1;     //负数标记
    13 //数字入栈
    14 void push_num(){
    15   if(num_top > -1){
    16      datas[++data_top] = atof(nums) * minus_tag;
    17      num_top = -1;
    18      minus_tag = 1;
    19      memset(nums, 0, sizeof(nums));  
    20   }
    21 }
    22 //操作符入栈,则计算值
    23 void push_op(char op)
    24 {
    25    float a = datas[data_top -1];
    26    float b = datas[data_top];
    27    float c = 0;
    28    if(op == '+') c = a + b;
    29    else if(op == '-') c = a -b;
    30    else if(op == '*') c = a * b;
    31    else if(op == '/') c = a / b;
    32    datas[--data_top] = c;
    33 }
    34 //中缀转后缀并计算值
    35 void calc(const char* str){
    36   char *tmp;
    37   tmp = (char*)str;
    38   char ops[CNT];          
    39   int op_top = -1;        
    40   int last_tag = 1; //上一个字符是否是运算符,默认是,用于处理负数
    41   while(*tmp != ''){
    42     char ch = *tmp;
    43     ++tmp;
    44     if(ch == ' ') continue;
    45    
    46     if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '('){
    47       push_num();
    48       if( (ch == '-') && last_tag ){
    49          minus_tag = -1;//负数标记
    50          last_tag = 0;
    51          continue;
    52       }
    53       last_tag = 1;
    54       while(op_top > -1){
    55         if(ch == '(') break;
    56         char op = ops[op_top];
    57         if(op == '(') break;
    58         if(ch == '+' || ch == '-'){
    59           push_op(op);
    60           --op_top;    
    61         }else{
    62           if(op == '+' || op == '-') break;
    63           else{
    64             push_op(op);
    65             --op_top;  
    66           }
    67         }  
    68       }
    69       ops[++op_top] = ch;
    70     }else if(ch == ')'){
    71       push_num();
    72       last_tag = 0;
    73       while(ops[op_top] != '('){
    74         push_op(ops[op_top]);
    75         --op_top;
    76       }
    77       --op_top; 
    78     }else{  
    79       last_tag = 0;
    80       nums[++num_top] = ch;
    81     }
    82   }// end of while *tmp 
    83   push_num();//最后的数据入栈
    84   while(op_top > -1){//最后的操作符入栈
    85      push_op(ops[op_top]);
    86      --op_top;   
    87   }     
    88 }
    89 
    90 int main(int argc, char *argv[]){
    91   char *parms = "-20.5+(100-(3+2)*8)/(8-5) - 10";
    92   data_top = -1;
    93   num_top = -1;
    94   calc(parms);
    95   printf("
    %s = ",parms);
    96   printf("%f
    ",datas[0]);
    97   return 0;
    98 }
    优化版

      

    附中缀表达式转前缀或后缀表达式原理

    转化步骤:

    1. 按照运算符的优先级对所有的运算单位加括号
    2. 将运算符移动到对应括号的前面(前缀表达式)或后面(后缀表达式)
    3. 去掉括号,得到前缀或后缀表达式

    示例:

        中缀表达式:5 + ( 6 + 7 ) × 8 - 9

    1)加括号
        变成 ( ( 5 + ( ( 6 + 7 ) × 8 ) ) - 9 )

    2)移动运算符

       前缀变成了 - ( + ( 5 × ( + ( 6 7 ) 8 ) ) 9 )

       后缀变成了 ( ( 5 ( ( 6 7 ) + 8 ) × ) + 9 ) -

    3)去掉括号
       前缀表达式: - + 5 × + 6 7 8 9
       后缀表达式:5 6 7 + 8 × + 9 -

  • 相关阅读:
    SQL中Group By的使用
    SQL Server中的Merge关键字
    C# 9.0 正式发布了(C# 9.0 on the record)
    sql server 本地复制订阅 实现数据库服务器 读写分离
    SQL Server游标
    走进异步编程的世界 开始接触 async/await
    C#发展历程以及C#6.0新特性
    .NET NPOI导出Excel详解
    Centos 7搭建Gitlab服务器超详细
    使用python设置word中的字体样式
  • 原文地址:https://www.cnblogs.com/btxz/p/12104221.html
Copyright © 2020-2023  润新知