Lab 6-2: Simple Complex Number Calculator (40%)
- 輸入:
- 以
double
格式輸入複數的實數及虛數部分,以空格分開,一行輸入一個複數 - 以
char
格式輸入複數的運算子,包含+
、-
、*
、/
,一行輸入一個運算子 - 複數與運算子以交錯的方式輸入,一行輸入一個複數接著一個運算子,倒數一行為複數
- 輸入 Ctrl+D 結束程式
- Windows 請輸入 Ctrl+Z (會在螢幕上顯示
^Z
) 再輸入 Enter (Format 中的⏎
) 結束程式
- 以
- 輸出:
- 顯示運算複數的結果
- 複數的格式為
(-)<real result> (+|-) (<imag result>i)
- 若輸入運算子、需顯示之前運算的結果,如 Example 的範例
- 檔名:
lab6-2_<學號>.cpp
(e.g.lab6-2_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
$ ./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
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⏎
$
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: be careful about the format of input
// hint: use `stod` to convert string to double
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;
// calculate result
void _calc_result();
// operation functions
// add the input value to the current value
void _add();
// subtract the input value from the current value
void _sub();
// multiply the input value with the current value
void _mul();
// divide the current value by the input value
void _div();
// assign the input value to the current value
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
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);
};
// parse the test cases, do not modify belows
void Complex_Calc::set_input(const string &arg_input)
{
// input is empty, read again
if (arg_input.empty())
{
return;
}
// input is a operation
else if (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;
}
}
// 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;
_calc_result();
}
}
// 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:
林恩佑(109021107)
#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: be careful about the format of input
// hint: use stod to convert string to double
friend istream &operator>>(istream &arg_is, Complex &arg_c);
friend class Complex_Calc;
};
Complex::Complex(const double &arg_real, const double &arg_image)
: m_real(arg_real), m_imag(arg_image)
{
}
Complex::Complex(const Complex &arg_c)
: m_real(arg_c.m_real), m_imag(arg_c.m_imag)
{
}
Complex &Complex::operator=(const Complex &arg_c)
{
m_real = arg_c.m_real;
m_imag = arg_c.m_imag;
return *this;
}
Complex &Complex::operator+=(const Complex &arg_c)
{
m_real += arg_c.m_real;
m_imag += arg_c.m_imag;
return *this;
}
Complex &Complex::operator-=(const Complex &arg_c)
{
m_real -= arg_c.m_real;
m_imag -= arg_c.m_imag;
return *this;
}
Complex &Complex::operator*=(const Complex &arg_c)
{
Complex a;
a.m_real = m_real;
a.m_imag = m_imag;
m_real = a.m_real * arg_c.m_real - a.m_imag * arg_c.m_imag;
m_imag = a.m_real * arg_c.m_imag + arg_c.m_real * a.m_imag;
return *this;
}
Complex &Complex::operator/=(const Complex &arg_c)
{
Complex a;
a.m_real = m_real;
a.m_imag = m_imag;
m_real = (a.m_real * arg_c.m_real + a.m_imag * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
m_imag = (arg_c.m_real * a.m_imag - a.m_real * arg_c.m_imag)
/ (arg_c.m_real * arg_c.m_real + arg_c.m_imag * arg_c.m_imag);
return *this;
}
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 << " - " << 0.0 - arg_c.m_imag << "i";
}
else
{
arg_os << arg_c.m_real << " + " << arg_c.m_imag << "i";
}
return arg_os;
}
istream &operator>>(istream &arg_is, Complex &arg_c)
{
string strs;
size_t sz;
arg_c = {0, 0};
arg_is >> strs;
try
{
arg_c.m_real = stod(strs);
}
catch (const invalid_argument &ia)
{
}
strs = "";
arg_is >> strs;
try
{
arg_c.m_imag = stod(strs);
}
catch (const invalid_argument &ia)
{
}
return arg_is;
}
// 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;
// calculate result
void _calc_result();
// operation functions
// add the input value to the current value
void _add();
// subtract the input value from the current value
void _sub();
// multiply the input value with the current value
void _mul();
// divide the current value by the input value
void _div();
// assign the input value to the current value
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
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);
};
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)
{
}
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;
default:
break;
}
}
void Complex_Calc::_add()
{
m_op = '+';
}
void Complex_Calc::_sub()
{
m_op = '-';
}
void Complex_Calc::_mul()
{
m_op = '*';
}
void Complex_Calc::_div()
{
m_op = '/';
}
void Complex_Calc::_assign()
{
m_op = '=';
}
ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc)
{
Complex arg_c = arg_comp_calc.m_curr_val;
arg_os << arg_c;
return arg_os;
}
/*
ostream &operator<<(ostream &arg_os, const Complex_Calc &arg_comp_calc){
if (arg_c.m_imag==0){
arg_os << arg_c.m_real <<endl;
}
else if (arg_c.m_imag<0){
arg_c.m_imag*=(-1);
arg_os<<arg_c.m_real<<" - "<<arg_c.m_imag<<" i"<<endl;
}
else{
arg_os << arg_c.m_real << " + " << arg_c.m_imag <<" i"<<endl;
}
return arg_os;
}
*/
// parse the test cases, do not modify belows
void Complex_Calc::set_input(const string &arg_input)
{
// input is empty, read again
if (arg_input.empty())
{
return;
}
// input is a operation
else if (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;
}
}
// 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;
_calc_result();
}
}
// 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;
arg_is >> input_imag;
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)
{
}
// parse the test cases, do not modify belows
void Complex_Calc::set_input(const string &arg_input)
{
// input is empty, read again
if (arg_input.empty())
{
return;
}
// input is a operation
else if (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;
}
}
// 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;
_calc_result();
}
}
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;
}
}