ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В 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 был применен в другой ситуации. Кроме того, программа демонстрирует различные случаи использования указателей и показывает, как полезно пред- ставлять строки в виде массива символов.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
