【C++ 程序】 复数类 (Complex)

这是一个功能强大的 Complex 类,支持多种功能,包括运算符,并支持字符串(并支持表达式)转复数。

++++++++++++++++++++++++++
Caution
请在 Visual Studio 2019 上运行,
否则可能会存在编译错误。
++++++++++++++++++++++++++

Complex.h

/*
 * Project: Complex
 * File: Complex.h
 * -----------------
 *
 * @author Teddy van Jerry
 *
 * @version 2020/12/28
 * - add the operator =
 * - add the function sqrt
 * - solve bugs which could lead to vector subscript out of range with illegal input
 * @version 2020/12/27
 * - use the template to deal with operators that take different parameter types
 * - move operator +, -, *, / from the Complex class
 * - add power function that takes a Complex
 * - add log function
 * @version 2020/12/22
 * - add two overload operator/ which take double and int
 * - add the exp, sin, cos function
 * - add the unary plus and the unary minus
 * @version 2020/12/13
 * - add the constrcutor list that takes a string
 * - modify the accuracy from 1E-16 to 1E-12
 * - add the error type "No input"
 * - modify the power function which takes a double
 * - add the argz function
 * - delete the power function which takes a int
 * - add the function complex_is and complex_is_information
 * - move functions in Calculator.h here
 * @version 2020/12/10
 * - modify some parameters into const reference
 * @version 2020/11/29
 * - add the conversion 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 <sstream>
#include <cmath>
#include <vector>
#include <Windows.h>

constexpr double PI = 3.141592653589793238462643383279;
#define E = 2.71828182845904523536028747;

extern double Inf; // declare

void error(LPCWSTR error_info); // declare

class Complex {

	// friendship declaration

	/**
	 * input
	 */
	friend std::istream& operator>>(std::istream& input, Complex& a);

	/**
	 * output
	 */
	friend std::ostream& operator<<(std::ostream& output, const Complex& a);

public:

	/**
	 * Constructor list
	 * used to initialize members Real and Inaginary
	 */
	Complex(double a = 0, double b = 0);

	/**
	 * Constructor list that takes a string
	 * used to initialize the complex
	 */
	Complex(std::string str);

	// function prototype(declaration)

	/**
	 * Add function
	 * used to add two Complex numbers
	 * return the sum of the two numbers
	 */
	Complex add(const Complex& a) const;

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

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

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

	/**
	 * Power function(double)
	 * used to power one Complex number
	 * return the power of it
	 */
	Complex power(const double& n) const;

	/**
	 * Power function(Complex)
	 */
	Complex power(const Complex& a) const;

	/**
	 * Sqrt function
	 */
	Complex sqrt(const Complex& a) const;

	/**
	 * Conjugate function
	 * return the conjugate of a Complex number
	 */
	Complex conjugate() const;

	/**
	 * Modulus function
	 * return the modulus of a Complex number
	 */
	Complex modulus() const;

	/**
	 * GetReal function
	 * return the real part of a Complex number
	 */
	double getReal() const;

	/**
	 * GetImaginary function
	 * return the imaginary part of a Complex number
	 */
	double getImaginary() const;

	/**
	 * argz function
	 * return the principle argument angle
	 */
	double argz() const;

	/**
	 * unary plus function
	 */
	Complex operator+();

	/**
	 * unary minus function
	 */
	Complex operator-();

	/**
	 * plus
	 */
	Complex operator+=(const Complex& a);

	/**
	 * minus
	 */
	Complex operator-=(const Complex& a);

	/**
	 * multiply
	 */
	Complex operator*=(const Complex& a);

	/**
	 * divide
	 */
	Complex operator/=(const Complex& a);

	/**
	 * power
	 */
	Complex operator^(const double& n);

	/**
	 * power
	 */
	Complex operator^=(const double& n);

	/**
	 * power
	 */
	Complex operator^(const Complex& n);

	/**
	 * power
	 */
	Complex operator^=(const Complex& n);

	/**
	 * isequal
	 * return true if equal
	 * return false if unequal
	 */
	bool operator==(const Complex& a);

	/**
	 * !isequal
	 * return true if unequal
	 * return false if equal
	 */
	bool operator!=(const Complex& a);

	/**
	 * assign
	 */
	void operator=(const Complex& a);

	/**
	 * assign from other types
	 */
	template<typename T_>
	void operator=(const T_& a);

	/**
	 * Convertion
	 * return the real part of the complex
	 */
	operator double();

private:
	/**
	* Private members
	*/
	double Real;
	double Imaginary;
};

/**
 * binary plus function
 */
template<typename T1, typename T2>
Complex operator+(const T1& a, const T2& b);

/**
 * binary minus function
 */
template<typename T1, typename T2>
Complex operator-(const T1& a, const T2& b);

/**
 * multiply function
 */
template<typename T1, typename T2>
Complex operator*(const T1& a, const T2& b);

/**
 * divide function
 */
template<typename T1, typename T2>
Complex operator/(const T1& a, const T2& b);

/**
 * exp that takes a Complex
 */
Complex exp(const Complex& n);

/**
 * log that takes a Complex
 */
Complex log(const Complex& n);

/**
 * sin that takes a Complex
 */
Complex sin(const Complex& a);

/**
 * cos that takes a Complex
 */
Complex cos(const Complex& a);

/**
 * Input operator
 */
std::istream& operator>>(std::istream& input, Complex& a);

/**
 * Output operator
 */
std::ostream& operator<<(std::ostream& output, const Complex& a);

/**
 * Error information
 */
void error(LPCWSTR error_info);

/**
 * Warning information
 */
void warning(LPCWSTR warning_info);

/**
 * Class Part
 * store its content, type and value
 */
class Part {
public:
	// constructor list
	Part(std::string str, std::string n, Complex 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;
};

/**
 * Calculate the priority of each operator
 */
int priority(char ch);

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

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

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

/**
 * Change the infix expression to postfix expression
 */
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)
 */
int input_complex(std::string line, std::vector<Part>& All_Parts);

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

/**
 * return the value of the Complex from the input which takes a string
 * if there is an error,
 * return Complex(Inf, Inf) to indicate error
 */
Complex complex_is(std::string line);

/**
 * the safe version of complex_is
 * which prints the content of an error input if any
 */
Complex complex_is_information(std::string line);

Complex.cpp

/*
 * Project: Complex
 * File: Complex.cpp
 * -----------------
 * This file implements the Complex.h interface.
 *
 * @author Teddy van Jerry
 *
 * @version 2020/12/28
 * - add the operator =
 * - add the function sqrt
 * - solve bugs which could lead to vector subscript out of range with illegal input
 * @version 2020/12/27
 * - use the template to deal with operators that take different parameter types
 * - move operator +, -, *, / from the Complex class
 * - add power function that takes a Complex
 * - add log function
 * @version 2020/12/22
 * - add two overload operator/ which take double and int
 * - add the exp, sin, cos function
 * - add the unary plus and the unary minus
 * @version 2020/12/13
 * - modify the accuracy from 1E-16 to 1E-12
 * - add the error type "No input"
 * - modify the power function which takes a double
 * - add the argz function
 * - delete the power function which takes a int
 * - add the function complex_is and complex_is_information
 * - move functions in Calculator.cpp here
 * @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(double a, double b) :Real(a), Imaginary(b) {}

Complex::Complex(std::string str) { *this = complex_is(str); };

Complex Complex::add(const Complex& a) const
{
	// *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) const
{
	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) const
{
	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) const
{
	double A = this->Real;
	double B = this->Imaginary;
	double C = a.Real;
	double D = a.Imaginary;
	if (C == 0 && D == 0)
	{
		error(L"Can't be divided by 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 double& n) const
{
	// De Moivre's formula
	double Argz = n * this->argz();
	double r = pow(this->modulus(), n);
	Complex result(r * cos(Argz), r * sin(Argz));
	return result;
}

Complex Complex::power(const Complex& a) const
{
	if (a.Imaginary == 0)
	{
		return this->power(a.Real);
	}
	else
	{
		return exp(log(*this) * a);
	}
}

Complex Complex::sqrt(const Complex& a) const
{
	if (a.Real == 0 && a.Imaginary == 0)
	{
		error(L"Mathematic error!\nRoot sign cannot be zero!");
		return 0;
	}
	else
	{
		return this->power(1 / a);
	}
}

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

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

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

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

double Complex::argz() const
{
	return atan2(this->Imaginary, this->Real);
}

Complex Complex::operator-()
{
	Complex ret(-this->Real, -this->Imaginary);
	return ret;
}

Complex Complex::operator+()
{
	return *this;
}

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);
}

Complex Complex::operator^=(const Complex& n)
{
	*this = this->power(n);
	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;
}

void Complex::operator=(const Complex& a)
{
	this->Real = a.Real;
	this->Imaginary = a.Imaginary;
}

template<typename T_>
void Complex::operator=(const T_& a)
{
	*this = static_cast<Complex>(a);
}

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

template<typename T1, typename T2>
Complex operator+(const T1& a, const T2& b)
{
	return static_cast<Complex>(a).add(static_cast<Complex>(b));
}

template<typename T1, typename T2>
Complex operator-(const T1& a, const T2& b)
{
	return static_cast<Complex>(a).minus(static_cast<Complex>(b));
}

template<typename T1, typename T2>
Complex operator*(const T1& a, const T2& b)
{
	return static_cast<Complex>(a).multiply(static_cast<Complex>(b));
}

template<typename T1, typename T2>
Complex operator/(const T1& a, const T2& b)
{
	return static_cast<Complex>(a).divide(static_cast<Complex>(b));
}

Complex exp(const Complex& n)
{
	Complex i(0, 1);
	Complex ret = std::exp(n.getReal());
	Complex i_ret(cos(n.getImaginary()), sin(n.getImaginary()));
	ret *= i_ret;
	return ret;
}

Complex log(const Complex& n)
{
	Complex ret(log(static_cast<double>(n.modulus())), n.argz());
	return ret;
}

Complex cos(const Complex& a)
{
	Complex i(0, 1);
	return (exp(i * a) + exp(-i * a)) / 2;
}

Complex sin(const Complex& a)
{
	Complex i(0, 1);
	//std::cout << i << std::endl;
	return (exp(i * a) - exp(-i * a)) / (Complex("2i"));
}

std::istream& operator>>(std::istream& input, Complex& a)
{
	std::string str;
	std::getline(input, str);
	a = static_cast<Complex>(str);
	return input;
}

std::ostream& operator<<(std::ostream& output, const Complex& a)
{
	if (!isnan(a.Real)) // if a.Real is not infinite(∞)
	{
		double accuracy = 1E-12;
		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);
}

Part::Part(std::string str = "undefined", std::string n = "undefined", Complex Value = 0) :content(str), type(n), value(Value) {}

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--)
	{
		if (i < 0)
		{
			error(L"Grammatical error!");
			return -1;
		}
		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'\\':
			if (Number[i + 1] == static_cast<Complex>(0))
			{
				error(L"Mathematic error!\nThe denominator can't be zero!");
				return -1; // error
			}
			else
			{
				Number[i] /= Number[i + 1];
			}
			break;
		case '^':
			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);
		}
	}
	if (All_Parts.size() == 2)
	{
		error(L"No input!");
		return -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;
}

Complex complex_is(std::string line)
{
	std::vector<Part> All_Parts;
	Complex error_complex(Inf, Inf);
	int feedback_input = input_complex(line, All_Parts);
	if (feedback_input == -1) // if there is an error
	{
		return error_complex;
	}
	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)
		{
			return error_complex;
		}
	}
	if (feedback_to_filter == -1)
	{
		return error_complex;
	}
	return All_Parts[0].value;
}

Complex complex_is_information(std::string line)
{
	Complex result = complex_is(line);
	// if there is an error, print where the error occurs
	if (isnan(result.getReal()) || isnan(result.getImaginary()))
	{
		std::cerr << "Error input in \"" << line << " \"!" << std::endl;
	}
	return result;
}

使用说明

构造函数

函数用法
Complex(double a = 0, double b = 0)实部和虚部
Complex(std::string str)字符串识别(可含运算符)

成员函数

函数用法
Complex add(const Complex& a) const加法
Complex minus(const Complex& a) const减法
Complex multiply(const Complex& a) const乘法
Complex divide(const Complex& a) const除法
Complex power(const double& a) const乘方(次数为实数)
Complex power(const Complex& a) const乘方(次数为复数)
Complex sqrt(const Complex& a) const开方
Complex conjugat() const共轭
Complex modulus() const取模
double getReal() const实部(只读)
double getImaginary() const虚部(只读)
运算符用法
Complex operator+()正号(单目)
Complex operator-()负号(单目)
Complex operator+=(const Complex& a)加等于
Complex operator-=(const Complex& a)减等于
Complex operator*=(const Complex& a)乘等于
Complex operator/=(const Complex& a)除等于
Complex operator^(const double& n)乘方(次数为实数)
Complex operator^=(const double& n)乘方等于(次数为实数)
Complex operator^(const Complex& n)乘方(次数为复数)
Complex operator^=(const Complex& n)乘方等于(次数为实数)
bool operator==(const Complex& a)相等于
bool operator!=(const Complex& a)不等于
void operator=(const Complex& a)拷贝构造(由复数构造)
template<typename T_> void operator=(const T_& a)拷贝构造(由实数、字符串构造)
operator double()Complex转换为double

友元

函数用法
std::istream& operator>>(std::istream& input, Complex& a)输入(字符串形式自动识别)
std::ostream& operator<<(std::ostream& output, const Complex& a)输出

全局函数

template<typename T1, typename T2>
Complex operator+(const T1& a, const T2& b);

函数用法
template<typename T1, typename T2> Complex operator+(const T1& a, const T2& b)加法
template<typename T1, typename T2> Complex operator-(const T1& a, const T2& b)减法
template<typename T1, typename T2> Complex operator*(const T1& a, const T2& b)乘法
template<typename T1, typename T2> Complex operator/(const T1& a, const T2& b)除法
Complex exp(const Complex& n)e 的幂
Complex log(const Complex& n)自然对数
Complex sin(const Complex& a)sin
Complex cos(const Complex& a)cos
void error(LPCWSTR error_info)错误提示内容
void warning(LPCWSTR error_info)警告提示内容

字符串识别运算符

运算符用法
+加号(双目)/ 正号(单目)
-减号(双目)/ 负号(单目)
*乘号
/除号
^乘方
( )括号
[ ]取模
< >取共轭

注意

  • 运算符^优先级很低,使用需用括号。(在字符串识别时没有这个问题,只有在cpp文件中使用这个重载运算符时才存在这个问题)
  • error()warning()如果是字符串应该用前缀L
  • 字符串识别支持括号间的乘号省略。

应用


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


See also

Teddy van Jerry 的导航页

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值