【C++ 程序】 TVJ Complex Calculator (v 2.1) 复数计算器

The latest version

【C++ 程序】 TVJ Complex Calculator (v 2.2) 复数计算器


简介

这是一个用 Visual C++ 做的控制台界面复数计算器程序,支持多种复数有关运算以及混合运算。
icon
Version

系统要求:Windows

应用程序下载

链接:https://download.csdn.net/download/weixin_50012998/13211328

Help

What is new in v 2.1

  • add the calculator function
  • solve bugs

Simple test

  • (此功能可以跳过)

  • 输入复数一行两个实数,分别代表实部和虚部。(以回车结束)

  • 输入实数一行一个数。(以回车结束)

  • 如果输入错误则会有错误提示,要求重新输入。

  • simple test 结束后自动进入计算器模式。

  • 示例:
    simple test

输入要求

各符号含义:

  • + 加法(双目)/正号(单目,仅限于式子开头和括号内的开头)
  • - 减法(双目)/负号(单目,仅限于式子开头和括号内的开头)
  • * 乘号(双目)
  • / 除号(双目)
  • ^ 乘方(双目)(此处仅支持次数为实数,若系数为复数,则虚部被忽略)
  • () 括号
  • [] 取模
  • <> 取共轭复数

注:

  • 输入各字符间可以有空格
  • 输入支持括号之间的乘号省略
  • 输入以回车结束

正确示例:
correct

错误示例:

  • 数学错误:除数不能为0!
    E1

  • 语法错误(没有配对的括号)
    E2

  • 不是英文字符(下图为输入了中文括号)
    E3

  • 语法错误E4

  • 语法错误(未定义的符号)E5

  • 输入错误数据E6

警告示例:

  • 指数的虚部被忽略。
    W1
    W2

程序

Main.cpp

/*
 * Project: Complex
 * File: Main.cpp
 * -----------------
 *
 * @author Teddy van Jerry
 *
 * @version 2020/12/01
 * - modify according to calculator.cpp
 * @version 2020/11/29
 * - add the header Curcor.h
 * @version 2020/11/28
 * - modify the input section
 * @version 2020/11/27
 * - modify the input section
 * @version 2020/11/26
 * - initial version
 */

#include <iostream>
#include <sstream>
#include <Windows.h>
#include <conio.h>
#include "Complex.h"
#include "Calculator.h"
#include "Cursor.h"
using namespace std;

Complex zero(0, 0);

// set the colour green
void set_green()
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
}

// set the colour yellow
void set_yellow()
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
}

// set the colour white
void set_white()
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}

void init()
{
	cursor("hide");
	set_green();
	cout << "TVJ Complex Calculator(v 2.1)\n=============================\n" << endl;
	MessageBox(NULL, L"This is TVJ Complex Calculator (v 2.1)\nDesigned by\nTeddy van Jerry,\nStudent 1,\nStudent 2,\nStudent 3\n2020.12",
		L"Information", MB_ICONINFORMATION);
	int choice_help = MessageBox(NULL, L"Want to see HELP?", L"TVJ Complex Calculator", MB_YESNO | MB_ICONINFORMATION);
	if (choice_help == IDYES)
	{
		// go to my CSDN blog
		ShellExecute(NULL, L"open", L"explorer.exe", L"https://blog.csdn.net/weixin_50012998/article/details/110428837", NULL, SW_SHOW);
	}
}

void simple_test()
{
	Complex a, b;
	double n;
	cursor("show");
	/**
	 * Input
	 * @ written by Teddy van Jerry
	 */
re_input1:
	set_yellow();
	cout << "Please input complex number a: ";
	set_white();
	cin >> a;
	if (cin.fail()) // if it is illegal input
	{
		error(L"Illegal input!");
		cin.clear();
		cin.ignore(1, '\n');
		goto re_input1; // try again
	}

re_input2:
	set_yellow();
	cin.ignore(100, '\n');
	cout << "Please input complex number b: ";
	set_white();
	cin >> b;
	if (cin.fail()) // if it is illegal input
	{
		error(L"Illegal input!");
		cin.clear();
		cin.ignore(1, '\n');
		goto re_input2; // try again
	}

re_input3:
	set_yellow();
	cin.ignore(100, '\n');
	cout << "Please input a real number: ";
	set_white();
	cin >> n;
	if (cin.fail()) // if it is illegal input
	{
		error(L"Illegal input!");
		cin.clear();
		cin.ignore(1, '\n');
		goto re_input3; // try again
	}

	cursor("hide"); // hide the cursor

	/**
	 * Test
	 * @ written by Teddy van Jerry
	 */
	cout << "\nThe real part of (" << a << ") is " << a.getReal() << endl;
	cout << "The real part of (" << b << ") is " << b.getReal() << endl;
	cout << "The imaginary part of (" << a << ") is " << a.getImaginary() << endl;
	cout << "The imaginary part of (" << b << ") is " << b.getImaginary() << endl;
	cout << "The conjugate of (" << a << ") is " << a.conjugate() << endl;
	cout << "The conjugate of (" << b << ") is " << b.conjugate() << endl;
	cout << "The modulus of (" << a << ") is " << a.modulus() << endl;
	cout << "The modulus of (" << b << ") is " << b.modulus() << endl;
	cout << "-a = " << zero - a << endl;
	cout << "-b = " << zero - b << endl;
	cout << "(" << a << ")^" << n << " = " << (a ^ n) << endl;
	cout << "(" << b << ")^" << n << " = " << (b ^ n) << endl;
	cout << "a + b = " << a + b << endl;
	cout << "a - b = " << a - b << endl;
	cout << "a * b = " << a * b << endl;
	cout << "a / b = " << a / b << endl;
}

int main(int argv, int** argc)
{
	init();

	// give the choice
	int choice = MessageBox(NULL, L"Want to have a simple test first?", L"Information", MB_ICONINFORMATION | MB_YESNO);
	if (choice == IDYES) // if choose yes
	{
		simple_test();
		cout << endl;
		cin.ignore(100, '\n');
	}
	complex_calculator(); // the calculator mode
	return 0;
}

Complex.h

/*
 * Project: Complex
 * File: Complex.h
 * -----------------
 *
 * @author Teddy van Jerry
 *
 * @version 2020/12/10
 * - modify some parameters into const reference
 * @version 2020/11/29
 * - add the convertion function(operator double())
 * @version 2020/11/27
 * - add function +=, -=, *=, /=, ^=
 * - add function error
 * - add function divide and power
 * - add function minus and multiply
 * - add function conjugate and modulus
 * @version 2020/11/26
 * - initial version
 */

#pragma once
#define _COMPLEX_
#include <iostream>
#include <cmath>
#include <Windows.h>

extern double Inf; // declare

void error(LPCWSTR error_info); // declare

class Complex {

	// friendship declaration

	/**
	 * input
	 * @ written by Teddy van Jerry
	 */
	friend std::istream& operator>>(std::istream& input, Complex& a);

	/**
	 * output
	 * @ written by Teddy van Jerry
	 */
	friend std::ostream& operator<<(std::ostream& output, const Complex& a);

public:

	/**
	 * Constructor list
	 * used to initialize members Real and Inaginary
	 * @ written by Teddy van Jerry
	 */
	Complex(double a = 0, double b = 0) :Real(a), Imaginary(b) {}

	// function prototype(declaration)

	/**
	 * Add function
	 * used to add two Complex numbers
	 * return the sum of the two numbers
	 * @ written by Teddy van Jerry
	 */
	Complex add(const Complex& a);

	/**
	 * Minus function
	 * used to minus two Complex numbers
	 * return the difference of the two numbers
	 * @ written by Student 2
	 */
	Complex minus(const Complex& a);

	/**
	 * Multiply function
	 * used to multiply two Complex numbers
	 * return the difference of the two numbers
	 * @ written by Student 2
	 */
	Complex multiply(const Complex& a);

	/**
	 * Divide function
	 * used to divide two Complex numbers
	 * return the product of the two numbers
	 * @ written by Student 3
	 */
	Complex divide(const Complex& a);

	/**
	 * Power function
	 * used to power one Complex number
	 * return the power of it
	 * @ written by Student 3
	 */
	Complex power(const int& n);

	/**
	 * Power function(double)
	 * used to power one Complex number
	 * return the power of it
	 * @ written by Teddy van Jerry
	 */
	Complex power(const double& n);

	/**
	 * Conjugate function
	 * return the conjugate of a Complex number
	 * @ written by Student 1
	 */
	Complex conjugate();

	/**
	 * Modulus function
	 * return the modulus of a Complex number
	 * @ written by Student 1
	 */
	Complex modulus();

	/**
	 * GetReal function
	 * return the real part of a Complex number
	 * @ written by Teddy van Jerry
	 */
	double getReal();

	/**
	 * GetImaginary function
	 * return the imaginary part of a Complex number
	 * @ written by Teddy van Jerry
	 */
	double getImaginary();

	/**
	 * add
	 * @ written by Teddy van Jerry
	 */
	Complex operator+(const Complex& a);

	/**
	 * minus
	 * @ written by Teddy van Jerry
	 */
	Complex operator-(const Complex& a);

	/**
	 * multiply
	 * @ written by Teddy van Jerry
	 */
	Complex operator*(const Complex& a);

	/**
	 * divide
	 * @ written by Teddy van Jerry
	 */
	Complex operator/(const Complex& a);

	/**
	 * add
	 * @ written by Teddy van Jerry
	 */
	Complex operator+=(const Complex& a);

	/**
	 * minus
	 * @ written by Teddy van Jerry
	 */
	Complex operator-=(const Complex& a);

	/**
	 * multiply
	 * @ written by Teddy van Jerry
	 */
	Complex operator*=(const Complex& a);

	/**
	 * divide
	 * @ written by Teddy van Jerry
	 */
	Complex operator/=(const Complex& a);

	/**
	 * power
	 * @ written by Teddy van Jerry
	 */
	Complex operator^(const double& n);

	/**
	 * power
	 * @ written by Teddy van Jerry
	 */
	Complex operator^=(const double& n);

	/**
	 * power
	 * @ written by Teddy van Jerry
	 */
	Complex operator^(const Complex& n);

	/**
	 * power
	 * @ written by Teddy van Jerry
	 */
	Complex operator^=(const Complex& n);

	/**
	 * isequal
	 * return true if equal
	 * return false if unequal
	 * @ written by Teddy van Jerry
	 */
	bool operator==(const Complex& a);

	/**
	 * !isequal
	 * return true if unequal
	 * return false if equal
	 * @ written by Teddy van Jerry
	 */
	bool operator!=(const Complex& a);

	/**
	 * Convertion
	 * return the real part of the complex
	 * @ written by Teddy van Jerry
	 */
	operator double();

private:
	/**
	* Private members
	* @ written by Teddy van Jerry
	*/
	double Real;
	double Imaginary;
};

/**
 * Input operator
 * @ written by Teddy van Jerry
 */
std::istream& operator>>(std::istream& input, Complex& a);

/**
 * Output operator
 * @ written by Teddy van Jerry
 */
std::ostream& operator<<(std::ostream& output, const Complex& a);

/**
 * Error information
 * @ written by Teddy van Jerry
 */
void error(LPCWSTR error_info);

/**
 * Warning information
 * @ written by Teddy van Jerry
 */
void warning(LPCWSTR warning_info);

Complex.cpp

/*
 * Project: Complex
 * File: Complex.cpp
 * -----------------
 * This file implements the Complex.h interface.
 *
 * @author Teddy van Jerry, Student 1, Student 2, Student 3
 *
 * @version 2020/12/10
 * - modify some parameters into const reference
 * @version 2020/11/29
 * - add the convertion function(operator double())
 * @version 2020/11/27
 * - add function +=, -=, *=, /=, ^=
 * - add function error
 * - add function divide and power
 * - add function minus and multiply
 * - add function conjugate and modulus
 * @version 2020/11/26
 * - initial version
 */

#include "Complex.h"

double Inf = 0.0 / 0; // define Inf (infinite)

Complex Complex::add(const Complex& a)
{
	// *this refers to the initial Complex number
	// (*this).func() equals to this->func()
	// (*this).member equals to this->member
	double new_Real = this->Real + a.Real;
	double new_Imaginary = this->Imaginary + a.Imaginary;
	Complex result(new_Real, new_Imaginary);
	return result;
}

Complex Complex::minus(const Complex& a)
{
	double new_Real = this->Real - a.Real;
	double new_Imaginary = this->Imaginary - a.Imaginary;
	Complex result(new_Real, new_Imaginary);
	return result;
}

Complex Complex::multiply(const Complex& a)
{
	double new_Real = this->Real * a.Real - this->Imaginary * a.Imaginary;
	double new_Imaginary = this->Real * a.Imaginary + a.Real * this->Imaginary;
	Complex result(new_Real, new_Imaginary);
	return result;
}

Complex Complex::divide(const Complex& a)
{
	double A = this->Real;
	double B = this->Imaginary;
	double C = a.Real;
	double D = a.Imaginary;
	if (C == 0 && D == 0)
	{
		error(L"The denominator can't be zero!");
		Complex result(Inf, Inf);
		return result;
	}
	else
	{
		double new_Real = (A * C + B * D) / (C * C + D * D);
		double new_Imaginary = (C * B - A * D) / (C * C + D * D);
		Complex result(new_Real, new_Imaginary);
		return result;
	}
}

Complex Complex::power(const int& n)
{
	if (!n) // if(n == 0)
	{
		Complex result(1, 0);
		return result;
	}
	else
	{
		int N = n;
		bool f = true;
		if (n < 0)
		{
			N = -N;
			f = false;
		}
		Complex result(this->Real, this->Imaginary);
		for (int i = 0; i < N - 1; i++)
		{
			result *= *this;
		}
		Complex e(1, 0);
		if (f == false)
		{
			result = e / result;
		}
		return result;
	}
}

Complex Complex::power(const double& n)
{
	if (fabs(n - round(n)) < 1E-10) // if it is almost an integer
	{
		return power(static_cast<int>(round(n)));
	}
	else
	{
		// De Moivre's formula
		double argz = n * atan2(this->Imaginary, this->Real);
		double r = pow(this->modulus().Real, n);
		Complex result(r * cos(argz), r * sin(argz));
		return result;
	}
}

Complex Complex::conjugate()
{
	double new_Real = this->Real;
	double new_Imaginary = -this->Imaginary;
	Complex result(new_Real, new_Imaginary);
	return result;
}

Complex Complex::modulus()
{
	double mod = sqrt(pow(this->Real, 2) + pow(this->Imaginary, 2));
	Complex result(mod, 0);
	return result;
}

double Complex::getReal()
{
	return this->Real;
}

double Complex::getImaginary()
{
	return this->Imaginary;
}

Complex Complex::operator+(const Complex& a)
{
	return this->add(a);
}

Complex Complex::operator-(const Complex& a)
{
	return this->minus(a);
}

Complex Complex::operator*(const Complex& a)
{
	return this->multiply(a);
}

Complex Complex::operator/(const Complex& a)
{
	return this->divide(a);
}

Complex Complex::operator+=(const Complex& a)
{
	*this = this->add(a);
	return *this;
}

Complex Complex::operator-=(const Complex& a)
{
	*this = this->minus(a);
	return *this;
}

Complex Complex::operator*=(const Complex& a)
{
	*this = this->multiply(a);
	return *this;
}

Complex Complex::operator/=(const Complex& a)
{
	*this = this->divide(a);
	return *this;
}

Complex Complex::operator^(const double& n)
{
	return this->power(n);
}

Complex Complex::operator^=(const double& n)
{
	*this = this->power(n);
	return *this;
}

Complex Complex::operator^(const Complex& n)
{
	return this->power(n.Real);
}

Complex Complex::operator^=(const Complex& n)
{
	*this = this->power(n.Real);
	return *this;
}

bool Complex::operator==(const Complex& a)
{
	if (this->Real == a.Real && this->Imaginary == a.Imaginary)
		return true;
	else return false;
}

bool Complex::operator!=(const Complex& a)
{
	if (*this == a) return false;
	else return true;
}

Complex::operator double()
{
	return Real;
}

std::istream& operator>>(std::istream& input, Complex& a)
{
	input >> a.Real >> a.Imaginary;
	return input;
}

std::ostream& operator<<(std::ostream& output, const Complex& a)
{
	if (a.Real != Inf) // if a.Real is not infinite(∞)
	{
		double accuracy = 1E-16;
		if (fabs(a.Real) > accuracy)
		{
			output << a.Real;
			if (a.Imaginary > accuracy)
			{
				if (fabs(a.Imaginary - 1) < accuracy)
				{
					output << " + i";
				}
				else
				{
					output << " + " << a.Imaginary << "i";
				}
			}
			else if (a.Imaginary < -accuracy)
			{
				if (fabs(-a.Imaginary - 1) < accuracy)
				{
					output << " - i";
				}
				else
				{
					output << " - " << -a.Imaginary << "i";
				}
			}
		}
		else
		{
			if (fabs(a.Imaginary + 1) < accuracy)
			{
				output << "-i";
			}
			else if (fabs(a.Imaginary) < accuracy)
			{
				output << 0;
			}
			else if (fabs(a.Imaginary - 1) < accuracy)
			{
				output << "i";
			}
			else
			{
				output << a.Imaginary << "i";
			}
		}
	}
	return output;
}

void error(LPCWSTR error_info)
{
	MessageBox(NULL, error_info, L"Error", MB_ICONERROR | MB_OK);
}

void warning(LPCWSTR warning_info)
{
	MessageBox(NULL, warning_info, L"Warning", MB_ICONWARNING | MB_OK);
}

Calculator.h

/*
 * Project: Complex
 * File: Calculator.h
 * -----------------
 *
 * @author Teddy van Jerry
 *
 * @version 2020/12/01
 * - solve bugs
 * @version 2020/11/29
 * - initial version
 */

#pragma once
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include "Complex.h"
#include "Cursor.h"

/**
 * Class Part
 * store its content, type and value
 * @ written by Wuqiong Zhao
 */
class Part {
public:
	// constructor list
	Part(std::string str = "undefined", std::string n = "undefined", Complex Value = 0) :content(str), type(n), value(Value) {}

	// the content of the part (including the string form of numbers)
	std::string content;

	// the type of the part (number/operator/i/Lbracket/Rbracket/complex)
	std::string type;

	// the value of the part (used as the element after calculating)
	// only valid when the type of Part is "complex"
	Complex value;
};

// declare
void set_green();
void set_yellow();
void set_white();

/**
 * Calculate the priority of each operator
 * @ written by Wuqiong Zhao
 */
int priority(char ch);

/**
 * insert one element(new_w) into a vector(W) at a certain(n) place
 * @ written by Wuqiong Zhao
 */
template<typename T>
void insert(std::vector<T>& W, T new_w, int n);

/**
 * delete elements in a vector(W) from n1 to n2
 * @ written by Wuqiong Zhao
 */
template<typename T>
void shrink(std::vector<T>& W, int n1, int n2);

/**
 * Calculate the result of a postfix expression
 * @ written by Wuqiong Zhao
 */
int to_result(std::vector<Complex>& Number, std::vector<char>& Operator);

/**
 * Change the infix expression to postfix expression
 * @ written by Wuqiong Zhao
 */
int to_postfix(std::vector<Part>& Parts, int i_beg, int i_end);

/**
 * Input
 * read from a getline
 * convert into a vector of Part
 * return the state (error or not)
 * @ written by Wuqiong Zhao
 */
int input_complex(std::string line, std::vector<Part>& All_Parts);

/**
 * to filter brackets out
 * return the state (error or not)
 * @ written by Wuqiong Zhao
 */
int filter_bracket(std::vector<Part>& Parts, int i_beg, int i_end);

/**
 * Caluculator Function
 * read a string from cin
 * print the output of the expression
 * @ written by Wuqiong Zhao
 */
void complex_calculator();

Calculator.cpp

/*
 * Project: Complex
 * File: Calculator.cpp
 * -----------------
 * This file implements the Calculator.h interface.
 *
 * @author Teddy van Jerry
 *
 * @version 2020/12/01
 * - solve bugs
 * @version 2020/11/29
 * - initial version
 */

#include "Calculator.h"

template<typename T>
void insert(std::vector<T>& W, T new_w, int n)
{
	T empty_part;
	W.push_back(empty_part);
	for (int i = W.size() - 2; i >= n; i--)
	{
		W[i + 1] = W[i];
	}
	W[n] = new_w;
}

template<typename T>
void shrink(std::vector<T>& W, int n1, int n2)
{
	T empty_part;
	if (n1 > n2) return;
	for (int i = n1; i != W.size(); i++)
	{
		W[i] = (i + n2 - n1 + 1 < W.size()) ? W[i + n2 - n1 + 1] : empty_part;
	}
	for (int i = n1; i <= n2; i++)
	{
		W.pop_back();
	}
}

int priority(char ch)
{
	switch (ch)
	{
	case '+': case'-':
		return 1;
	case '*':case '/':case'\\':
		return 2;
	case '^':
		return 4;
	default:
		return -1; // indicate error
	}
}

int to_result(std::vector<Complex>& Number, std::vector<char>& Operator)
{
	int error_index = 0; // 0 indeicates succeeded, -1 indicates failed

	// used for test
	// std::cout << Operator.size() << " " << Number.size() << std::endl;
	for (int i = Number.size() - 2, j = Operator.size() - 1; j >= 0; i--, j--)
	{
		switch (Operator[Operator.size() - 1 - j])
		{
		case '+':
			Number[i] += Number[i + 1];
			break;
		case '-':
			Number[i] -= Number[i + 1];
			break;
		case '*':
			Number[i] *= Number[i + 1];
			break;
		case '/': case'\\':
			extern Complex zero;
			if (Number[i + 1] == zero)
			{
				error(L"Mathematic error!\nThe denominator can't be zero!");
				return -1; // error
			}
			else
			{
				Number[i] /= Number[i + 1];
			}
			break;
		case '^':
			if (Number[i + 1].getImaginary() != 0)
			{
				warning(L"The imaginary part of the exponent is omitted.");
			}
			Number[i] ^= Number[i + 1];
			break;
		default:
			std::cerr << "What's up? It is " << Number[i] << std::endl;
			error(L"Programme Bug"); // impossible by theory
			return -1;
		}
		Number.pop_back();
	}
	Operator.clear();
	return 0;
}

int to_postfix(std::vector<Part>& Parts, int i_beg, int i_end)
{
	std::vector<Complex> Number;
	std::vector<char> Operator;
	std::vector<char> temp_operator;
	int num_Operator = 0;
	for (int i = i_beg + 1; i < i_end - 1; i++)
	{
		// considering that operator - and + can be an unary operator
		if (i == i_beg + 1)
		{
			if (Parts[i_beg + 1].type == "operator")
			{
				if (Parts[i_beg + 1].content == "-" || Parts[i_beg + 1].content == "+")
				{
					Number.push_back(0);
					Operator.push_back(Parts[i_beg + 1].content[0]);
					num_Operator++;
					continue;
				}
				else // if not - or + but in the front, error
				{
					error(L"Grammatical error!");
					return -1;
				}
			}
		}
		if (Parts[i].type == "complex")
		{
			Number.push_back(Parts[i].value);
			continue;
		}
		if (Parts[i].type == "number")
		{
			std::istringstream is(Parts[i].content);
			double number;
			is >> number; // now the string number has been converted into double
			if (is.fail())
			{
				error(L"Illegal input of number!");
				return -1;
			}
			Number.push_back(number);
		}
		else if (Parts[i].type == "i")
		{
			if (Parts[i + 1].content == "^")
			{
				if (num_Operator == Number.size()) // i.e. +i, -i
				{
					Number.push_back(1);
				}
				while (!temp_operator.empty() && priority('*') <= priority(*--temp_operator.end()))
				{
					Operator.push_back(*--temp_operator.end());
					temp_operator.pop_back();
				}
				temp_operator.push_back('*');
				num_Operator++;
				Complex temp_i(0, 1);
				Number.push_back(temp_i);
				while (!temp_operator.empty() && priority('^') <= priority(*--temp_operator.end()))
				{
					Operator.push_back(*--temp_operator.end());
					temp_operator.pop_back();
				}
				temp_operator.push_back('^');
				num_Operator++;
				++i;
			}
			else
			{
				if (num_Operator == Number.size()) // i.e. +i or -i
				{
					Complex result(0, 1);
					Number.push_back(result);
				}
				else
				{
					double temp = *--Number.end();
					Complex result(0, temp);
					Number.pop_back();
					Number.push_back(result);
				}
			}
			continue;
		}
		else if (temp_operator.empty())
		{
			switch (Parts[i].content[0])
			{
			case '+': case '-': case'*': case'/': case'\\': case'^':
				temp_operator.push_back(Parts[i].content[0]);
				num_Operator++;
				break;
			case ' ': case'\t': case'\r': case'\n':
				break;
			case ')': case '(':
				error(L"Grammatical error!\nMismatched ()");
				return -1;
			case ']': case '[':
				error(L"Grammatical error!\nMismatched []");
				return -1;
			case '>': case '<':
				error(L"Grammatical error!\nMismatched <>");
				return -1;
			default:
				error(L"Grammatical error!\nUndefined operator!");
				// used for test
				// std::cout << "* /" << Parts[i].content[0] << std::endl;
				return -1;
			}
		}
		else
		{
			switch (Parts[i].content[0])
			{
			case '+': case '-': case'*': case'/': case'\\': case'^':
				while (!temp_operator.empty() && priority(Parts[i].content[0]) <= priority(*--temp_operator.end()))
				{
					Operator.push_back(*--temp_operator.end());
					temp_operator.pop_back();
				}
				temp_operator.push_back(Parts[i].content[0]);
				num_Operator++;
				break;
			case ' ':case'\t':case'\r':case'\n':
				break;
			case ')': case '(':
				error(L"Grammatical error!\nMismatched ()");
				return -1;
			case ']': case '[':
				error(L"Grammatical error!\nMismatched []");
				return -1;
			case '>': case '<':
				error(L"Grammatical error!\nMismatched <>");
				return -1;
			default:
				error(L"Grammatical error!\nUndefined operator!");
				// used for test
				// std::cout << "* /" << Parts[i].content[0] << std::endl;
				return -1;
			}
		}
		if ((Parts[i].type == "number" || Parts[i].type == "complex") && Number.size() < 1 + Operator.size())
		{
			error(L"Grammatical error!");
			return -1; // error
		}
		if (to_result(Number, Operator) == -1)
		{
			return -1; // error
		}
		num_Operator = temp_operator.size();
	}
	for (int j = temp_operator.size() - 1; j >= 0; j--)
	{
		Operator.push_back(temp_operator[j]);
	}
	if (Number.size() != 1 + Operator.size())
	{
		error(L"Grammatical error!");
		return -1; // error
	}
	if (to_result(Number, Operator))
	{
		return -1;
	}
	Complex final_result = Number[0];
	if (Parts[i_beg].content == "[")
	{
		final_result = final_result.modulus();
	}
	else if (Parts[i_beg].content == "<")
	{
		final_result = final_result.conjugate();
	}
	// used for test
	// std::cout << "Final_result: " << final_result << std::endl;

	// the contents between two brackets have been calculated,
	// they will be replaced by a complex number.
	// First clear previous contents(shrink),
	// then insert the complex number in the type of Part.
	shrink(Parts, i_beg, i_end - 1);
	// used for test
	// std::cout << i_beg << " " << i_end << "/" << Parts.size() << std::endl;
	Part final_result_insert("", "complex", final_result);
	insert(Parts, final_result_insert, i_beg);
	return 0;
}

int input_complex(std::string line, std::vector<Part>& All_Parts)
{
	Part first_one("(", "Lbracket"), last_one(")", "Rbracket");
	All_Parts.push_back(first_one);
	for (int i = 0; i < line.length(); i++)
	{
		if (line[i] < 0 || line[i] > 255)
		{
			error(L"Not legal English characters!");
			return -1;
		}
		if (isspace(line[i])) continue;
		std::string temp_number;
		while (i < line.length() && (isdigit(line[i]) || line[i] == '.'))
		{
			temp_number += line[i++];
			if (i < line.length() && (line[i] < 0 || line[i] > 255))
			{
				error(L"Not legal English characters!");
				return -1;
			}
		}
		if (temp_number != "")
		{
			Part this_number(temp_number, "number");
			All_Parts.push_back(this_number);
			temp_number = ""; // recover
			i--;
			continue;
		}
		else
		{
			std::string empty_str_here;
			switch (line[i])
			{
			case 'i': case'I':
			{
				Part this_i("i", "i");
				All_Parts.push_back(this_i);
				break;
			}

			case '+': case '-': case '*': case '/': case '\\': case '^':
			{
				Part this_operator(empty_str_here + line[i], "operator");
				All_Parts.push_back(this_operator);
				break;
			}
			case '(': case '[': case '<':
			{
				Part this_bracket(empty_str_here + line[i], "Lbracket");
				All_Parts.push_back(this_bracket);
				break;
			}
			case ')': case ']': case '>':
			{
				Part this_bracket(empty_str_here + line[i], "Rbracket");
				All_Parts.push_back(this_bracket);
				break;
			}
			default:
				error(L"Grammatical error!\nUndefined operator!");
				return -1; // error
			}
		}
	}
	All_Parts.push_back(last_one);
	for (int i = All_Parts.size() - 2; i >= 0; i--)
	{
		// e.g. in case )(, add * between them
		if (All_Parts[i].type == "Rbracket" && All_Parts[i + 1].type == "Lbracket")
		{
			Part default_multiply("*", "operator");
			insert(All_Parts, default_multiply, i + 1);
		}
	}
	return 0;
}

int filter_bracket(std::vector<Part>& Parts, int i_beg, int i_end)
{
	int error_index = 0; // 0 indicates succeeded, -1 indicates failed
	for (int i = i_end - 2; i > i_beg; i--)
	{
		if (Parts[i].type == "Rbracket")
		{
			std::string match_bracket = (Parts[i].content == ")") ? "(" : (Parts[i].content == "]") ? "[" : "<";
			// the difference between right brackets and left brackets
			// if difference is zero, we find the match of the bracket
			int difference = 1;
			for (int j = i - 1; j > i_beg; j--)
			{
				if (Parts[j].content == Parts[i].content)
				{
					difference++;
				}
				else if (Parts[j].content == match_bracket)
				{
					difference--;
				}
				if (difference == 0)
				{
					error_index = filter_bracket(Parts, j, i + 1);
					return (error_index == 0) ? 0 : -1;
				}
			}
			if (difference != 0)
			{
				switch (Parts[i].content[0])
				{
				case ')':
					error(L"Grammatical error!\nMismatched ()");
					break;
				case ']':
					error(L"Grammatical error!\nMismatched []");
					break;
				case '>':
					error(L"Grammatical error!\nMismatched <>");
					break;
				}
				return -1; // error
			}
		}
	}
	error_index = to_postfix(Parts, i_beg, i_end);
	return (error_index == 0) ? 0 : -1;
}

void complex_calculator()
{
	set_green();
	std::cout << "This is the Calculator mode.\n" << std::endl;
	while (1)
	{
		set_yellow();
		cursor("show");
		std::cout << ">>> ";
		set_white();
		std::string line;
		getline(std::cin, line); // get the whole line
		std::vector<Part> All_Parts;
		int feedback_input = input_complex(line, All_Parts);
		if (feedback_input == -1) // if there is an error
		{
			std::cerr << std::endl;
			continue;
		}
		int feedback_to_filter = 0;
		while (All_Parts.size() != 1)
		{
			feedback_to_filter = filter_bracket(All_Parts, 0, All_Parts.size());
			// std::cout << All_Parts.size() << std::endl;
			if (feedback_to_filter == -1)
				break;
		}
		if (feedback_to_filter == -1)
		{
			std::cerr << std::endl;
			continue;
		}
		set_yellow();
		std::cout << "-> Ans: ";
		set_white();
		std::cout << All_Parts[0].value << std::endl;

		std::cout << std::endl;
	}
}

Cursor.h

/*
 * Project: Complex
 * File: Cursor.h
 * -----------------
 *
 * @author Teddy van Jerry
 *
 * @version 2020/11/15
 * - initial version
 */
#pragma once
#define _CURSOR_HS_
#include <Windows.h>
#include <string>

/**
 * cursor("hide") will hide the cursor
 * cursor("show") will shou the cursor
 * @ written by Wuqiong Zhao
 */
void cursor(std::string str);

Cursor.cpp

/*
 * Project: Complex
 * File: Cursor.cpp
 * -----------------
 * This file implements the Cursor.h interface.
 *
 * @author Teddy van Jerry
 *
 * @version 2020/11/15
 * - initial version
 */

#include "Cursor.h"

void cursor(std::string str)
{
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cci;

	for (auto& c : str)
		c = tolower(c);

	if (str == "hide")
	{
		// hide the cursor
		GetConsoleCursorInfo(hOut, &cci);
		cci.bVisible = FALSE;
		SetConsoleCursorInfo(hOut, &cci);
	}
	else if (str == "show")
	{
		// show the cursor
		GetConsoleCursorInfo(hOut, &cci);
		cci.bVisible = TRUE;
		SetConsoleCursorInfo(hOut, &cci);
	}
}

分析

复数类(Complex Class)其他应用

【SEU程序设计课笔记】 17 - 2020/12/10 - Write C++ programs - 分形绘图


ALL RIGHTS RESERVED © 2020 Teddy van Jerry
欢迎转载,转载请注明出处。


See also

Teddy van Jerry 的导航页

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页