더북(TheBook)

두 스택 컨테이너에 대한 참조를 인수로 받는다. 피연산자는 operands 컨테이너에서 top()을 호출해서 얻어온다. top() 함수는 상위 원소에 접근만 한다. 따라서 다음 원소에 접근하려면 pop()을 호출해서 상위 원소를 제거해야 한다. operand 순차열은 스택에 역순으로 되어 있다. 따라서 처음 접근한 피연산자가 연산에서 오른쪽 피연산자가 된다. operators 컨테이너의 상위에 있는 원소를 switch 문에 사용해 실행할 연산을 선택한다. case 문에 해당하는 것이 없으면 익셉션을 던져서 연산자가 올바르지 않다고 알려준다.

전체 프로그램의 코드는 다음과 같다.

// Ex3_01.cpp
// 스택 컨테이너를 사용한 간단한 계산기
#include <cmath>                 // pow() 함수
#include <iostream>              // 표준 스트림
#include <stack>                 // stack<T> 컨테이너
#include <algorithm>             // remove()
#include <stdexcept>             // runtime_error 익셉션
#include <string>                // string 클래스
using std::string;
 
// precedence() 함수를 위한 코드 생략…
 
// execute() 함수를 위한 코드 생략…
 
int main()
{
  std::stack<double> operands;   // 피연산자 푸시다운 스택
  std::stack<char> operators;    // 연산자 푸시다운 스택
  string exp;                    // 평가할 계산식
  std::cout <<
              “An arithmetic expression can include the operators +, -, *, /, and ^ for exponentiation.”
            << std::endl;
  try
  {
    while (true)
    {
      std::cout << “Enter an arithmetic expression and press Enter - enter an empty line to end:”
<< std::endl;
      std::getline(std::cin, exp, ‘\n’);
      if (exp.empty()) break;
 
      // 공백을 제거한다
      exp.erase(std::remove(std::begin(exp), std::end(exp), ’ ‘), std::end(exp));
 
      size_t index {};                    // 문자열 식을 위한 인덱스
 
      // 모든 표현식에서 피연산자는 숫자로 시작해야 한다
      operands.push(std::stod(exp, &index)); // 스택에 첫 번째 피연산자(좌측값, lhs)를 넣는다
 
      while (true)
      {
        operators.push(exp[index++]);     // 연산자를 스택에 넣는다
 
                // Get rhs operand
        size_t i {}; // 서브스트링의 인덱스
        operands.push(std::stod(exp.substr(index), &i)); // 우측값 피연산자(rhs)를 넣는다
        index += i; // 식의 인덱스를 증가
        if (index == exp.length()) // 식의 끝에 도달했으면…
        {
          while (!operators.empty()) // …처리되지 않은 연산자를 실행
            execute(operators, operands);
          break;
        }
 
        // 여기까지 도달하면 처리할 연산자가 아직 남아 있다…
        // 이전 연산자와 같거나 더 높은 우선순위이면 실행한다
        while (!operators.empty() && precedence(exp[index]) <= precedence(operators.top()))
          execute(operators, operands);         // 이전 연산자를 실행한다
      }
      std::cout << “result = “ << operands.top() << std::endl;
    }
  }
  catch (const std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }
  std::cout << “Calculator ending…” << std::endl;
}
 

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.