отчет. Руководство по использованию программы 11 Заключение 12 Список литературы 13 Приложение а 14 Приложение б 16
Скачать 161.49 Kb.
|
Содержание1.Техническое задание 2 2.Введение 4 3.Общий раздел 6 4.Технологический раздел 7 5.Руководство по использованию программы 11 6.Заключение 12 7.Список литературы 13 8.Приложение А 14 9.Приложение Б 16 1.Техническое заданиеЦели создания и назначение программы Необходимо разработать программу, которая бы вычисляла арифметическое выражение, введенное с клавиатуры. Арифметическое выражение может содержать числа (в том числе экспоненциальной форме), символы арифметических операций, скобки, функции синуса, косинуса, тангенса, логарифма, экспоненты. Требования к программе Программа должна иметь возможность ввода пользователем арифметического выражения, вычисляемое в дальнейшем. Она должна иметь понятный вывод и сообщение о найденной ошибке, если есть. В программе должен производиться контроль за вводимыми пользователем данными с клавиатуры. В случае введения некорректных данных, программа выводит сообщение об ошибке и завершается. Если же ошибок не допущено, то можно продолжить вычисления, вводя новое выражение. Требования к составу технических средств: операционная система Windows, ПЭВМ в стандартном окружении. Требования к информационной и программной совместимости: на этапе проектирования программной системы необходимо использовать методы и приёмы объектно-ориентированного анализа. После анализа предполагаемых к использованию объектов и также их взаимодействия необходимо разработать соответствующих им классы и методы, а также разработать алгоритмы их взаимодействия, а затем перейти к поэтапной разработке и тестированию создаваемой программной системы. Желательно поэтапно проектировать программу, на каждом шаге добавляя по одному блоку и каждый этап тщательно отлаживать. Разработанная программа должна быть реализована на объектно-ориентированном языке программирования С++ в любой интегрированной среде разработки. 1.3 Требования к программной документации В ходе работы над данным проектом необходимо разработать следующие документы: техническое задание, пояснительная записка. 1.4 Порядок контроля и приема Контроль работы будет производиться путем проверки работоспособности функций программы в формате ввода разных данных предполагаемого формата (арифметические выражения). Стадии и этапы разработки 1 этап: Разработка структуры входных и выходных данных. 2 этап: Разработка алгоритма решения задачи. 3 этап: Разработка структуры программы. 4 этап: Разработка тестов. 5 этап: Написание текста программы. 6 этап: Отладка программы. 7 этап: Написание и оформление отчета о выполненной работе в виде пояснительной записки. 2.ВведениеДанная курсовая работы выполняется с целью развития навыков ведения самостоятельной работы и овладения методикой анализа и приспособляемости при решении разрабатываемых проблем и вопросов. Курсовая работа включает в себя алгоритмизацию и разработку приложения по методологии объектно-ориентированного программирования, моделирующих процедуры работы с динамическими списками. Разработка приложения велась на языке программирования С++. Данный язык программирования является одним из самых популярных и распространенных инструментов разработки программного обеспечения. С++ обладает высокой производительностью, способствующей оперативной работе с ресурсами системы, что приводит к высокой скорости выполнения поставленных задач. Стоит также отметить, что данный язык программирования обладает обширной библиотекой классов, шаблонов и методов, способствующей эффективной разработке программного обеспечения. В качестве среды разработки была выбрана Microsoft Visual Studio - один из наиболее удобных и полных продуктов, используемых для разработки программного обеспечения. Высокоскоростная и удобная для программирования система предлагает широкий набор разнообразных инструментов проектирования для любого пользователя. 3.Общий разделТема данной работы знакома многим. В наше время возросла потребность в обработке данных, особенно это заметно в сфере образования. Сегодня многие простейшие выражения можно переложить на плечи уже созданных алгоритмов и самим занимать тем, что пока недоступно машинному разуму. Одной из таких программ-помощников является данная работа - программа «Инженерный калькулятор», выполняющая как основные арифметические выражения, так и более сложные – косинусы, синусы, тангенсы, логарифмы. Целью данной курсовой работы является получение практических навыков в области программирования и области структур и алгоритмов обработки данных. Для решения поставленной задачи необходимо выполнить следующие задачи: Ознакомиться со способами организации данных и выбрать наиболее подходящий для выполнения курсовой работы Ознакомиться с выбранной средой разработки, в данном случае Visual Studio Сформулировать логическую структуры программы Разработать программу «Инженерный калькулятор» В качестве способа организации данных при вычислениях был выбран std::vector. Это контейнер с последовательным доступом к элементам. Элементы хранятся непрерывно, а значит доступны не только через итераторы, но и через смещения, добавляемые к указателям на элементы. Это означает, что указатель на элемент вектора может передаваться в любую функцию, ожидающую указатель на элемент массива. 4.Технологический разделКонсольное приложение «Инженерный калькулятор» - программный продукт, позволяющий получить результат выполнения вычислений. Логическая структура программы опирается на объектно-ориентированный подход к программированию, который заключается в представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса. Хранение данных реализовано с помощью структуры данных vector, реализованной в библиотеке STL. Ввод данных в программу осуществляется путем ввода пользователем требуемых программой данных с помощью клавиатуры. Вывод данных осуществляется на экран в консоль программы, также предусмотрено последующий ввод данных для вычисления новых значений. Выход из программы происходит при нарушении формата ввода, либо же при вводе «exit» в поле ввода. Класс EngineeringCalculator Класс Employee является начальным для данной программы, имея в своем составе main Методы класса Employee: void main() – стартовая точка программы, также содержит ввод арифметического выражения Класс Calculate Класс Calculate является основным классом программы по обработке данных, введенных пользователем. Все атрибуты класса имеют спецификатор доступа private. Публично доступны лишь конструктор и метод getAnswer() Основные атрибуты класса Calculate: bool unary – булевая переменная, указывающая унарная ли операция. vector vector Методы класса Calculate: Calculate(string &formula) – конструктор, содержащий в себе соновную обработку поданного выражения. double getAnswer() – получить ответ по запросу. bool operation(char c) – проверка является ли символом из «библиотеки». int prioritet(char op) – получить приоритет операнда для упорядочивания вычислений. void action(vector Класс ComplexElements Класс ComplexElements реализует разбор таких «сложных» элементов как тригонометрические выражения, логарифмы и экспонента. Методы класса ComplexElements: ComplexElements(string& formula) – конструктор, содержащий в себе основную обработку «сложных» операндов. string forE(string origin, int j) – специальный метод для е, перестраховка на случай е как экспоненциальной записи. Класс Check Класс Check реализует простейшие проверки введенных данных. Атрибуты класса Check: string temp; - сохранение переданной строки для использования в проверках. Методы класса Check: Check(string formula) – конструктов в котором сохраняется переданная строка в собственную переменную и вызываются методы проверки. bool character(char c) – проверка принадлежит ли символ «библиотеке» или является ли цифрой void firstCheck() – проверка на излишнее количество скобок и двойные операнды void secondCheck() – проверка на наличие неразрешенных символов. Рис.4.1. Диаграмма классов 5.Руководство по использованию программыВ программе реализован интуитивно понятный интерфейс(Рис.5.1.). Вот как выглядит обычное выполнение программы: Рис.5.1. Интерфейс программы При вводе данных имеющих неподходящий формат(Рис.5.2.) или в итоге имеющих неразрешенное значение(Рис.5.3.) выдается сообщение “Incorrect input” и программа завершается Рис.5.2. Неправильный формат Рис.5.3. Отрицательное значение в логарифме 6.ЗаключениеВ ходе данной работы были получены практические навыки алгоритмизации и разработки приложений, моделирующих процедуры работы с динамическими списками. Была разработана программа «Инженерный калькулятор», выполняющая требования, изложенные в Техническом Задании и имеющая интуитивно понятный интерфейс. В результате были изучены разработки и проектирования моделей управления структурами данных в среде программирования С++. Полученные навыки способствуют пониманию и послужат осознанному использованию сложных структур данных для применения в компьютерных системах управления и автоматизации процессов. 7.Список литературы1. Павловская Т.А., Щупак Ю.А. С/С++. Структурное программирование. Практикум. – СПб.: Питер, 2002. Первое обращение – 20.10.18 2. Подбельский В.В. Язык С++; Учебное пособие. М.: Финансы и статистика, 1996. Первое обращение – 28.09.18 3. Павловская Т.А. С/С++. Программирование на языке высокого уровня. – СПб.: Питер, 2002. Первое обращение – 20.10.18 4. Дейтл Х.М., Дейтл П.Дж. Как программировать на С. – М.: Бином, 2004. Первое обращение – 20.10.18 5. Турчак Л.И. Основы численных методов. – М.: Наука, 1978. Первое обращение – 24.10.18 6. Ахо А., Хопкрофт Джон, Ульман Джеффри «Структуры данных и алгоритмы», М: Издательский дом «Вильямс», 2000. Первое обращение – 24.10.18 8.Приложение АРис.8.1. Краткая блок-схема функционирования программы 9.Приложение БКласс EngineeringCalculator #include "pch.h" #include #include "Calculate.h" #include "ComplexElements.h" #include using namespace std; int main() { string str; bool isFirst = true; cout << "Enter your formula: "; cin >> str; while (!(str.size() == 4 && str[0] == 'e' && str[1] == 'x' && str[2] == 'i' && str[3] == 't')) { if (!isFirst) { system("cls"); cout << "Enter your formula: "; cin >> str; } isFirst = false; string origin = str; // Для отображаения изначально введенной формулы ComplexElements task(str); Calculate ans_task(str); //запуск вычисления ответа cout << "Your formula: " << origin << " -> " << str << endl; //Вывод изначальной формулы и ее упрощенноего вараинта(все сложные функции вычислены и посдтавленны числа) cout << ans_task.getAnswer() << endl << endl; system("pause"); } cout << "End" << endl; system("pause"); } Класс Calculate #include "pch.h" #include "Calculate.h" #include "Check.h" #include "ComplexElements.h" #include #include #include using namespace std; bool unary = true; // создадим булевскую переменную для распределения операторов на унарные и бинарные vector vector Calculate::Calculate(string & formula) { ComplexElements a(formula); //заменяем возможные сложные функции на их числовое представление Check b(formula); //Проверки введенных данных unary = true; int pos = formula.find("--"); // для замены двух минусов на + int i = 0; while (pos != -1) { string h = formula.substr(pos + 2, i - 1); formula.replace(pos, i + 2, "+"); pos = formula.find("--"); } pos = formula.find("++"); // замена двух плюсов на один i = 0; while (pos != -1) { string h = formula.substr(pos + 2, i - 1); formula.replace(pos, i + 2, "+"); pos = formula.find("++"); } for (int i = 0; i < formula.size(); i++) { /*cout << "iterator: " << i << endl; cout << "Value1" << endl; for (int i = 0; i < value.size(); i++) { cout << value[i] << endl; }*/ /*cout << "Formula: " << formula << endl;*/ if (formula[i] == '(') { //если текущий элемент — открывающая скобка, то положим её в стек op.push_back('('); unary = true; } else if (formula[i] == ')') { //если закрывающая скобка - выполняем все операции, находящиеся внутри этой скобки while (op.back() != '(') { action(value, op.back()); op.pop_back(); } op.pop_back(); unary = false; } else if (operation(formula[i]) || (formula[i]=='-' && !isdigit(formula[i+1]) && !isdigit(formula[i - 1]))) { //если данный элемент строки является одни из операндов, то char znak = formula[i]; if (unary == true)znak = -znak; //придает отрицательное значение, для распознавания функции унарности оператора while (!op.empty() && prioritet(op.back()) >= prioritet(znak)) { action(value, op.back()); //выполняем сами алгебраические вычисления, где все уже операции упорядочены op.pop_back(); //в одном из стеков по строгому убыванию приоритета, если двигаться от вершины } op.push_back(znak); unary = true; } else { string number; //заведем строку для найденных числовых операндов bool isMinus = true; /* (i!=0 && formula[i-1] == '-') { number += '-'; }*/ while (i < formula.size() && (isdigit(formula[i]) || formula[i] == '.' || formula[i] == 'e' || (formula[i] == '-' && isMinus && formula[i - 1] == 'e'))) { //распознаем значения, включая те, что в экспоненциальной форме if (formula[i] == '-') { isMinus = false; } number += formula[i++]; } i--; value.push_back(atof(number.c_str())); //поместим в вектор с числовыми выражениями unary = false; } /*cout << "Value2" << endl; for (int i = 0; i < value.size(); i++) { cout << value[i] << endl; }*/ } while (!op.empty()) { //выполним еще не использованные операции action(value, op.back()); op.pop_back(); } //по итогу получаем результат как единственный элемент вектора значений } double Calculate::getAnswer() { /*cout << "result" << endl; for (int i = 0; i < value.size(); i++) { cout << value[i] << endl; }*/ return value.back(); //получить результат вычислений } bool Calculate::operation(char c) { return c == '+' || c == '-' || c == '*' || c == '/' || c == '^'; // "библиотека операндов } int Calculate::prioritet(char op) //данная функция будет возвращать приоритет поступившей операции { if (op < 0) return 3; else { if (op == '+' || op == '-')return 1; else if (op == '*' || op == '/')return 2; else if (op == '^')return 4; else return -1; } } void Calculate::action(vector { if (op < 0) { //для унарных операций double unitar = value.back(); value.pop_back(); if (-op == '-')value.push_back(-unitar); } else { //для бинарных операций double right = value.back(); value.pop_back(); double left = value.back(); value.pop_back(); //cout << op << " " << left << " " << right << " " << pow(left, right) << endl; if (op == '+')value.push_back(left + right); else if (op == '-')value.push_back(left - right); else if (op == '*')value.push_back(left*right); else if (op == '/')value.push_back(left / right); else if (op == '^')value.push_back(pow(left, right)); } } Класс ComplexElements #include "pch.h" #include "ComplexElements.h" #include "Calculate.h" #include #include #include #include #include using namespace std; #define PI 3.14159265 ComplexElements::ComplexElements(string & formula) { int pos = formula.find("sin("); // Каждая из функций обрабатывается похожим образом - здесь находим координату первого вхождения функции(если есть) int i = 0; while (pos != -1) { string temp = formula.substr(pos + 4); //обрезаем кусок после нее int k = 1; i = 0; for (; i < temp.size() && k != 0; i++) { //Здесь с помощью подсчета для нахождения закрывающей скобки вычисляем координату завершения тела функции if (temp[i] == '(') { k++; } if (temp[i] == ')') { k--; } } temp = formula.substr(pos + 4, i - 1); //выделяем это тело Calculate res(temp); //вычисляем тело функции formula.replace(pos, i + 4, "(" + to_string(sin(res.getAnswer()/** PI / 180*/)) + ")");//выполняем функцию на вычисленное значение и заменяем эту функцию вычесленным значением(по умплчанию синус/косинус/тангенс обрабаотывают значения в радианах) pos = formula.find("sin(");//находим точку входа следующей функции, если ее нет, то pos=-1 и мы выходим их цикла } pos = formula.find("cos("); i = 0; while (pos != -1) { string temp = formula.substr(pos + 4); int k = 1; i = 0; for (; i < temp.size() && k != 0; i++) { if (temp[i] == '(') { k++; } if (temp[i] == ')') { k--; } } temp = formula.substr(pos + 4, i - 1); Calculate ans(temp); formula.replace(pos, i + 4, "(" + to_string(cos(ans.getAnswer()/** PI / 180*/)) + ")"); pos = formula.find("cos("); } pos = formula.find("tan("); i = 0; while (pos != -1) { string temp = formula.substr(pos + 4); int k = 1; i = 0; for (; i < temp.size() && k != 0; i++) { if (temp[i] == '(') { k++; } if (temp[i] == ')') { k--; } } temp = formula.substr(pos + 4, i - 1); Calculate ans(temp); formula.replace(pos, i + 4, "(" + to_string(tan(ans.getAnswer()/** PI / 180*/)) + ")"); pos = formula.find("tan("); } pos = formula.find("ln("); i = 0; while (pos != -1) { string temp = formula.substr(pos + 3); int k = 1; i = 0; for (; i < temp.size() && k != 0; i++) { if (temp[i] == '(') { k++; } if (temp[i] == ')') { k--; } } temp = formula.substr(pos + 3, i - 1); Calculate ans(temp); formula.replace(pos, i + 4, "(" + to_string(log(ans.getAnswer())) + ")"); pos = formula.find("ln("); } pos = formula.find("log("); i = 0; while (pos != -1) { string temp = formula.substr(pos + 4); int k = 1; i = 0; for (; i < temp.size() && k != 0; i++) { if (temp[i] == '(') { k++; } if (temp[i] == ')') { k--; } } temp = formula.substr(pos + 4, i - 1); Calculate ans(temp); formula.replace(pos, i + 4, "(" + to_string(log10(ans.getAnswer())) + ")"); pos = formula.find("log("); } for (int j = 0; j < formula.size(); j++) { //для экспоненты мы должны проверять,0 что это не e из записи числа. if (formula[j] == 'e') { if (j == 0 || j == formula.size() - 1 || (!isdigit(formula[j - 1]) && (formula[j + 1] != '-' || !isdigit(formula[j + 1])))) { formula = forE(formula, j); } } } } string ComplexElements::forE(string origin, int j) { string temp = origin.substr(0, j); origin = temp + to_string(exp(1)) + origin.substr(j + 1, origin.size() - 1); return origin; } Класс Check #include "pch.h" #include "Check.h" #include #include using namespace std; string temp; Check::Check(string formula) { temp = formula; firstCheck(); //проверка на двойные операнды(кроме -- и ++) и на количество закрывающих и открывающих скобок secondCheck(); //проверка на недопустимые значения и на частные случаи неверного расположения элементов } void Check::firstCheck() { int k = 0; for (int i = 0; i < temp.size(); i++) { if (temp[i] == '(') { k++; } if (temp[i] == ')') { k--; } if (k < 0) { cout << "Incorrect input"; system("pause"); exit(1); } } if (k != 0) { cout << "Incorrect input"; system("pause"); exit(1); } if (temp.find("**") != -1 && temp.find("//") != -1 && temp.find("^^") != -1 && temp.find(".") != -1) { cout << "Incorrect input"; system("pause"); exit(1); } } bool Check::character(char c) { return isdigit(c) || c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == 'e' || c == '.' || c == '(' || c == ')'; } void Check::secondCheck() { for (int i = 0; i < temp.size(); i++) { if (character(temp[i])) { if (i == temp.size() - 1) { if (temp[i] != 'e' && temp[i] != ')' && !isdigit(temp[i])) { //проверка чтобы не заканчивалось на операнд cout << "Incorrect input" << endl; system("pause"); exit(6); } } else if (i == 0) { if (temp[i] != 'e' && temp[i] != '(' && temp[i] != '-' && !isdigit(temp[i])) { //проверка чтобы не начиналось с опреанда cout << "Incorrect input" << endl; system("pause"); exit(4); } } } else { cout << "Incorrect input" << endl; system("pause"); exit(3); } } } |