栈  0.1
数据结构_第3章
Rpn.hh
Go to the documentation of this file.
1 
12 #ifndef __RPN_HH__
13 #define __RPN_HH__
14 
15 #include "List.h"
16 #include "Stack.hh"
17 #include <cctype>
18 #include <cmath>
19 #include <cstdio>
20 #include <exception>
21 #include <iostream>
22 #include <string>
23 #include <utility>
24 
29 namespace RPN
30 {
31 
32 const int buf_size = 80;
33 
34 enum struct notationType
35 {
36  Infix,
37  Postfix
38 };
39 
44 class RpnException : public std::exception
45 {
46 public:
54  RpnException(const std::string &text = "undefined exception",
55  const std::string &id = "undefined",
56  const std::string &td = "Generic ArgException")
57  : std::exception(),
58  _errorText(text),
59  _argId(id),
60  _typeDescription(td) {}
61 
66  virtual ~RpnException() noexcept {}
67 
73  std::string error() const { return (_errorText); }
74 
80  std::string argId() const
81  {
82  if (_argId == "undefined")
83  return " ";
84  else
85  return ("Argument: " + _argId);
86  }
87 
91  const char *what() const noexcept
92  {
93  static std::string ex;
94  ex = _argId + " -- " + _errorText;
95  return ex.c_str();
96  }
97 
104  std::string typeDescription() const { return _typeDescription; }
105 
106 private:
110  std::string _errorText;
111 
115  std::string _argId;
116 
123  std::string _typeDescription;
124 };
125 
126 class Rpn_t
127 {
128 private:
129  struct Item
130  {
131  enum class Item_type
132  {
133  Operand,
134  Operator
135  };
136 
137  enum class Operator_type : int8_t
138  {
144  NAO = (int8_t)0xFF,
145  Add = 0x10,
146  Sub = 0x11,
147  Mul = 0x20,
148  Div = 0x21,
149  Exp = 0x30,
150  Oparen = 0x01,
151  Cparen = 0x02
152  };
153 
156  double operand_val = NAN;
157 
167 
174  explicit Item(double operand_val)
176 
184  : item_type(Item_type::Operator), operator_type(op), operand_val(NAN) {}
185 
195  bool hasLoPriThan(const Item &rhs) const;
196 
203  bool isOperator() const { return item_type == Item_type::Operator; }
204 
211  bool isOperand() const { return item_type == Item_type::Operand; }
212 
220  bool isNAO() const { return isOperator() && operator_type == Operator_type::NAO; }
221 
227  static Item nao() { return Item(Item_type::Operator, Operator_type::NAO, NAN); }
228 
235  int8_t priority() const { return static_cast<int8_t>(operator_type) >> 4; }
236 
246  static Item excOp(const Item &op, const Item &opL = nao(), const Item &opR = nao());
247 
252  static const int8_t priOfAdd = static_cast<int8_t>(Operator_type::Add) >> 4;
253 
258  static const int8_t priOfMul = static_cast<int8_t>(Operator_type::Mul) >> 4;
259 
268  friend bool operator==(const Item &lhs, const Item &rhs); // 授予operator==()访问Item的私有成员的权限
269  };
270 
279  friend bool operator==(const Item &lhs, const Item &rhs); // 授予operator==()访问Rpn_t类的私有内嵌类Item的权限
280 
281 private:
287 
291  std::string postfixStr;
292 
302  Item stoItem(const char *_ch, const char **_EndPtr = nullptr) const;
303 
310  std::string itemToStr(const Item &Op) const;
311 
318  List::dLinkList<Item> exprStrToList(const std::string &exprStr) const;
319 
327 
334  std::string itemListToStr(const List::dLinkList<Item> &itemList) const;
335 
336 public:
343  explicit Rpn_t(const std::string &expr_str = "0.0", notationType exprType = notationType::Infix);
344 
349  ~Rpn_t() = default;
350 
356  double calcVal() const;
357 
363  std::string postfix() const;
364 
372  Rpn_t &assign(const std::string &expr_str, notationType _type = notationType::Infix);
373 };
374 
375 Rpn_t::Rpn_t(const std::string &expStr, notationType expType)
376 {
377  if (expStr.empty())
378  throw(RpnException("Empty string!\n"));
379 
380  // arg1是后缀式
381  if (expType == notationType::Postfix)
382  {
383  itemList = std::move(exprStrToList(expStr));
385 
386  return;
387  }
388 
389  // arg1是中缀式
390  List::dLinkList<Item> infixList = std::move(exprStrToList(expStr)); // 创建中缀list
391  itemList = std::move(infixListToPostfixList(infixList)); // 转为后缀list
392  postfixStr = std::move(itemListToStr(itemList)); // 创建后缀表达式的string
393 }
394 
395 // 设置Rpn_t类对象的值
396 Rpn_t &Rpn_t::assign(const std::string &expStr, notationType expType)
397 {
398  if (expStr.empty())
399  throw(RpnException("Empty string!\n"));
400 
401  itemList.clear();
402 
403  // arg1是后缀式
404  if (expType == notationType::Postfix)
405  {
406  itemList = std::move(exprStrToList(expStr));
408 
409  return *this;
410  }
411 
412  // arg1是中缀式
413  List::dLinkList<Item> infixList = std::move(exprStrToList(expStr)); // 创建中缀list
414  itemList = std::move(infixListToPostfixList(infixList)); // 转为后缀list
415  postfixStr = std::move(itemListToStr(itemList));
416 
417  return *this;
418 }
419 
420 // 获取后缀形式的string
421 std::string Rpn_t::postfix() const
422 {
423  return postfixStr;
424 }
425 
426 // 从string首解析一个项(操作符/操作数). 非0时, 使_EndPtr指向合法项的下一字符
427 Rpn_t::Item Rpn_t::stoItem(const char *ch, const char **_EndPtr) const
428 {
429  while (*ch)
430  {
431  // 跳过前面所有空格
432  if (isspace(*ch))
433  {
434  ++ch;
435  continue;
436  }
437 
438  // 处理非数字(操作符). (暂假定所有操作符都只有一个字符)
439  if (!isdigit(*ch))
440  {
441  if (_EndPtr)
442  *_EndPtr = ch + 1;
443 
444  switch (*ch)
445  {
446  case '+':
448  break;
449  case '-':
451  break;
452  case '*':
454  break;
455  case '/':
457  break;
458  case '^':
460  break;
461  case '(':
463  break;
464  case ')':
466  break;
467  default:
469  break;
470  } // switch (*ch)
471 
472  } // if (!isdigit(*ch))
473 
474  // 处理操作数
475  char *pEnd; // 将指向首数字的下一字符
476  double operandValue = strtod(ch, &pEnd);
477 
478  if (_EndPtr)
479  *_EndPtr = pEnd;
480 
482 
483  } //while (!*ch)
484 
485  if (_EndPtr)
486  *_EndPtr = ch;
487 
489 }
490 
491 // 用string中的表达式创建一个list
492 List::dLinkList<Rpn_t::Item> Rpn_t::exprStrToList(const std::string &exprStr) const
493 {
494  const char *expr_cstr = exprStr.c_str();
496 
497  while (*expr_cstr)
498  itemList.push_back(std::move(stoItem(expr_cstr, &expr_cstr)));
499 
500  // 若最后一个有效字符后有空白字符, 将导致一个多余的NAO进入itemList.
501  if (itemList.back().isNAO())
502  itemList.pop_back();
503 
504  return itemList;
505 }
506 
507 // 用一个中缀list创建一个后缀list
509 {
510  Stack::linkStack<Item> opStack; // 暂存运算符的栈
511  List::dLinkList<Item> postfixList; // 后缀运算符list
512 
513  // 初始化. NAO(优先级最低)进栈
514  opStack.push(Item::nao());
515 
516  // 读中缀list
517  for (auto i = infixList.begin(); i != infixList.end(); ++i)
518  {
519  // 操作数直接输出
520  if ((*i).isOperand())
521  {
522  postfixList.push_back(*i);
523  continue;
524  }
525 
526  // 开始处理操作符
527  if ((*i).isNAO()) // 禁止非法操作符
528  throw(RpnException("Invalid expr!\n"));
529 
530  // 读到开括号, 进栈
531  if ((*i).operator_type == Item::Operator_type::Oparen)
532  {
533  opStack.push((*i));
534  continue;
535  }
536 
537  // 读到闭括号, opStack退栈直到遇到开括号
538  if ((*i).operator_type == Item::Operator_type::Cparen)
539  {
540  Item _topItem = opStack.top();
541  while (_topItem.operator_type != Item::Operator_type::Oparen)
542  {
543  opStack.pop();
544  postfixList.push_back(_topItem);
545  _topItem = opStack.top();
546  }
547  opStack.pop(); // 开括号退栈, 但不加入后缀list
548  continue;
549  }
550 
551  // 读到乘方运算符(右结合, 暂为最高优先级), 进栈
552  if ((*i).operator_type == Item::Operator_type::Exp)
553  {
554  opStack.push(*i);
555  continue;
556  }
557 
558  // 读到加减乘除(左结合), 则退栈直到栈顶操作符优先级较低或遇到开括号, 然后进栈
559  auto _pri = (*i).priority();
560  if (_pri >= Item::priOfAdd && _pri <= Item::priOfMul)
561  {
562  Item _topItem = opStack.top();
563 
564  // 当栈顶不是(开)括号(优先级0)或栈底标志NAO(优先级-1), 且栈顶优先级不低于当前运算符, 退栈
565  while (_topItem.priority() > 0 && !_topItem.hasLoPriThan((*i)))
566  {
567  opStack.pop();
568  postfixList.push_back(_topItem);
569  _topItem = opStack.top();
570  }
571 
572  // 当前运算符进栈
573  opStack.push((*i));
574  continue;
575  } // if (_pri >= Item::priOfAdd && _pri <= Item::priOfMul)
576 
577  } // for (auto i = infixList.begin(); i != infixList.end(); ++i)
578 
579  // 退栈至栈空(NAO不要进itemlist)
580  while (!opStack.top().isNAO())
581  postfixList.push_back(opStack.pop());
582 
583  return postfixList;
584 }
585 
586 // 计算(后缀)表达式的值
587 double Rpn_t::calcVal() const
588 {
589  double result; // 表达式计算结果
590  Stack::seqStack<Item> rpnStack; // 存储后缀表达式item的栈
591 
592  for (auto i = itemList.begin(); i != itemList.end(); ++i)
593  {
594  // 读到操作数, 进栈
595  if ((*i).isOperand())
596  {
597  rpnStack.push(*i);
598  continue;
599  }
600 
601  // 读到操作符, 退栈取操作数, 然后将计算结果进栈
602  if ((*i).isNAO()) // 禁止非法操作符
603  throw(RpnException("Invalid expr!\n"));
604 
605  if (rpnStack.isEmpty())
606  throw(RpnException("Invalid expr!\n"));
607  Item opR = rpnStack.pop();
608 
609  if (rpnStack.isEmpty())
610  throw(RpnException("Invalid expr!\n"));
611  Item opL = rpnStack.pop();
612 
613  rpnStack.push(Item::excOp(*i, opL, opR));
614  }
615 
616  // 读完表达式后, 栈中应只有1个元素, 此为表达式的值
617  result = (rpnStack.pop().operand_val);
618 
619  // 若栈非空, 则为非法表达式
620  if (!rpnStack.isEmpty())
621  throw(RpnException("Invalid expr!\n"));
622 
623  return result;
624 }
625 
626 // 获取表示itemList的string
627 std::string Rpn_t::itemListToStr(const List::dLinkList<Item> &itemList) const
628 {
629  std::string exprStr;
630 
631  for (auto i = itemList.begin(); i != itemList.end(); ++i)
632  {
633  exprStr += itemToStr(*i).append(" ");
634  }
635 
636  return exprStr;
637 }
638 
639 // 获取表示项(操作符/操作数)的string
640 std::string Rpn_t::itemToStr(const Item &Op) const
641 {
643  {
644  char buf[buf_size];
645 
646  int numOfCh = snprintf(buf, buf_size, "%.15g", Op.operand_val);
647  if (numOfCh > 0 && numOfCh < buf_size)
648  return buf;
649 
650  throw(RpnException("Number is too long!\n"));
651  }
652 
653  switch (Op.operator_type)
654  {
656  return "+";
657  break;
659  return ")";
660  break;
662  return "/";
663  break;
665  return "^";
666  break;
668  return "*";
669  break;
671  return "(";
672  break;
674  return "-";
675  break;
676  default:
677  return "#";
678  break;
679  }
680 
681  throw(RpnException("What's wrong with your code???\n"));
682 }
683 
684 // 运算符优先级lhs < rhs. NAO(非法运算符)的优先级为最低
685 bool Rpn_t::Item::hasLoPriThan(const Item &rhs) const
686 {
687  // 若非操作符, 恒false
688  if (rhs.item_type != Item_type::Operator)
689  return false;
690 
691  // 获取优先级
692  int8_t pri_lhs = priority();
693  int8_t pri_rhs = rhs.priority();
694 
695  if (!pri_lhs || !pri_rhs) // undefined priority
696  return false;
697 
698  return pri_lhs < pri_rhs;
699 }
700 
701 // 执行运算. 一元运算符, arg2或arg3为NAO.
702 Rpn_t::Item Rpn_t::Item::excOp(const Item &op, const Item &opL, const Item &opR)
703 {
704  if (!op.isOperator() || op.isNAO())
705  throw(RpnException("Arg1 should be a valid operator!\n"));
706 
707  switch (op.operator_type)
708  {
709  case Operator_type::Add:
710  if (!opL.isOperand() || !opR.isOperand())
711  throw(RpnException("Invalid operand!\n"));
712  return Item(opL.operand_val + opR.operand_val);
713  break;
714  case Operator_type::Div:
715  if (!opL.isOperand() || !opR.isOperand())
716  throw(RpnException("Invalid operand!\n"));
717  return Item(opL.operand_val / opR.operand_val);
718  break;
719  case Operator_type::Exp:
720  if (!opL.isOperand() || !opR.isOperand())
721  throw(RpnException("Invalid operand!\n"));
722  return Item(pow(opL.operand_val, opR.operand_val));
723  break;
724  case Operator_type::Mul:
725  if (!opL.isOperand() || !opR.isOperand())
726  throw(RpnException("Invalid operand!\n"));
727  return Item(opL.operand_val * opR.operand_val);
728  break;
729  case Operator_type::Sub:
730  if (!opL.isOperand() || !opR.isOperand())
731  throw(RpnException("Invalid operand!\n"));
732  return Item(opL.operand_val - opR.operand_val);
733  break;
734  default:
735  throw(RpnException("Invalid operator!\n"));
736  break;
737  }
738 }
739 
740 bool operator==(const Rpn_t::Item &lhs, const Rpn_t::Item &rhs)
741 {
742  if (lhs.item_type != rhs.item_type)
743  return false;
744  if (lhs.operator_type != rhs.operator_type)
745  return false;
746  return lhs.operand_val == rhs.operand_val;
747 }
748 
749 } // namespace RPN
750 
751 #endif // __RPN_HH__
List::dLinkList
Definition: dLinkList.h:23
RPN::buf_size
const int buf_size
项的最大长度 = buf_size - 1
Definition: Rpn.hh:32
RPN::Rpn_t::Item::hasLoPriThan
bool hasLoPriThan(const Item &rhs) const
Item内嵌类的工具函数
Definition: Rpn.hh:685
RPN::Rpn_t::Item::priOfMul
static const int8_t priOfMul
二元乘法的优先级(同除法)
Definition: Rpn.hh:258
RPN::Rpn_t::Item::isOperand
bool isOperand() const
是操作数
Definition: Rpn.hh:211
RPN::RpnException::RpnException
RpnException(const std::string &text="undefined exception", const std::string &id="undefined", const std::string &td="Generic ArgException")
Constructor.
Definition: Rpn.hh:54
RPN::Rpn_t::Item::isOperator
bool isOperator() const
是操作符
Definition: Rpn.hh:203
RPN::RpnException::_typeDescription
std::string _typeDescription
Describes the type of the exception.
Definition: Rpn.hh:123
RPN::RpnException
异常类
Definition: Rpn.hh:44
Stack::linkStack::push
virtual void push(const T &elem)
Definition: linkStack.hpp:76
RPN::RpnException::typeDescription
std::string typeDescription() const
Definition: Rpn.hh:104
RPN::Rpn_t::Item::Item
Item(Item_type item_type, Operator_type operator_type, double operand_val=NAN)
Construct a new Item object.
Definition: Rpn.hh:165
RPN::Rpn_t::Item::Operator_type::Mul
@ Mul
Stack::seqStack
Definition: seqStack.hxx:37
RPN::notationType::Postfix
@ Postfix
后缀表达式
Stack::linkStack
Definition: linkStack.hpp:21
Stack::linkStack::top
virtual T top() const
Definition: linkStack.hpp:100
RPN::Rpn_t::Item::Item_type::Operator
@ Operator
操作符
RPN::Rpn_t::Item::operator_type
Operator_type operator_type
操作符类型
Definition: Rpn.hh:155
RPN::Rpn_t::calcVal
double calcVal() const
计算(后缀)表达式的值
Definition: Rpn.hh:587
RPN::Rpn_t::stoItem
Item stoItem(const char *_ch, const char **_EndPtr=nullptr) const
Rpn类的工具函数
Definition: Rpn.hh:427
Stack::seqStack::push
virtual void push(const T &elem)
Definition: seqStack.hxx:86
RPN::Rpn_t::Item::Operator_type::Div
@ Div
RPN::Rpn_t::Item::nao
static Item nao()
获得一个NAO(非法操作符)
Definition: Rpn.hh:227
List.h
栈的抽象类
Stack::seqStack::isEmpty
virtual bool isEmpty() const
Definition: seqStack.hxx:80
RPN::Rpn_t::operator==
friend bool operator==(const Item &lhs, const Item &rhs)
operator==
Definition: Rpn.hh:740
RPN::Rpn_t::Item::Item
Item(double operand_val)
Construct a new Item object.
Definition: Rpn.hh:174
RPN::Rpn_t::itemToStr
std::string itemToStr(const Item &Op) const
获取表示项(操作符/操作数)的string
Definition: Rpn.hh:640
RPN::Rpn_t::postfix
std::string postfix() const
获取后缀形式的string
Definition: Rpn.hh:421
RPN::Rpn_t::Item
< 后缀式的元素: 操作数, 操作符
Definition: Rpn.hh:129
RPN
RPN 名字空间
Definition: Rpn.hh:29
RPN::Rpn_t::Item::priority
int8_t priority() const
获取优先级.
Definition: Rpn.hh:235
RPN::Rpn_t::Item::priOfAdd
static const int8_t priOfAdd
二元加法的优先级(同减法)
Definition: Rpn.hh:252
RPN::Rpn_t::postfixStr
std::string postfixStr
存储后缀形式的字符串
Definition: Rpn.hh:291
RPN::Rpn_t::Item::Operator_type::Add
@ Add
lowest(but NAO) priority: 0x01
Stack::linkStack::pop
virtual T pop()
Definition: linkStack.hpp:88
List::dLinkList::end
virtual iterator end()
Definition: dLinkList.h:145
RPN::Rpn_t::Item::Operator_type::Sub
@ Sub
RPN::Rpn_t::Item::Operator_type::NAO
@ NAO
Not an operator(lowest priority): 0xFF.
RPN::Rpn_t
Definition: Rpn.hh:126
RPN::RpnException::what
const char * what() const noexcept
Returns the arg id and error text.
Definition: Rpn.hh:91
RPN::Rpn_t::Item::Operator_type::Oparen
@ Oparen
undefine priority : 0x00
List::dLinkList::push_back
void push_back(const T &obj)
Definition: dLinkList.h:304
Stack::seqStack::pop
virtual T pop()
Definition: seqStack.hxx:104
RPN::RpnException::~RpnException
virtual ~RpnException() noexcept
Destroy the Rpn Exception object.
Definition: Rpn.hh:66
RPN::Rpn_t::Item::item_type
Item_type item_type
项的类型
Definition: Rpn.hh:154
RPN::RpnException::_errorText
std::string _errorText
The text of the exception message.
Definition: Rpn.hh:110
RPN::Rpn_t::Item::excOp
static Item excOp(const Item &op, const Item &opL=nao(), const Item &opR=nao())
执行一次运算.
Definition: Rpn.hh:702
RPN::Rpn_t::Rpn_t
Rpn_t(const std::string &expr_str="0.0", notationType exprType=notationType::Infix)
Construct a new Rpn_t object.
Definition: Rpn.hh:375
RPN::Rpn_t::itemListToStr
std::string itemListToStr(const List::dLinkList< Item > &itemList) const
获取表示itemList的string
Definition: Rpn.hh:627
RPN::Rpn_t::assign
Rpn_t & assign(const std::string &expr_str, notationType _type=notationType::Infix)
设置Rpn_t类对象的值
Definition: Rpn.hh:396
RPN::notationType
notationType
< 表达式类型
Definition: Rpn.hh:34
RPN::Rpn_t::~Rpn_t
~Rpn_t()=default
Destroy the Rpn_t object.
RPN::Rpn_t::Item::operator==
friend bool operator==(const Item &lhs, const Item &rhs)
operator==
Definition: Rpn.hh:740
RPN::Rpn_t::itemList
List::dLinkList< Item > itemList
存储后缀表达式的双链表
Definition: Rpn.hh:286
RPN::Rpn_t::exprStrToList
List::dLinkList< Item > exprStrToList(const std::string &exprStr) const
用string中的表达式创建一个list
Definition: Rpn.hh:492
RPN::Rpn_t::Item::isNAO
bool isNAO() const
是NAO?
Definition: Rpn.hh:220
RPN::Rpn_t::Item::Operator_type
Operator_type
Definition: Rpn.hh:137
Stack.hh
栈的抽象类
RPN::Rpn_t::Item::Item_type::Operand
@ Operand
操作数
RPN::notationType::Infix
@ Infix
中缀表达式
RPN::Rpn_t::Item::Item
Item(Operator_type op=Operator_type::NAO)
Construct a new Item object.
Definition: Rpn.hh:183
List::dLinkList::begin
virtual iterator begin()
Definition: dLinkList.h:136
RPN::Rpn_t::Item::Item_type
Item_type
< 项的类型
Definition: Rpn.hh:131
RPN::Rpn_t::Item::operand_val
double operand_val
操作数的值(为操作符时, 无效)
Definition: Rpn.hh:156
RPN::RpnException::_argId
std::string _argId
The argument related to this exception.
Definition: Rpn.hh:115
RPN::Rpn_t::infixListToPostfixList
List::dLinkList< Item > infixListToPostfixList(const List::dLinkList< Item > &infixList) const
用一个中缀list创建一个后缀list
Definition: Rpn.hh:508
RPN::RpnException::error
std::string error() const
Returns the error text.
Definition: Rpn.hh:73
RPN::Rpn_t::Item::Operator_type::Cparen
@ Cparen
RPN::RpnException::argId
std::string argId() const
Returns the argument id.
Definition: Rpn.hh:80
RPN::Rpn_t::Item::Operator_type::Exp
@ Exp
highest priority: 0x07