第二十二节 表达式计算器(1)



    攻破C语言到现在是不是该结束了呢,非也,前面二十一节只是给大家填充下你们在大学遗漏的C语言基本知识。对,没错,是基本知识,或许你看前面的程序或者有难度,但是我可以告诉你,这些本应都是在大学应该完成的知识体系,只是因为大学期间的种种原因,没有去完成。
    好了,基本知识体系差不多补充完整了,从这节开始,我们上实战了。

要求:写一个控制台程序,该程序实现输入一个表达式能够根据表达式计算出相应的结果。
例如:例如:输入字符串"1+2*(3-4)/5=",输出结果:0.6

要求:
基本要求:能够对+ - * /  进行运算,能够对优先级进行运算和括号匹配运算。
扩展要求:
1.  支持多数据类型输入,如: 0x12F(十六进制)、 12FH(十六进制)、  234O(八进制) 、‘F’(字符) 、0000 1111B(二进制)
2.  支持未知数赋值运算  如: x=3  则  3X+5=14
3.  支持常用函数运算 如: log、 ln、 sin、 sqrt等;
4.  支持大数据计算;
5.  支持自定义运算符。


    这个题目涉及的东西很多很多,在往后待我慢慢给大家分析。暂且先将这个帖子闲置几天,看看有没有网友对此有想法,如果你想学习下,OK、联系我,我会给你提供思路和帮助

表达式计算器所涉及的知识点非常多,我先给大家罗列下:
1.动态双向链表(这是我的算法,或许你可以试试数组,但是这两者的优劣在何处?我希望你能明白),表达式的校对
2.中缀表达式转化为后缀表达式
3.后缀表达式的计算
4.文件读写
5.不同进制的转换
6.大整数算法

我从大方向大致列举出这六点,现在我们就一项一项进行搞定。

我们首先建立一个动态双向链表:
        /* 建立一个头结点*/
        Formula_head = new node;
        init_node(Formula_head);
        Formula_head->ch = getchar();
        Formula_follow = Formula_head;

        /* 从用户读取输入*/
        for(;;){
         
         newnode = new node;    /* 新增加一个节点来存储输入*/
         init_node(newnode);    /* 初始化节点数据 */
     
         while(1){    /* 获取输入数据,并且删除空格*/
          
       newnode->ch = getchar();
       //cin >> newnode->ch ;
          if(' ' != newnode->ch ){
           
           //print_link_data(Formula_follow);
           
           break;
           
          }
         }
     
         /* 结束输入*/
         if('\n' == newnode->ch){  
       
          break;
          
         }
   
         /* 加入节点*/
         Formula_follow = add_node(Formula_follow, newnode);
         
        }

读取表达式之后,需要对表达式进行校对,处理未知数和防止输入不规则表达式(错误表达式):
        /* 检查是否是未知数算式*/
        if( check_unknow(Formula_head) ){
         
         x_head = Formula_head;
         Formula_head = NULL;
         X_flag = 1;
         continue;
         
        }
   
        /*如果有未知数的处理*/
           if(X_flag){
            
         Formula_head = add_x_in_link(Formula_head,x_head);
         
        }
   
        /*检查错误*/
        if(check(Formula_head)){
         
         continue;
         
        }

/***************************************************
** 函数名称:check
** 函数功能:扫描链表,检查表达式是否错误 
** 入口参数:node *head
** 出口参数:
***************************************************/
int check(node *head)
{
int brackets = 0;

for(; head; head=head->next){
  
  /*连续出现2个运算符,报错*/
  if(('+'==head->ch) || ('-'==head->ch) || 
     ('*'==head->ch) || ('/'==head->ch)){
   
    if(('+'==head->next->ch) || ('-'==head->next->ch) || 
       ('*'==head->next->ch) || ('/'==head->next->ch)){
    
        cout<<"erro: Consecutive two operators!"<
    
        return 1;
       }
   
  }
  
  /* 括号不匹配,报错*/
  if('(' == head->ch){
   
   brackets++;
   
  }
  if(')' == head->ch){
   
   brackets--;
   
   if(brackets<0){
    
    cout<<"erro: brackets is not right,please check it out!"<
    return 1;
    
   }
  }
  
}
/* 括号不匹配*/
if(0 != brackets){
  
  cout<<"erro: brackets is not right,please check it out!"<
  return 1;
    
}

/*没错返回0*/
return 0 ;

}

/***************************************************
** 函数名称:check_unknow
** 函数功能:检查是否为未知数算式
** 入口参数:node *head
** 出口参数:
***************************************************/
int check_unknow(node *head)
{

if(('x'==head->ch) && ('='==head->next->ch) && (NULL!=head->next->next)){
  
  return 1 ;
  
}

return 0;
}


这里开始,我们就不再是小试牛刀了,而是将数据结构真正用于实际项目中,达到算法最优、代码最优的效果。

你可能感兴趣的:(c学习)