русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Лабораторная работа №10


Дата добавления: 2015-07-09; просмотров: 586; Нарушение авторских прав


Тема: “Вычисление выражений, вводимых с клавиатуры”

В этой работе рассматривается одна из интереснейших и труднейших тем программирования: разбор выражений. В программировании известны различные подходы к решению этой задачи. В этой работе рассматривается рекурсивно-нисходящий алгоритм разбора выражений. Вычисление выражения выполняется с помощью шаблонного класса, при этом подразумевается, что выражение - числовое, вычисляемое по законам алгебры.

Основой для построения числового выражения служат следующие элементы: числа, операции (+, -, *, /, ^ - возведение в степень, %, =), скобки, переменные. Имена переменных рассматриваются как одиночные латинские буквы, регистр не имеет значения. В приведенной ниже версии реализованы минимальные возможности по обработке ошибок для того, чтобы не перегружать программу.

Пример: Шаблонный класс для вычисления значения выражения, вводимого с клавиатуры

Нижеследующая программа является консольным приложением Windows.

#define _USE_MATH_DEFINES

#include <iostream>

#include <conio.h>

#include <windows.h>

#include <stdio.h>

#include <ctype.h>

#include <string.h>

#include <stdlib.h>

#include <cmath>

using namespace std;

 

#define NUMVARS 26 // размер массива для хранения значений переменных

 

template <class PType> class CParser //анализатор

{

//типы элементов выражения:

enum types {DELIMITER = 1, VARIABLE, NUMBER};

//разделитель, переменная, число

// элементы данных класса:

char* exp_ptr; // Указатель на выражение

char token[80]; // Элемент выражения

char tok_type; // Тип элемента

//функции:

int isdelim(char c); // проверяет, является ли элемент разделителем

void get_token(); /* выбирает из строки очередной элемент выражения, помещает его в строку token и определяет его тип */



void putback();//возврат в выражении на 1 элемент назад:

void eval_exp1(PType &result); // присваивание

void eval_exp2(PType &result); // Сложение и вычитание

void eval_exp3(PType &result); // Умножение, деление, остаток от деления

void eval_exp4(PType &result); // Возведение в степень

void eval_exp5(PType &result); // Унарный плюс или минус

void eval_exp6(PType &result); // Обработка выражения в скобках

void atom (PType &result); // Значение числа

void serror(int error); // вывод сообщения об ошибке

PType find_var(char* s); // возвращает значение переменной

public:

CParser(); // конструктор

PType vars[NUMVARS]; // массив значений переменных

PType eval_exp(char *exp); //точка входа

} ;

 

//определение функций:

// записываем нули в массив значений переменных:

template <class PType> CParser<PType>::

CParser()

{

exp_ptr = NULL;

for (int i=0; i<NUMVARS; i++)

vars[i]=0;

}

 

// Функция, проверяющая, является ли элемент разделителем:

template <class PType> int CParser<PType>::

isdelim(char c)

{

if (strchr(" +-/*%^=()",c) || c==9 || c=='\r' || c==0)

return 1;

else return 0;

}

 

//Функция, которая выбирает из выражения очередной элемент

template <class PType> void CParser<PType>::

get_token()

{

register char *temp = token; //Указатель на token

*temp='\0';

tok_type=0;

if (! *exp_ptr) return; //Конец выражения

while (isspace(*exp_ptr)) ++exp_ptr; // Пропускаем пробелы

if (strchr("+-*/%^=()", *exp_ptr)) // Если очередной символ - знак операции

{

tok_type=DELIMITER;

*temp++ = *exp_ptr++; //Продвигаемся к след. символу

}

else if (isalpha(*exp_ptr))

{

tok_type=VARIABLE;

while (!isdelim(*exp_ptr)) *temp++ = *exp_ptr++;

while (isspace(*exp_ptr)) ++exp_ptr;

//if (*exp_ptr == '(') tok_type=FUNCTION;

}

else if (isdigit(*exp_ptr))

{

tok_type = NUMBER;

while (!isdelim(*exp_ptr)) *temp++ = *exp_ptr++;

}

*temp = '\0';

}

// точка входа в программу разбора выражения:

template <class PType> PType CParser<PType>::

eval_exp(char *exp)

{

PType result;

exp_ptr = exp;

get_token(); // 1 - ый операнд

if (! *token)

{

serror(2); //Нет выражения

return 0;

}

eval_exp1(result);

if(*token) serror(0);

return result;

}

 

//возврат в выражении на 1 элемент назад:

template <class PType> void CParser<PType>::

putback()

{

char *t = token;

for (; *t; t++) exp_ptr--;

}

 

//присваивание:

template <class PType> void CParser<PType>::

eval_exp1(PType &result)

{

int slot;

char ttok_type;

char temp_token[80];

if (tok_type == VARIABLE)

{

//сохранить старый элемент:

strcpy(temp_token, token);

ttok_type = tok_type;

//вычисление индекса переменной:

slot = toupper(*token)-'A'; get_token();

if (*token != '=')

{

putback(); //вернуть текущий элемент

//восстанавливаем предыдущий элемент

strcpy(token, temp_token);

tok_type = ttok_type;

}

else

{

get_token();

eval_exp2(result);

vars[slot] = result;

return;

}

}

eval_exp2(result);

}

 

// Сложение и вычитание:

template <class PType> void CParser<PType>::

eval_exp2(PType &result)

{

register char op;

PType temp;

eval_exp3(result);

while ( ( op = *token ) == '+' || op == '-')

{

get_token();

eval_exp3(temp);

switch (op)

{

case '+':

result+=temp;

break;

case '-':

result-=temp;

break;

}

}

}

 

// Умножение, деление, остаток от деления:

template <class PType> void CParser<PType>::

eval_exp3(PType &result)

{

register char op;

PType temp;

eval_exp4(result);

while ( ( op = *token) == '*' || op == '/' || op == '%')

{

get_token();

eval_exp4(temp);

switch (op)

{

case '*':

result*=temp;

break;

case '/':

result/=temp;

break;

case '%':

result=(int)result % (int) temp;

break;

}

}

}

 

// Возведение в степень:

template <class PType>void CParser<PType>::

eval_exp4(PType &result)

{

PType temp;

eval_exp5(result);

if ( *token == '^')

{

get_token();

eval_exp4(temp);

result=pow(result,temp);

}

}

 

// Унарный плюс или минус:

template <class PType>void CParser<PType>::

eval_exp5(PType &result)

{

register char op;

op=0;

if ((tok_type == DELIMITER) && *token == '+'

|| *token == '-')

{

op= *token;

get_token();

}

eval_exp6(result);

if (op == '-') result = -result;

}

 

// Обработка выражения в скобках:

template <class PType>void CParser<PType>::

eval_exp6(PType &result)

{

if ( *token == '(' )

{

get_token();

eval_exp1(result); // вычисляем выражение в скобках

if (*token != ')')

serror(1);

get_token();

}

else atom(result);

}

 

// Значение числа:

template <class PType>void CParser<PType>::

atom (PType &result)

{

switch (tok_type)

{

case NUMBER:

result = atof(token);

get_token(); return;

case VARIABLE:

result = find_var(token);

get_token(); return;

default: serror(0);

}

}

// вывод сообщения об ошибке:

template <class PType>void CParser<PType>::

serror(int error)

{

static char *e[]=

{

"Синтаксическая ошибка",

"Незакрытые скобки",

"Выражение записано неверно"

};

cout << e[error] << endl;

}

 

// возвращает значение переменной:

template <class PType>PType CParser<PType>::

find_var(char* s)

{

if (!isalpha(*s))

{

serror(1);

return 0;

}

int i=toupper(*token) - 'A';

return vars[i];

}

// файл “Calculator.cpp” :

/*#include <iostream>

#include <conio.h>

#include <windows.h>*/

#include "calculator.h"

//using namespace std;

 

int main()

{

//Настройки шрифтов и региональных стандартов:

if(SetConsoleCP(1251)==0)

//проверка правильности установки кодировки символов для ввода

{

cerr<<"Fialed to set codepage!"<<endl;

/* если не удалось установить кодовую страницу, вывод сообщения об ошибке */

}

if(SetConsoleOutputCP(1251)==0)//тоже самое для вывода

{

cerr<<"Failed to set OUTPUT page!"<<endl;

}

CParser <double> ob;

char expstr[81];

cout<<" Для выхода из программы введите пустое выражение (нажмите <Enter>)\n";

while(1)

{

cout<<"Введите выражение ";

cin.getline(expstr, 80);

if (expstr[0] == 0) break;

cout<<"Результат = ";

cout<<ob.eval_exp(expstr) << endl;

}

_getch();

return 0;

}

Запустите программу (<Ctrl>+<F5>) и введите несколько выражений, например:

x = -2.5

3 * (x – 1.5^2)

Убедитесь в правильности работы программы.

 



<== предыдущая лекция | следующая лекция ==>
Задания для самостоятельного выполнения | КОРОТКИ ТЕОРЕТИЧНІ ВІДОМОСТІ


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 3.164 сек.