The latest version
【C++ 程序】 TVJ Complex Calculator (v 2.2) 复数计算器
Contents
简介
这是一个用 Visual C++ 做的控制台界面复数计算器程序,支持多种复数有关运算以及混合运算。
系统要求: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 结束后自动进入计算器模式。
示例:
输入要求
各符号含义:
+
加法(双目)/正号(单目,仅限于式子开头和括号内的开头)-
减法(双目)/负号(单目,仅限于式子开头和括号内的开头)*
乘号(双目)/
除号(双目)^
乘方(双目)(此处仅支持次数为实数,若系数为复数,则虚部被忽略)()
括号[]
取模<>
取共轭复数
注:
- 输入各字符间可以有空格
- 输入支持括号之间的乘号省略
- 输入以回车结束
正确示例:
错误示例:
数学错误:除数不能为0!
语法错误(没有配对的括号)
不是英文字符(下图为输入了中文括号)
语法错误
语法错误(未定义的符号)
输入错误数据
警告示例:
- 指数的虚部被忽略。
程序
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);
}
}
分析
- 复数类使用时应注意
^
符号优先级很低,比如加减法优先级都比它高(运算符重载无法改变其优先级)。 - 另见我的博客 【C++ 程序】 TVJ Matrix Laboratory (v 1.1)
- 另见我的博客 【笔记】 在 Visual C++ 中设置 exe 文件的图标。
- 另见我的博客 【笔记】 在 Visual C++ 中设置 exe 文件的版本信息。
- 另见我的博客 【笔记】 在 Visual C++ 中设置 MessageBox。
- 另见我的博客 【笔记】 在 Visual C++ 中设置网页链接。
复数类(Complex Class)其他应用
【SEU程序设计课笔记】 17 - 2020/12/10 - Write C++ programs - 分形绘图
ALL RIGHTS RESERVED © 2020 Teddy van Jerry
欢迎转载,转载请注明出处。