Lab 6-3: Enhanced Complex Number Calculator (20%)
- 輸入:
- 以
double
格式輸入複數的實數及虛數部分,以空格分開,一行輸入一個複數 - 以
char
格式輸入複數的運算子,包含+
、-
、*
、/
,一行輸入一個運算子 - 複數與運算子以交錯的方式輸入,一行輸入一個複數接著一個運算子,倒數一行為複數
- 在任一行輸入 Ctrl+D 結束程式
- Windows 請輸入 Ctrl+Z (會在螢幕上顯示
^Z
) 再輸入 Enter (Format 中的⏎
) 結束程式
- 程式輸入以行為單位,每行輸入為任何有效的
string
格式
- 以
- 輸出:
- 顯示運算複數的結果
- 複數的格式為
(-)<real result> (+|-) (<imag result>i)
- 若輸入運算子、需顯示之前運算的結果,如 Example 的範例
- 若使用者輸入的複數或運算子不正確,則顯示錯誤訊息
Error: Invalid input
並結束程式
- 檔名:
lab6-3_<學號>.cpp
(e.g.lab6-3_106062802.cpp
)
注意事項:
- 程式不會輸出任何使用者提示,只會輸出程式結果或錯誤訊息
- 程式僅需處裡輸入錯誤的例外狀況,如輸入的複數或運算子不正確,其餘錯誤不須處裡
- 請基於 pseudo code 提供的
main
及Complex_Calc::set_input
進行修改來處理輸入與輸出 - 程式需要於 10 秒內完成,所有的測資皆會保證於 10 秒內完成
Format
<real 1> <imag 1>⏎
<result 1>
<op 1>⏎
<result 1>
<real 2> <imag 2>⏎
<result 2>
<op 2>⏎
<result 2>
...
<real n-1> <imag n-1>⏎
<result n-1>
<op n-1>⏎
<result n-1>
<real n> <imag n>⏎
<result n>
^Z⏎
Example
Normal
$ ./a.out
1.0 0.0⏎
1
^Z⏎
$ ./a.out
0.0 1.0⏎
0 + 1i⏎
^Z⏎
$ ./a.out
1.0 0.0⏎
1
+⏎
1
^Z⏎
$ ./a.out
^Z⏎
$ ./a.out
1.0 0.0⏎
1
+⏎
1
2.0 1.1⏎
3 + 1.1i
-⏎
3 + 1.1i
-3.0 -2.2⏎
6 + 3.3i
*⏎
6 + 3.3i
4.3 2.1⏎
18.87 + 26.79i
/⏎
18.87 + 26.79i
-1.2 -3.4⏎
-8.74846 + 2.46231i
^Z⏎
$ ./a.out
1.0 0.0⏎
1
+⏎
1
2.0 1.1⏎
3 + 1.1i
-⏎
3 + 1.1i
-3.0 -2.2⏎
6 + 3.3i
*⏎
6 + 3.3i
4.3 2.1⏎
18.87 + 26.79i
/⏎
18.87 + 26.79i
-1.2 3.4⏎
5.26477 - 7.40815i
^Z⏎
$
Exception Handling
$ ./a.out
+⏎
Error: Invalid input
$
$ ./a.out
1.0 0.0⏎
1
1.0 0.0⏎
Error: Invalid input
$
$ ./a.out
1.0 0.0⏎
1
+⏎
1
+⏎
Error: Invalid input
$
$ ./a.out
1.0 2.0 3.0⏎
Error: Invalid input
$
$ ./a.out
1.0 2.0⏎
1 + 2i
sdafsdagret⏎
Error: Invalid input
$
$ ./a.out
sdoifjwepoirjpwoie⏎
Error: Invalid input
$
Pseudo Code
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;
class Complex_Calc;
class Complex
{
private:
// data members
// save the real and imaginary parts of the complex number
// with `double` precision
double m_real;
double m_imag;
public:
// Constructor, initializes real and imaginary parts
Complex(const double &arg_real = 0.0, const double &arg_imag = 0.0);
// Copy constructor
Complex(const Complex &arg_c);
// assignment operator
Complex &operator=(const Complex &arg_c);
// add assignment operator
Complex &operator+=(const Complex &arg_c);
// subtract assignment operator
Complex &operator-=(const Complex &arg_c);
// multiply assignment operator
Complex &operator*=(const Complex &arg_c);
// divide assignment operator
Complex &operator/=(const Complex &arg_c);
// add function
Complex operator+(const Complex &arg_c) const;
// subtract function
Complex operator-(const Complex &arg_c) const;
// multiply function
Complex operator*(const Complex &arg_c) const;
// divide function
Complex operator/(const Complex &arg_c) const;
// cout `<<` operator for print complex number
// note: be careful about the format of output
friend ostream &operator<<(ostream &arg_os, const Complex &arg_c);
// cin `>>` operator for input complex number
// note: use `>>` to parse the string to double,
// use `istream::fail()` to check the conversion is successful
// and use `istream::eof()` to check the is parse to the end of line
friend istream &operator>>(istream &arg_is, Complex &arg_c);
friend class Complex_Calc;
};
// Complex calculator class declaration
class Complex_Calc
{
private:
// define current value
Complex m_curr_val;
// define input value
Complex m_input_val;
// define operation
// `+`, `-`, `*`, `/`, and `=`
char m_op;
// define input status, truns `op` for true and turns `value` for false
bool m_op_input;
// calculate result
void _calc_result();
// operation functions
// set activation op to add
void _add();
// set activation op to subtract
void _sub();
// set activation op to multiply
void _mul();
// set activation op to divide
void _div();
// set activation op to assign
void _assign();
public:
// Constructor
Complex_Calc();
// Copy constructor
Complex_Calc(const Complex_Calc &arg_int_calc);
// Destructor
~Complex_Calc(){}; // no need to do anything
// set input value or operation
// as the same as the user input number or operation
// into the calculator
void set_input(const string &arg_input);
// cout `<<` operator for print calculator status
// note: be careful about the format of output
friend ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc);
};
// error and exit
void error_and_exit()
{
cerr << "Error: Invalid input" << endl;
exit(1);
}
void Complex_Calc::set_input(const string &arg_input)
{
// input is empty, read again
if (arg_input.empty())
{
return;
}
// input is a operator in right turn
// set the activated operation
// as the same as the user press the op button
// set to 'input a complex number' turn
// input is a complex number in right turn
// as the same as the user type a number
// it performs as the same as the user pressed the '=' button
// if the input is the first input
// thus, we initialize the m_op to '='
// else, input is invalid
else
{
error_and_exit();
}
}
// main function
int main()
{
// create an instance of the class
Complex_Calc calc;
string input;
while (getline(cin, input))
{
calc.set_input(input);
cout << calc << endl;
}
}
Reference Code:
林元鴻(110021120)
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;
class Complex_Calc;
class Complex
{
private:
// data members
// save the real and imaginary parts of the complex number
// with `double` precision
double m_real;
double m_imag;
public:
// Constructor, initializes real and imaginary parts
Complex(const double &arg_real = 0.0, const double &arg_imag = 0.0)
{
m_real = arg_real;
m_imag = arg_imag;
}
// Copy constructor
Complex(const Complex &arg_c)
{
m_real = arg_c.m_real;
m_imag = arg_c.m_imag;
}
// assignment operator
Complex &operator=(const Complex &arg_c)
{
m_imag = arg_c.m_imag;
m_real = arg_c.m_real;
return *this;
}
// add assignment operator
Complex &operator+=(const Complex &arg_c)
{
m_imag = m_imag + arg_c.m_imag;
m_real = m_real + arg_c.m_real;
return *this;
}
// subtract assignment operator
Complex &operator-=(const Complex &arg_c)
{
m_imag = m_imag - arg_c.m_imag;
m_real = m_real - arg_c.m_real;
return *this;
}
// multiply assignment operator
Complex &operator*=(const Complex &arg_c)
{
Complex p;
p.m_real = (m_real * arg_c.m_real) - (m_imag * arg_c.m_imag);
p.m_imag = (m_real * arg_c.m_imag) + (m_imag * arg_c.m_real);
m_imag = p.m_imag;
m_real = p.m_real;
return *this;
}
// divide assignment operator
Complex &operator/=(const Complex &arg_c)
{
Complex p;
p.m_real = (arg_c.m_real * m_real + m_imag * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
p.m_imag = (arg_c.m_real * m_imag - m_real * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
m_imag = p.m_imag;
m_real = p.m_real;
return *this;
}
// add function
Complex operator+(const Complex &arg_c) const
{
Complex p;
p.m_imag = m_imag + arg_c.m_imag;
p.m_real = m_real + arg_c.m_real;
return p;
}
// subtract function
Complex operator-(const Complex &arg_c) const
{
Complex p;
p.m_imag = m_imag - arg_c.m_imag;
p.m_real = m_real - arg_c.m_real;
return p;
}
// multiply function
Complex operator*(const Complex &arg_c) const
{
Complex p;
p.m_real = (m_real * arg_c.m_real) - (m_imag * arg_c.m_imag);
p.m_imag = (m_real * arg_c.m_imag) + (m_imag * arg_c.m_real);
return p;
}
// divide function
Complex operator/(const Complex &arg_c) const
{
Complex p;
p.m_real = (arg_c.m_real * m_real + m_imag * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
p.m_imag = (arg_c.m_real * m_imag - m_real * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
return p;
}
friend ostream &operator<<(ostream &arg_os, const Complex &arg_c)
{
if (arg_c.m_imag == 0)
arg_os << arg_c.m_real;
else if (arg_c.m_imag > 0)
arg_os << arg_c.m_real << " + " << arg_c.m_imag << 'i';
else
arg_os << arg_c.m_real << " - " << (-1) * (arg_c.m_imag) << 'i';
return arg_os;
}
friend istream &operator>>(istream &arg_is, Complex &arg_c)
{
string str_x, str_y, temp;
if (getline(arg_is, str_x, ' '))
{
if (getline(arg_is, str_y, '\n'))
{
arg_c.m_real = stod(str_x);
arg_c.m_imag = stod(str_y);
}
}
return arg_is;
}
friend class Complex_Calc;
};
// Complex calculator class declaration
class Complex_Calc
{
private:
// define current value
Complex m_curr_val;
// define input value
Complex m_input_val;
// define operation
// `+`, `-`, `*`, `/`, and `=`
string m_op;
// calculate result
void _calc_result()
{
switch (m_op[0])
{
case '+':
_add();
break;
case '-':
_sub();
break;
case '*':
_mul();
break;
case '/':
_div();
break;
case '=':
_assign();
break;
}
return;
}
// operation functions
// add the input value to the current value
void _add()
{
m_curr_val += m_input_val;
return;
}
// subtract the input value from the current value
void _sub()
{
m_curr_val -= m_input_val;
return;
}
// multiply the input value with the current value
void _mul()
{
m_curr_val *= m_input_val;
return;
}
// divide the current value by the input value
void _div()
{
m_curr_val /= m_input_val;
return;
}
// assign the input value to the current value
void _assign()
{
m_curr_val = m_input_val;
return;
}
public:
// Constructor
Complex_Calc(const Complex &arg_curr_val = Complex(0, 0),
const Complex &arg_input_val = Complex(0, 0),
const string op = "=")
{
m_curr_val = arg_curr_val;
m_input_val = arg_input_val;
m_op = op;
}
//(const Complex &arg_curr_val = (0, 0),
// const Complex &arg_input_val = (0,0),
// const char op = '=')
// Copy constructor
Complex_Calc(const Complex_Calc &arg_int_calc)
{
m_curr_val = arg_int_calc.m_curr_val;
m_input_val = arg_int_calc.m_input_val;
m_op = arg_int_calc.m_op;
}
// Destructor
~Complex_Calc(){}; // no need to do anything
// set input value or operation
void set_input(const string &arg_input);
// cout `<<` operator for print calculator status
// note: be careful about the format of output
friend ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc)
{
arg_os << arg_comp_calc.m_curr_val;
return arg_os;
}
};
// parse the test cases, do not modify belows
void error_and_exit()
{
cout << "Error: Invalid input" << endl;
exit(1);
}
void Complex_Calc::set_input(const string &arg_input)
{
// input is empty, read again
if (arg_input.empty())
{
error_and_exit();
return;
}
// input is a operation
else if (arg_input == "+" || arg_input == "-"
|| arg_input == "*" || arg_input == "/" || arg_input == "=")
{
m_op = arg_input;
}
// input is a complex number
// as the same as the user type a number
// it performs as the same as the user pressed the '=' button
// if the input is the first input
// thus, we initialize the m_op to '='
else
{
stringstream ss(arg_input);
ss >> m_input_val;
if (m_input_val.m_imag == 0 && m_input_val.m_real == 0 && m_op == "/")
{
error_and_exit();
}
_calc_result();
}
}
// main function
bool test(string input, int n)
{
if (n % 2 == 0)
{
int t = 0;
for (int i = 0; i < input.size(); i++)
{
if (input[i] == ' ')
{
t++;
}
}
if (t != 1)
{
return false;
}
double real, imag;
stringstream ss(input);
ss >> real;
if (ss.fail()) // if fail return false
{
return false;
}
ss >> imag;
if (ss.fail())
{
return false;
}
if (!ss.eof()) // if it is not the end of file return false
{
return false;
}
}
else
{
if (input.size() != 1)
{
return false;
}
else if (input[0] != '+' && input[0] != '-'
&& input[0] != '*' && input[0] != '/')
{
return false;
}
}
return true;
}
int main()
{
int n = 0;
// create an instance of the class
Complex_Calc calc;
string input;
while (getline(cin, input))
{
if (!(test(input, n)))
{
error_and_exit();
}
calc.set_input(input);
cout << calc << endl;
n++;
}
}
陳誼倫(110021127)
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
#include <vector>
using namespace std;
class Complex_Calc;
class Complex
{
private:
double m_real;
double m_imag;
public:
Complex(const double &arg_real = 0.0, const double &arg_imag = 0.0);
Complex(const Complex &arg_c);
Complex &operator=(const Complex &arg_c);
Complex &operator+=(const Complex &arg_c);
Complex &operator-=(const Complex &arg_c);
Complex &operator*=(const Complex &arg_c);
Complex &operator/=(const Complex &arg_c);
Complex operator+(const Complex &arg_c) const
{
Complex res(*this);
res += arg_c;
return res;
}
Complex operator-(const Complex &arg_c) const
{
Complex res(*this);
res -= arg_c;
return res;
}
Complex operator*(const Complex &arg_c) const
{
Complex res(*this);
res *= arg_c;
return res;
}
Complex operator/(const Complex &arg_c) const
{
Complex res(*this);
res /= arg_c;
return res;
}
friend ostream &operator<<(ostream &arg_os, const Complex &arg_c);
friend istream &operator>>(istream &arg_is, Complex &arg_c);
friend class Complex_Calc;
};
Complex::Complex(const double &arg_real, const double &arg_imag)
: m_real(arg_real), m_imag(arg_imag) {}
Complex::Complex(const Complex &arg_point)
: m_real(arg_point.m_real), m_imag(arg_point.m_imag) {}
Complex &Complex::operator=(const Complex &arg_c)
{
this->m_real = arg_c.m_real;
this->m_imag = arg_c.m_imag;
return *this;
}
Complex &Complex::operator+=(const Complex &arg_c)
{
this->m_real += arg_c.m_real;
this->m_imag += arg_c.m_imag;
return *this;
}
Complex &Complex::operator-=(const Complex &arg_c)
{
this->m_real -= arg_c.m_real;
this->m_imag -= arg_c.m_imag;
return *this;
}
Complex &Complex::operator*=(const Complex &arg_c)
{
double _real = this->m_real, _imag = this->m_imag;
this->m_real = (_real * arg_c.m_real) - (_imag * arg_c.m_imag);
this->m_imag = (_real * arg_c.m_imag) + (_imag * arg_c.m_real);
return *this;
}
Complex &Complex::operator/=(const Complex &arg_c)
{
double _real = this->m_real, _imag = this->m_imag;
this->m_real = ((_real * arg_c.m_real) + (_imag * arg_c.m_imag))
/ ((arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag));
this->m_imag = ((-_real * arg_c.m_imag) + (_imag * arg_c.m_real))
/ ((arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag));
return *this;
}
std::ostream &operator<<(std::ostream &arg_os, const Complex &arg_point)
{
if (arg_point.m_imag == 0)
{
arg_os << arg_point.m_real;
return arg_os;
}
else if (arg_point.m_imag < 0)
{
arg_os << arg_point.m_real << " - " << -arg_point.m_imag << "i ";
return arg_os;
}
else
{
arg_os << arg_point.m_real << " + " << arg_point.m_imag << "i ";
return arg_os;
}
}
std::istream &operator>>(std::istream &arg_is, Complex &arg_point)
{
string str_x, str_y, temp;
if (getline(arg_is, str_x, ' '))
{
if (getline(arg_is, str_y, ' '))
{
arg_point.m_real = stod(str_x);
arg_point.m_imag = stod(str_y);
}
}
return arg_is;
}
class Complex_Calc
{
private:
Complex m_curr_val;
Complex m_input_val;
char m_op, op;
int process = 0;
void _calc_result()
{
switch (m_op)
{
case '+':
m_curr_val += m_input_val;
break;
case '-':
m_curr_val -= m_input_val;
break;
case '*':
m_curr_val *= m_input_val;
break;
case '/':
if (m_input_val.m_real == 0 && m_input_val.m_imag == 0)
{
error_and_exit();
}
else
{
m_curr_val /= m_input_val;
break;
}
case '=':
m_curr_val = m_input_val;
break;
}
}
void _add()
{
m_op = '+';
}
void _sub()
{
m_op = '-';
}
void _mul()
{
m_op = '*';
}
void _div()
{
m_op = '/';
}
void _assign()
{
m_op = '=';
}
public:
Complex_Calc();
Complex_Calc(const Complex_Calc &arg_int_calc);
~Complex_Calc(){};
void error_and_exit();
void set_input(const string &arg_input);
friend ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc);
};
Complex_Calc::Complex_Calc() : m_curr_val(), m_input_val(), m_op('=')
{
}
Complex_Calc::Complex_Calc(const Complex_Calc &arg_int_calc)
: m_curr_val(arg_int_calc.m_curr_val),
m_input_val(arg_int_calc.m_input_val),
m_op(arg_int_calc.m_op)
{
}
bool check_complex(const string &input)
{
string temp_str;
vector<string> vec;
stringstream terms_extractor(input);
while (terms_extractor >> temp_str)
{
vec.push_back(temp_str);
}
if (vec.size() == 2)
{
if ((!isdigit(vec[0][0]) && vec[0][0] != '-')
|| (!isdigit(vec[1][0]) && vec[1][0] != '-'))
{
return false;
}
for (int i = 1; i < vec[0].size(); i++)
{
if (isdigit(vec[0][i]) || vec[0][i] == '.')
{
continue;
}
else
{
return false;
}
}
for (int i = 1; i < vec[1].size(); i++)
{
if (isdigit(vec[1][i]) || vec[1][i] == '.')
{
continue;
}
else
{
return false;
}
}
}
else
{
return false;
}
return true;
}
bool check_op(const string &input)
{
if (input == "+" || input == "-" || input == "*" || input == "/")
{
return true;
}
else
{
return false;
}
}
void Complex_Calc::set_input(const string &arg_input)
{
if ((process % 2 == 1) && (check_op(arg_input) == true))
{
op = arg_input[0];
}
else if ((process % 2 == 0) && (check_complex(arg_input) == true))
{
switch (op)
{
case '+':
_add();
break;
case '-':
_sub();
break;
case '*':
_mul();
break;
case '/':
_div();
break;
case '=':
_assign();
break;
}
stringstream ss(arg_input);
ss >> m_input_val;
_calc_result();
}
else
{
error_and_exit();
}
process = process + 1;
}
void Complex_Calc::error_and_exit()
{
cout << "Error: Invalid input" << endl;
exit(1);
}
std::ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc)
{
arg_os << arg_comp_calc.m_curr_val;
return arg_os;
}
// main function
int main()
{
// create an instance of the class
Complex_Calc calc;
string input;
while (getline(cin, input))
{
calc.set_input(input);
cout << calc << endl;
}
}
TA
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;
class Complex_Calc;
class Complex
{
private:
// data members
// save the real and imaginary parts of the complex number
// with `double` precision
double m_real;
double m_imag;
public:
// Constructor, initializes real and imaginary parts
Complex(const double &arg_real = 0.0, const double &arg_imag = 0.0);
// Copy constructor
Complex(const Complex &arg_c);
// assignment operator
Complex &operator=(const Complex &arg_c);
// add assignment operator
Complex &operator+=(const Complex &arg_c);
// subtract assignment operator
Complex &operator-=(const Complex &arg_c);
// multiply assignment operator
Complex &operator*=(const Complex &arg_c);
// divide assignment operator
Complex &operator/=(const Complex &arg_c);
// add function
Complex operator+(const Complex &arg_c) const;
// subtract function
Complex operator-(const Complex &arg_c) const;
// multiply function
Complex operator*(const Complex &arg_c) const;
// divide function
Complex operator/(const Complex &arg_c) const;
// cout `<<` operator for print complex number
// note: be careful about the format of output
friend ostream &operator<<(ostream &arg_os, const Complex &arg_c);
// cin `>>` operator for input complex number
// note: use `>>` to parse the string to double,
// use `istream::fail()` to check the conversion is successful
// and use `istream::eof()` to check the is parse to the end of line
friend istream &operator>>(istream &arg_is, Complex &arg_c);
friend class Complex_Calc;
};
// Complex calculator class declaration
class Complex_Calc
{
private:
// define current value
Complex m_curr_val;
// define input value
Complex m_input_val;
// define operation
// `+`, `-`, `*`, `/`, and `=`
char m_op;
// define input status, turns `op` for true and turns `value` for false
bool m_op_input;
// calculate result
void _calc_result();
// operation functions
// set activation op to add
void _add();
// set activation op to subtract
void _sub();
// set activation op to multiply
void _mul();
// set activation op to divide
void _div();
// set activation op to assign
void _assign();
public:
// Constructor
Complex_Calc();
// Copy constructor
Complex_Calc(const Complex_Calc &arg_int_calc);
// Destructor
~Complex_Calc(){}; // no need to do anything
// set input value or operation
// as the same as the user input number or operation
// into the calculator
void set_input(const string &arg_input);
// cout `<<` operator for print calculator status
// note: be careful about the format of output
friend ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc);
};
// error and exit
void error_and_exit()
{
cerr << "Error: Invalid input" << endl;
exit(1);
}
// Complex class implementation
// Constructor, initializes real and imaginary parts
// hint: as like as `modify` function in examples
// but use default constructor to implement
Complex::Complex(const double &arg_real, const double &arg_imag)
: m_real(arg_real), m_imag(arg_imag)
{
}
// Copy constructor
Complex::Complex(const Complex &arg_c)
: m_real(arg_c.m_real), m_imag(arg_c.m_imag)
{
}
// assignment operator
Complex &Complex::operator=(const Complex &arg_c)
{
if (this == &arg_c) // self-assignment
return *this;
m_real = arg_c.m_real;
m_imag = arg_c.m_imag;
return *this;
}
// add assignment operator
Complex &Complex::operator+=(const Complex &arg_c)
{
m_real += arg_c.m_real;
m_imag += arg_c.m_imag;
return *this;
}
// subtract assignment operator
Complex &Complex::operator-=(const Complex &arg_c)
{
m_real -= arg_c.m_real;
m_imag -= arg_c.m_imag;
return *this;
}
// multiply assignment operator
Complex &Complex::operator*=(const Complex &arg_c)
{
double real = m_real * arg_c.m_real - m_imag * arg_c.m_imag;
double imag = m_real * arg_c.m_imag + m_imag * arg_c.m_real;
m_real = real;
m_imag = imag;
return *this;
}
// divide assignment operator
Complex &Complex::operator/=(const Complex &arg_c)
{
if (arg_c.m_real == 0 && arg_c.m_imag == 0)
error_and_exit();
double real = (m_real * arg_c.m_real + m_imag * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
double imag = (m_imag * arg_c.m_real - m_real * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
m_real = real;
m_imag = imag;
return *this;
}
// add function
Complex Complex::operator+(const Complex &arg_c) const
{
Complex c(*this);
c += arg_c;
return c;
}
// subtract function
Complex Complex::operator-(const Complex &arg_c) const
{
Complex c(*this);
c -= arg_c;
return c;
}
// multiply function
Complex Complex::operator*(const Complex &arg_c) const
{
Complex c(*this);
c *= arg_c;
return c;
}
// divide function
Complex Complex::operator/(const Complex &arg_c) const
{
Complex c(*this);
c /= arg_c;
return c;
}
// cout `<<` operator for print complex number
// note: be careful about the format of output
ostream &operator<<(ostream &arg_os, const Complex &arg_c)
{
if (arg_c.m_imag > 0)
{
arg_os << arg_c.m_real << " + " << arg_c.m_imag << "i";
}
else if (arg_c.m_imag < 0)
{
arg_os << arg_c.m_real << " - " << -arg_c.m_imag << "i";
}
else
{
arg_os << arg_c.m_real;
}
return arg_os;
}
// cin `>>` operator for input complex number
// note: be careful about the format of input
istream &operator>>(istream &arg_is, Complex &arg_c)
{
double input_real, input_imag;
arg_is >> input_real;
if (arg_is.fail())
{
error_and_exit();
}
arg_is >> input_imag;
if (arg_is.fail() || !arg_is.eof())
{
error_and_exit();
}
arg_c.m_real = input_real;
arg_c.m_imag = input_imag;
return arg_is;
}
// Complex_Calc class implementation
// Constructor
Complex_Calc::Complex_Calc()
: m_curr_val(), m_input_val(), m_op('='), m_op_input(false)
{
}
// Copy constructor
Complex_Calc::Complex_Calc(const Complex_Calc &arg_int_calc)
: m_curr_val(arg_int_calc.m_curr_val),
m_input_val(arg_int_calc.m_input_val),
m_op(arg_int_calc.m_op),
m_op_input(arg_int_calc.m_op_input)
{
}
void Complex_Calc::set_input(const string &arg_input)
{
// input is empty, read again
if (arg_input.empty())
return;
// input is a operator in right turn
else if (m_op_input && (arg_input == "+" || arg_input == "-"
|| arg_input == "*" || arg_input == "/" || arg_input == "="))
{
// set the activated operation
// as the same as the user press the op button
switch (arg_input[0])
{
case '+':
_add();
break;
case '-':
_sub();
break;
case '*':
_mul();
break;
case '/':
_div();
break;
case '=':
_assign();
break;
}
// set to 'input a complex number' turn
m_op_input = false;
}
// input is a complex number in right turn
// as the same as the user type a number
// it performs as the same as the user pressed the '=' button
// if the input is the first input
// thus, we initialize the m_op to '='
else if (!m_op_input)
{
stringstream ss(arg_input);
ss >> m_input_val;
_calc_result();
m_op_input = true;
}
// else, input is invalid
else
{
error_and_exit();
}
}
void Complex_Calc::_calc_result()
{
switch (m_op)
{
case '+':
m_curr_val += m_input_val;
break;
case '-':
m_curr_val -= m_input_val;
break;
case '*':
m_curr_val *= m_input_val;
break;
case '/':
m_curr_val /= m_input_val;
break;
case '=':
m_curr_val = m_input_val;
break;
}
}
// add the input value to the current value
void Complex_Calc::_add()
{
m_op = '+';
}
// subtract the input value from the current value
void Complex_Calc::_sub()
{
m_op = '-';
}
// multiply the input value with the current value
void Complex_Calc::_mul()
{
m_op = '*';
}
// divide the current value by the input value
void Complex_Calc::_div()
{
m_op = '/';
}
// assign the input value to the current value
void Complex_Calc::_assign()
{
m_op = '=';
}
// cout `<<` operator for print calculator status
ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc)
{
arg_os << arg_comp_calc.m_curr_val;
return arg_os;
}
// main function
int main()
{
// create an instance of the class
Complex_Calc calc;
string input;
while (getline(cin, input))
{
calc.set_input(input);
cout << calc << endl;
}
}