Lab 4-3: Advance Complex Number Calculation (15%)
- 輸入:
- 以
double
格式輸入複數的實數及虛數部分,以空格分開,一行輸入一個複數 - 以
char
格式輸入複數的運算子,包含+
、-
、*
、/
,一行輸入一個運算子 - 複數與運算子以交錯的方式輸入,一行輸入一個複數接著一個運算子,倒數兩行為複數與完成輸入指令
- 輸入 Ctrl+D 完成輸入
- Windows 請輸入 Ctrl+Z (會在螢幕上顯示
^Z
) 再輸入 Enter (Format 中的⏎
) 完成輸入
- Windows 請輸入 Ctrl+Z (會在螢幕上顯示
- 程式輸入以行為單位,每行輸入為任何有效的
string
格式
- 以
- 輸出:
- 顯示運算複數的結果
- 若使用者輸入的複數或運算子不正確,則顯示錯誤訊息
Error: Invalid input
並結束程式
- 檔名:
lab4-3_<學號>.cpp
(e.g.lab4-3_106062802.cpp
)
注意事項:
- 程式不會輸出任何使用者提示,只會輸出程式結果或錯誤訊息
- 程式僅需處裡輸入錯誤的例外狀況,如輸入的複數或運算子不正確,其餘錯誤不須處裡
- 請基於 pseudo code 提供的 main function 進行修改來處理輸入與輸出
- 程式需要於 10 秒內完成,所有的測資皆會保證於 10 秒內完成
Format
<real 1> <imag 1>⏎
<op 1>⏎
<real 2> <imag 2>⏎
<op 2>⏎
...
<real n-1> <imag n-1>⏎
<op n-1>⏎
<real n> <imag n>⏎
^Z⏎
<real result> + <imag result> i
Example
Normal
$ ./a.out
1.0 0.0⏎
^Z⏎
1 + 0 i
$
$ ./a.out
1.0 0.0⏎
+⏎
2.0 1.1⏎
-⏎
-3.0 -2.2⏎
*⏎
4.3 2.1⏎
/⏎
-1.2 -3.4⏎
^Z⏎
-8.74846 + 2.46231 i
$
Exception Handling
$ ./a.out
+⏎
Error: Invalid input
$
$ ./a.out
1.0 0.0⏎
+⏎
^Z⏎
Error: Invalid input
$
$ ./a.out
1.0 0.0⏎
1.0 0.0⏎
Error: Invalid input
$
$ ./a.out
1.0 0.0⏎
+⏎
+⏎
Error: Invalid input
$
$ ./a.out
^Z⏎
Error: Invalid input
$
$ ./a.out
1.0 2.0 3.0⏎
Error: Invalid input
$
$ ./a.out
1.0 2.0⏎
sdafsdagret⏎
Error: Invalid input
$
$ ./a.out
sdoifjwepoirjpwoie⏎
Error: Invalid input
$
Pseudo Code
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Complex
{
private:
// data members
// save the real and imaginary parts of the complex number
// with `double` precision
public:
// Constructor, initializes real and imaginary parts
// hint: as like as `modify` function in examples
// but use default constructor to implement
// print function
// note: be careful about the format of output
// especially the ` ` and newline (endl)
void print();
// add function
// subtract function
// multiply function
// divide function
// parse function
// note: use `stringstream` and `>>` to parse the string to double
// and use `stringstream::fail()` to check the conversion is successful
};
// parse op global function
char parse_op(const string &arg_str);
// prompt invalid input and exit
void prompt_invalid_input()
{
cout << "Error: Invalid input" << endl;
exit(1);
}
int main()
{
string input;
Complex result_complex;
char op = ' '; // default op is ' '
bool is_process_continue = true; // current process should be continued or not
while (is_process_continue)
{
// get the first input
// check is not end of input
if (input.empty() || cin.eof())
{
prompt_invalid_input();
}
// check the input is a valid complex number
// calculate the result
// get the second input
// check is end of input or not
if (input.empty() || cin.eof())
{
is_process_continue = false;
}
// if not end of input, check the input is a valid operator
}
result_complex.print();
return 0;
}
Reference Code:
藍珮芳(110021116)
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
class Complex
{
private:
double m_real;
double m_imag;
public:
Complex(double arg_real = 0.0, double arg_imag = 0.0)
{
m_real = arg_real;
m_imag = arg_imag;
}
void print()
{
cout << m_real << " + " << m_imag << " i\n";
};
Complex add(Complex &arg_c)
{
Complex temp;
temp.m_real = m_real + arg_c.m_real;
temp.m_imag = m_imag + arg_c.m_imag;
return temp;
};
Complex sub(Complex &arg_c)
{
Complex temp;
temp.m_real = m_real - arg_c.m_real;
temp.m_imag = m_imag - arg_c.m_imag;
return temp;
};
Complex mul(Complex &arg_c)
{
Complex temp;
temp.m_real = m_real * arg_c.m_real - m_imag * arg_c.m_imag;
temp.m_imag = m_real * arg_c.m_imag + m_imag * arg_c.m_real;
return temp;
};
Complex div(Complex &arg_c)
{
Complex temp;
temp.m_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);
temp.m_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);
return temp;
};
};
bool check_complex(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(string &input)
{
if (input == "+" || input == "-" || input == "*" || input == "/")
{
return true;
}
else
{
return false;
}
}
int main()
{
string input;
Complex result_complex;
char op = ' ';
int process = 0;
while (getline(cin, input))
{
if ((process % 2 == 1) && (check_op(input) == true))
{
op = input[0];
}
else if ((process % 2 == 0) && (check_complex(input) == true))
{
double real, imag;
stringstream ss(input);
ss >> real >> imag;
Complex current_complex(real, imag);
switch (op)
{
case '+':
result_complex = result_complex.add(current_complex);
break;
case '-':
result_complex = result_complex.sub(current_complex);
break;
case '*':
result_complex = result_complex.mul(current_complex);
break;
case '/':
result_complex = result_complex.div(current_complex);
break;
case ' ':
result_complex = current_complex;
break;
default:
cerr << "Error: unknown operation\n";
return 1;
}
}
else
{
cout << "Error: Invalid input" << endl;
return 0;
}
process = process + 1;
}
if (process = 0 || process % 2 == 1)
{
result_complex.print();
}
else
{
cout << "Error: Invalid input" << endl;
}
return 0;
}
TA
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void prompt_invalid_input();
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
// hint: as like as `modify` function in examples
// but use default constructor to implement
Complex(const double &arg_real = 0.0, const double &arg_imag = 0.0)
{
m_real = arg_real;
m_imag = arg_imag;
}
// print function
// note: be careful about the format of output
// especially the ` ` and newline (endl)
void print()
{
cout << m_real << " + " << m_imag << " i" << endl;
}
// add function
Complex add(const Complex &arg_c)
{
Complex c;
c.m_real = m_real + arg_c.m_real;
c.m_imag = m_imag + arg_c.m_imag;
return c;
}
// subtract function
Complex sub(const Complex &arg_c)
{
Complex c;
c.m_real = m_real - arg_c.m_real;
c.m_imag = m_imag - arg_c.m_imag;
return c;
}
// multiply function
Complex mul(const Complex &arg_c)
{
Complex c;
c.m_real = m_real * arg_c.m_real - m_imag * arg_c.m_imag;
c.m_imag = m_real * arg_c.m_imag + m_imag * arg_c.m_real;
return c;
}
// divide function
Complex div(const Complex &arg_c)
{
if (arg_c.m_real == 0 && arg_c.m_imag == 0)
prompt_invalid_input();
Complex c;
c.m_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);
c.m_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);
return c;
}
// parse function
// note: use `stringstream` and `>>` to parse the string to double
// and use `stringstream::fail()` to check the conversion is successful
bool parse(const string &arg_str)
{
// Check if the number of tokens = 2
for (int i = 0, n = 0; i < arg_str.length(); i++)
{
if (arg_str[i] == ' ')
n++;
if (n > 1 || (n == 0 && i == arg_str.length() - 1))
return false;
}
stringstream ss(arg_str);
double input_real, input_imag;
ss >> input_real;
if (ss.fail())
{
return false;
}
ss >> input_imag;
if (ss.fail())
{
return false;
}
m_real = input_real;
m_imag = input_imag;
return ss.eof();
}
};
// parse op global function
char parse_op(const string &arg_str)
{
switch (arg_str[0])
{
case '+':
case '-':
case '*':
case '/':
return arg_str[0];
default:
return '\0'; // invalid op
}
}
// prompt invalid input and exit
void prompt_invalid_input()
{
cout << "Error: Invalid input" << endl;
exit(1);
}
int main()
{
string input;
Complex result_complex;
char op = ' '; // default op is ' '
bool is_process_continue = true; // current process should be continued or not
while (is_process_continue)
{
// get the first input
getline(cin, input);
// check is not end of input
if (input.empty() || cin.eof())
{
prompt_invalid_input();
}
// check the input is a valid complex number
Complex input_complex;
bool is_valid_complex = input_complex.parse(input);
if (!is_valid_complex)
{
prompt_invalid_input();
}
// calculate the result
switch (op)
{
case '+':
result_complex = result_complex.add(input_complex);
break;
case '-':
result_complex = result_complex.sub(input_complex);
break;
case '*':
result_complex = result_complex.mul(input_complex);
break;
case '/':
result_complex = result_complex.div(input_complex);
break;
case ' ':
result_complex = input_complex;
break;
default:
prompt_invalid_input();
}
// get the second input
getline(cin, input);
// check is end of input or not
if (input.empty() || cin.eof())
{
is_process_continue = false;
}
// if not end of input, check the input is a valid operator
else
{
op = parse_op(input);
if (op == '\0')
{
prompt_invalid_input();
}
}
}
result_complex.print();
return 0;
}