Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /home/studb20/public_html/index.php on line 4
 Программа PARSE - ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 10) онлайн - Studbook

ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 10) онлайн

Программа PARSE

Типичные действия с программой PARSE могут выглядеть следующим образом:

Введите арифметическое выражение в виде 2+3*4/3-2 Числа должны быть из одной цифры Не используйте пробелы и скобки Выражение: 9+6/3

Результат: 11

Еще одно выражение (д/н)? н

Заметим, что результат может состоять более чем из одной цифры. Он огра- ничен только численным размером типа char, от -128 до +127. Мы ограничили лишь вводимые числа диапазоном от 0 до 9.

Вот листинг программы:

// parse.cpp

// программа разбора арифметических выражений

#include <iostream>

#include <cstring>

using namespace std;

const int LEN = 80;       // максимальная длина выражения

const int MAX = 40;       //

///////////////////////////////////////////////////////////

class Stack

{

  private:

    char st [ MAX ];      // массив данных

    int top;              // количество сохраненных данных

  public:

    Stack ( )              // конструктор

      { top = 0; }

    void push ( char var ) // поместить в стек

      { st [ ++top ] = var; }

    char pop ( )           // взять из стека

      { return st [ top-- ]; }

    int gettop ( )         // узнать количество элементов

      { return top; }

};

///////////////////////////////////////////////////////////

class express

{

  private:

    Stack s;                   // стек данных

    char* pStr;                // строка для ввода

    int len;                   // длина строки

  public:

    express ( char* ptr )      // конструктор

      {

        pStr = ptr;            // запоминаем указатель на строку

        len = strlen ( pStr ); // устанавливаем длину

      }

 

void parse ( );            // разбор выражения

    int solve ( );             // получение результата

};

///////////////////////////////////////////////////////////

void express::parse ( ) // добавляем данные в стек

{

  char ch;              // символ из строки

  char lastval;         // последнее значение

  char lastop;          // последний оператор

  for ( int j = 0; j < len; j++ ) // для всех символов в строке

  {

    ch = pStr [ j ];    // получаем символ

 

    if ( ch >= '0' && ch <= '9' ) // если это цифра,

      s.push ( ch - '0' );        // то сохраняем ее значение

    else

    if ( ch == '+' || ch == '-' || ch == '*' || ch == '/' )

    {

      if ( s.gettop ( ) == 1 ) // если это первый оператор,

        s.push ( ch );         // помещаем его в стек

      else // иначе

      {

        lastval = s.pop ( ); // получаем предыдущее число

        lastop = s.pop ( );  // получаем предыдущий оператор

        // если это * или /, а предыдущий был + или -, то

        if ((ch == '*' || ch == '/') && (lastop == '+' || lastop == '-'))

        {

          s.push ( lastop ); // отменяем последние два взятия из стека

          s.push ( lastval );

        }

        else

        {

          // помещаем в стек результат операции

          switch ( lastop )

          {

            case '+': s.push ( s.pop ( ) + lastval ); break;

            case '-': s.push ( s.pop ( ) - lastval ); break;

            case '*': s.push ( s.pop ( ) * lastval ); break;

            case '/': s.push ( s.pop ( ) / lastval ); break;

            default: cout << "\nНеизвестный оператор"; exit ( 1 );

          }

        }

        s.push ( ch ); // помещаем в стек текущий оператор

      }

    }

    else               // какая-то ерунда...

    {

      cout << "\nНеизвестный символ";

      exit ( 1 );

    }

  }

}

///////////////////////////////////////////////////////////

int express::solve ( ) // убираем данные из стека

{

  char lastval;        // предыдущее значение

  while ( s.gettop ( ) > 1 )

{

    lastval = s.pop ( ); // получаем предыдущее значение

    switch ( s.pop ( ) ) // получаем предыдущий оператор

    {

      case '+': s.push ( s.pop ( ) + lastval ); break;

      case '-': s.push ( s.pop ( ) - lastval ); break;

      case '*': s.push ( s.pop ( ) * lastval ); break;

      case '/': s.push ( s.pop ( ) / lastval ); break;

      default: cout << "\nНеизвестный оператор"; exit ( 1 );

    }

  }

  return int ( s.pop ( ) ); // последний оператор в стеке – это результат

}

///////////////////////////////////////////////////////////

int main ( )

{

  char ans;            // 'д' или 'н'

  char string [ LEN ]; // строка для разбора

 

  cout << "\nВведите арифметическое выражение в виде 2+3*4/3-2"

          "\nЧисла должны быть из одной цифры"

          "\nНе используйте пробелы и скобки";

  do

  {

    cout << "\nВыражение: ";

    cin >> string;                          // вводим строку

    express* eptr = new express ( string ); // создаем объект для разбора

    eptr->parse ( );                        // разбираем

    cout << "\nРезультат: "

         << eptr->solve ( );                // решаем

    delete eptr;                            // удаляем объект

    cout << "Еще одно выражение (д/н)? ";

    cin >> ans;

  }

  while ( ans == 'д' );

  return 0;

}

 

Это длинная программа, но в ней показано, как разработанный ранее класс Stack был применен в другой ситуации. Кроме того, программа демонстрирует различные случаи использования указателей и показывает, как полезно пред- ставлять строки в виде массива символов.

 

46