北邮22信通一枚~
跟随课程进度更新北邮信通院DSP的笔记、代码和文章,欢迎关注~
获取更多文章,请访问专栏:
目录
一、原理
可以发现,h(n)和w(n)都是关于n=M中心对称的。
举个例子
以单位冲激响应为例,取M=10,验证每一项的对称性。
#include<iostream> #include<cmath> const double PI = acos(-1.0); using namespace std; const double MIN = 1e-5; int main() { system("color 0A"); int m = 10; double temp = 0; for (int i = 0; i <= 2*m; i++) { cout << "第"; if (i < 10)cout << "0"; cout<< i << "项:"; temp = sin((i - m) * 1.0) / ((i - m) * PI); if (abs(temp) < MIN)temp = 0; cout << temp << endl; } return 0; }
输出结果为:
发现取值群确实关于M(M=10)呈中心对称。
举个例子
以布莱克曼窗为例,取M=10,验证每一项的对称性。
#include<iostream> #include<cmath> const double PI = acos(-1.0); using namespace std; const double MIN = 1e-5; int main() { system("color 0A"); int m = 10; double temp = 0; for (int i = 0; i <= 2*m; i++) { cout << "第" << i << "项:"; temp = 0.42 - 0.50 * cos(i * PI / m) + 0.08 * cos(2 * i * PI / m); if (abs(temp) < MIN)temp = 0; cout << temp << endl; } return 0; }
输出的结果为:
发现取值群确实关于M(M=10)呈中心对称。
综上,
对于所有的序列存储,存储空间都可以减少一半;
对于所有的序列运算,计算时间都可以减少一半。
二、新增变量
long double center_hn, center_wn, center_que;
由于size(hd(n))==size(w(n))==size(h(n))==2*M+1,长度是奇数,所以中心对称点是第M+1项,所以第M+1项的对称项还是自己,这个点比较特殊,需要单独拿出来计算,所以设置了center_hn,center_wn和center_que三个变量,用来储存三个序列的中心对称点,以及进行中心对称点之间的运算。
三、改进
所有的改进其实都遵循同一原则,即先计算并存储前M项,之后单独计算第M+1项(即中心对称点),最后倒序输出前M项。
3.1对hd(n)存储空间和运算速度的改进
原代码:
void hn_calculate()
{
cout << endl << "hd(n)的计算结果为:hd(n) = " << endl;
ld temp = 0;
bool is_limit = 0;
for (int i = 0; i < N; i++)
{
is_limit = (i == M);
switch (filter_type)
{
case IS_LP:
temp = (is_limit == 1) ? (c2 / PI) :
sin((i - M) * c2) / ((i - M) * PI); break;
case IS_HP:
temp = (is_limit == 1) ? (1 - c1 / PI) :
sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BP:
temp = (is_limit == 1) ? (c2 / PI - c1 / PI) :
sin((i - M) * c2) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BS:
temp = (is_limit == 1) ? (c1 / PI + 1 - c2 / PI) :
sin((i - M) * c1) / ((i - M) * PI) +
sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c2) / ((i - M) * PI); break;
default:
throw"error:hn_calculate_switch_invalid_filter_type!"; break;
}
if (abs(temp) <= MIN)temp = 0;
que_hn.push_back(temp);
print(temp, i);
}
}
改进后的代码:
void hn_calculate()
{
cout << endl << "hd(n)的计算结果为:hd(n) = " << endl;
ld temp = 0;
//入队0——M-1项
for (int i = 0; i < M; i++)
{
switch (filter_type)
{
case IS_LP:
temp = sin((i - M) * c2) / ((i - M) * PI); break;
case IS_HP:
temp = sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BP:
temp = sin((i - M) * c2) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BS:
temp = sin((i - M) * c1) / ((i - M) * PI) +
sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c2) / ((i - M) * PI); break;
default:
throw"error:hn_calculate_switch_invalid_filter_type!"; break;
}
//近似估计
if (abs(temp) <= MIN)temp = 0;
que_hn.push_back(temp);
print(temp, i);
}
//中心值 第M+1个值
switch (filter_type)
{
case IS_LP:
temp = c2 / PI; break;
case IS_HP:
temp = 1 - c1 / PI; break;
case IS_BP:
temp = c2 / PI - c1 / PI; break;
case IS_BS:
temp = c1 / PI + 1 - c2 / PI; break;
default:
throw"error:hn_calculate_center_switch_invalid_filter_type!"; break;
}
print(temp, M);
center_hn = temp;
//从尾部出队,并从头部入队
for (int i = M + 1; i < N; i++)
{
temp = que_hn.back();
que_hn.pop_back();
que_hn.push_front(temp);
print(temp, i);
}
//循环过后,que_hn中的顺序还是0~M项。
cout << endl << "hd(n)的长度为:" << 2 * que_hn.size() + 1;
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
cout << endl << endl;
}
3.2对w(n)存储空间和运算速度的改进
原代码:
void wn_calculate()
{
cout << endl << "w(n)的计算结果为:w(n) = " << endl;
ld temp = 0;
for (int i = 0; i < N; i++)
{
temp = window_type.a - window_type.b * cos(i * PI / M) +
window_type.c * cos(2 * i * PI / M);
if (abs(temp) <= MIN)temp = 0;
que_wn.push_back(temp);
print(temp, i);
}
cout << endl << "w(n)的长度为:" << que_wn.size();
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
改进后的代码:
void wn_calculate()
{
cout << endl << "w(n)的计算结果为:w(n) = " << endl;
ld temp = 0;
for (int i = 0; i < M; i++)
{
temp = window_type.a - window_type.b * cos(i * PI / M)
+ window_type.c * cos(2 * i * PI / M);
que_wn.push_back(temp);
print(temp, i);
}
//中心值
center_que = 1;
print(center_que, M);
for (int i = M + 1; i < N; i++)
{
temp = que_wn.back();
que_wn.pop_back();
print(temp, i);
que_wn.push_front(temp);
}
cout << endl << "w(n)的长度为:" << 2 * que_wn.size() + 1;
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
3.3对h(n)存储空间和运算速度的改进
原代码:
void que_calculate()
{
cout << endl << "h(n)的计算结果为:h(n) = " << endl;
ld temp = 0;
for (int i = 0; i < N; i++)
{
temp = que_hn.front() * que_wn.front();
que.push_back(temp);
print(temp, i);
que_hn.push_back(que_hn.front()); que_hn.pop_front();
que_wn.push_back(que_wn.front()); que_wn.pop_front();
}
cout << endl << "h(n)的长度为:" << que.size();
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
改进后的代码:
void que_calculate()
{
cout << endl << "h(n)的计算结果为:h(n) = " << endl;
ld temp = 0;
if (window_type.type != RECTANG)
{
for (int i = 0; i < M; i++)
{
temp = que_hn.front() * que_wn.front();
que.push_back(temp);
print(temp, i);
que_hn.push_back(que_hn.front()); que_hn.pop_front();
que_wn.push_back(que_wn.front()); que_wn.pop_front();
}
//中心值
center_que = center_hn * center_wn;
print(center_que, M);
for (int i = M + 1; i < N; i++)
{
temp = que.back();
que.pop_back();
print(temp, i);
que.push_front(temp);
}
}
//如果是矩形窗,那就不用计算了,直接输出hn即可。
else
{
for (int i = 0; i < M; i++)
{
temp = que_hn.front();
que_hn.pop_front();
que_hn.push_back(temp);
print(temp, i);
}
//中心值
print(center_hn, M);
for (int i = M + 1; i < N; i++)
{
temp = que_hn.back();
que_hn.pop_back();
que_hn.push_front(temp);
print(temp, i);
}
}
cout << endl << "h(n)的长度为:" << 2 * que.size() + 1;
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
四、代码部分
4.1总体代码
#include<iostream>
#include<cmath>
#include<deque>
#include <sstream>
#include<iomanip>
#include<cstring>
#include<string>
#include<deque>
using namespace std;
#define ERROR 0
#define RECTANG 1
#define HANNING 2
#define HAMMING 3
#define BLACKMN 4
#define IS_LP 5
#define IS_HP 6
#define IS_BP 7
#define IS_BS 8
#define UN_KNOWN 9
#define MIN 10e-9
typedef long double ld;
const double PI = acos(-1.0);
//表达式中对小数的精确度
const int define_setpercision = 2;
//阻带衰减最大近似容忍度
const int tolerate = 3;
struct window_data
{
int type;
double a, b, c;
ld accurate_transition_bandwith;
ld approximate_transition_bandwith;
ld sidelobe_peak_attenuation;
ld min_stopband_attenuation;
bool operator == (window_data w)
{
return ((this->type == w.type) && (this->a == w.a) && (this->b == w.b) && (this->c == w.c) &&
(this->accurate_transition_bandwith == w.accurate_transition_bandwith) &&
(this->approximate_transition_bandwith == w.approximate_transition_bandwith) &&
(this->sidelobe_peak_attenuation == w.sidelobe_peak_attenuation) &&
(this->min_stopband_attenuation == w.min_stopband_attenuation)) ? true : false;
}
friend ostream& operator <<(ostream& output, window_data window_type)
{
output << "window_type_data_detecting……" << endl;
output << "window_type.type = " << window_type.type << endl;
output << "window_type.a = " << window_type.a << endl;
output << "window_type.b = " << window_type.b << endl;
output << "window_type.c = " << window_type.c << endl;
output << "window_type.accurate_transition_bandwith = " <<
window_type.accurate_transition_bandwith << endl;
output << "window_type.approximate_transition_bandwith = " <<
window_type.approximate_transition_bandwith << endl;
output << "window_type.sidelobe_peak_attenuation = " <<
window_type.sidelobe_peak_attenuation << endl;
output << "window_type.min_stopband_attenuation = " <<
window_type.min_stopband_attenuation << endl;
output << endl << endl;
return output;
}
};
window_data windows[5] =
{
{},
{ RECTANG, 1.00, 0.00, 0.00, 1.80 * PI, 4.00 * PI, 13, 21 },
{ HANNING, 0.50, 0.50, 0.00, 6.20 * PI, 8.00 * PI, 32, 44 },
{ HAMMING, 0.54, 0.46, 0.00, 6.60 * PI, 8.00 * PI, 43, 53 },
{ BLACKMN, 0.42, 0.50, 0.08, 11.0 * PI, 12.0 * PI, 58, 74 }
};
int filter_type;
window_data window_type;
static int N, M;
ld p1, p2, s1, s2, As, fs, c1, c2;
deque<ld>que_hn; //长度N
deque<ld>que_wn; //长度N
deque<ld>que; //长度N
ld center_hn, center_wn, center_que;
//选择窗的类型
window_data choose()
{
int i = 1;
while (As > windows[i].min_stopband_attenuation)i++;
if (i < 5)return windows[i];
else if (i >= 5 && (As - windows[4].min_stopband_attenuation) <= tolerate)return windows[4];
else
throw"error:non_window_suits!";
}
void print(ld data, int pos)
{
cout << setiosflags(ios::fixed) <<
setprecision(4) << showbase << data << " ";
if (pos % 5 == 4)cout << endl;
}
//判断选通滤波器类型
int check_types(ld p1, ld p2, ld s1, ld s2)
{
if (p1 > p2 || s1 > s2 || s1 == p2 ||
s2 == p1 || s1 == s2 || p1 == p2)
return ERROR;
if (s1 * p1 != 0)
return (p2 > p1 && s2 > s1 && p1 != s1 && p2 != s2) ?
((p1 > s1) ? IS_BP : IS_BS) : (ERROR);
else
return (s2 != p2) ? (s2 < p2 ? IS_HP : IS_LP) : (ERROR);
}
void change()
{
//数字频率转换为数字角频率wp1,wp2,ws1,ws2;
p1 *= (2 * PI / fs); p2 *= (2 * PI / fs);
s1 *= (2 * PI / fs); s2 *= (2 * PI / fs);
//求得wc1,wc2,相当于w0 - wc, w0 + wc;
c1 = (p1 + s1) / 2; c2 = (p2 + s2) / 2;
//计算N、M
window_type = choose();
if (filter_type == IS_BP || filter_type == IS_BS)
if (abs(s2 - p2) != abs(s1 - p1))throw"error:非对称过渡带宽!";
//谁不等于0就用谁
N = (s1 - p1 == 0) ?
ceil(window_type.accurate_transition_bandwith / abs(s2 - p2)) :
ceil(window_type.accurate_transition_bandwith / abs(s1 - p1));
N = (N % 2 == 1) ? N : (N + 1);
M = (N - 1) / 2;
}
auto format_double_value(double val, int fixed) {
std::ostringstream oss;
oss << std::setprecision(fixed) << val;
return oss.str();
}
void hn_output()
{
cout << endl << "hd(n)表达式为:h(n) = ";
string string_pi = "sin(n-" + format_double_value(M, define_setpercision) + ")π/"
+ "((n-" + to_string(M) + ")π)";
string string_c1 = "sin(n-" + to_string(M) + ")"
+ format_double_value(c1 / PI, define_setpercision) + "π/"
+ "((n-" + to_string(M) + ")π)";
string string_c2 = "sin(n-" + to_string(M) + ")"
+ format_double_value(c2 / PI, define_setpercision) + "π/"
+ "((n-" + to_string(M) + ")π)";
//对lp来说,c1=0,对hp来说,c2=0
switch (filter_type)
{
case IS_LP:
cout << string_c2; break;
case IS_HP:
cout << string_pi << " - " << string_c1; break;
case IS_BP:
cout << string_c2 << " - " << string_c1; break;
case IS_BS:
cout << string_c1 << " + " << string_pi
<< " - " << string_c2; break;
default:
throw"error:hn_output!"; break;
}
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
//原代码
/*
void hn_calculate()
{
cout << endl << "hd(n)的计算结果为:hd(n) = " << endl;
ld temp = 0;
bool is_limit = 0;
for (int i = 0; i < N; i++)
{
is_limit = (i == M);
switch (filter_type)
{
case IS_LP:
temp = (is_limit == 1) ? (c2 / PI) :
sin((i - M) * c2) / ((i - M) * PI); break;
case IS_HP:
temp = (is_limit == 1) ? (1 - c1 / PI) :
sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BP:
temp = (is_limit == 1) ? (c2 / PI - c1 / PI) :
sin((i - M) * c2) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BS:
temp = (is_limit == 1) ? (c1 / PI + 1 - c2 / PI) :
sin((i - M) * c1) / ((i - M) * PI) +
sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c2) / ((i - M) * PI); break;
default:
throw"error:hn_calculate_switch_invalid_filter_type!"; break;
}
if (abs(temp) <= MIN)temp = 0;
que_hn.push_back(temp);
print(temp, i);
}
}
*/
//改进后的代码
void hn_calculate()
{
cout << endl << "hd(n)的计算结果为:hd(n) = " << endl;
ld temp = 0;
//入队0——M-1项
for (int i = 0; i < M; i++)
{
switch (filter_type)
{
case IS_LP:
temp = sin((i - M) * c2) / ((i - M) * PI); break;
case IS_HP:
temp = sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BP:
temp = sin((i - M) * c2) / ((i - M) * PI) -
sin((i - M) * c1) / ((i - M) * PI); break;
case IS_BS:
temp = sin((i - M) * c1) / ((i - M) * PI) +
sin((i - M) * PI) / ((i - M) * PI) -
sin((i - M) * c2) / ((i - M) * PI); break;
default:
throw"error:hn_calculate_switch_invalid_filter_type!"; break;
}
//近似估计
if (abs(temp) <= MIN)temp = 0;
que_hn.push_back(temp);
print(temp, i);
}
//中心值 第M+1个值
switch (filter_type)
{
case IS_LP:
temp = c2 / PI; break;
case IS_HP:
temp = 1 - c1 / PI; break;
case IS_BP:
temp = c2 / PI - c1 / PI; break;
case IS_BS:
temp = c1 / PI + 1 - c2 / PI; break;
default:
throw"error:hn_calculate_center_switch_invalid_filter_type!"; break;
}
print(temp, M);
center_hn = temp;
//从尾部出队,并从头部入队
for (int i = M + 1; i < N; i++)
{
temp = que_hn.back();
que_hn.pop_back();
que_hn.push_front(temp);
print(temp, i);
}
//循环过后,que_hn中的顺序还是0~M项。
cout << endl << "hd(n)的长度为:" << 2 * que_hn.size() + 1;
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
cout << endl << endl;
}
//内部调用
string string_create(double A, double B, double C)
{
string string_a, string_b, string_c, string_final;
string_a = format_double_value(A, define_setpercision);
string_b = " - " + format_double_value(B, define_setpercision)
+ "cos(2nπ/("
+ to_string(N) + "-1))";
string_c = " + " + format_double_value(C, define_setpercision)
+ "cos(4nπ/("
+ to_string(N) + "-1))";
if (B)string_a += string_b;
if (C)string_a += string_c;
return string_a;
}
void wn_output()
{
cout << endl << "w(n)的表达式为:w(n) = ";
if (window_type.type >= RECTANG && window_type.type <= BLACKMN)
cout << string_create(window_type.a, window_type.b, window_type.c);
else throw"error:wn_output_invalid_window_type.type!";
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
//原代码
/*
void wn_calculate()
{
cout << endl << "w(n)的计算结果为:w(n) = " << endl;
ld temp = 0;
for (int i = 0; i < N; i++)
{
temp = window_type.a - window_type.b * cos(i * PI / M) +
window_type.c * cos(2 * i * PI / M);
if (abs(temp) <= MIN)temp = 0;
que_wn.push_back(temp);
print(temp, i);
}
cout << endl << "w(n)的长度为:" << que_wn.size();
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}*/
//改进后的代码
void wn_calculate()
{
cout << endl << "w(n)的计算结果为:w(n) = " << endl;
ld temp = 0;
for (int i = 0; i < M; i++)
{
temp = window_type.a - window_type.b * cos(i * PI / M)
+ window_type.c * cos(2 * i * PI / M);
que_wn.push_back(temp);
print(temp, i);
}
//中心值
center_que = 1;
print(center_que, M);
for (int i = M + 1; i < N; i++)
{
temp = que_wn.back();
que_wn.pop_back();
print(temp, i);
que_wn.push_front(temp);
}
cout << endl << "w(n)的长度为:" << 2 * que_wn.size() + 1;
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
//原代码
/*
void que_calculate()
{
cout << endl << "h(n)的计算结果为:h(n) = " << endl;
ld temp = 0;
for (int i = 0; i < N; i++)
{
temp = que_hn.front() * que_wn.front();
que.push_back(temp);
print(temp, i);
que_hn.push_back(que_hn.front()); que_hn.pop_front();
que_wn.push_back(que_wn.front()); que_wn.pop_front();
}
cout << endl << "h(n)的长度为:" << que.size();
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
*/
//改进后的代码
void que_calculate()
{
cout << endl << "h(n)的计算结果为:h(n) = " << endl;
ld temp = 0;
if (window_type.type != RECTANG)
{
for (int i = 0; i < M; i++)
{
temp = que_hn.front() * que_wn.front();
que.push_back(temp);
print(temp, i);
que_hn.push_back(que_hn.front()); que_hn.pop_front();
que_wn.push_back(que_wn.front()); que_wn.pop_front();
}
//中心值
center_que = center_hn * center_wn;
print(center_que, M);
for (int i = M + 1; i < N; i++)
{
temp = que.back();
que.pop_back();
print(temp, i);
que.push_front(temp);
}
}
//如果是矩形窗,那就不用计算了,直接输出hn即可。
else
{
for (int i = 0; i < M; i++)
{
temp = que_hn.front();
que_hn.pop_front();
que_hn.push_back(temp);
print(temp, i);
}
//中心值
print(center_hn, M);
for (int i = M + 1; i < N; i++)
{
temp = que_hn.back();
que_hn.pop_back();
que_hn.push_front(temp);
print(temp, i);
}
}
cout << endl << "h(n)的长度为:" << 2 * que.size() + 1;
cout << endl << "其中n的范围为[0," << N - 1 << "]" << endl;
}
void input()
{
string get_input;
cout << endl << "欢迎登录FIR_DF设计系统!" << endl;
cout << endl << "我们需要获取您的一些数据要求~" << endl;
cout << "请输入您想设计的数字滤波器类型(包括lp、hp、bp、bs、unknown):";
cin >> get_input;
if (get_input == "lp")filter_type = IS_LP;
else if (get_input == "hp")filter_type = IS_HP;
else if (get_input == "bp")filter_type = IS_BP;
else if (get_input == "bs")filter_type = IS_BS;
else if (get_input == "unknown") filter_type == UN_KNOWN;
else { cout << "error:输入错误!"; exit(0); }
cout << endl << "下面是关于键入频率和衰减系数的指标的一些声明。\n\
声明:\n\
因为在模拟域中,低通滤波器的通带和阻带下截止频率均趋于负无穷,\n\
所以在数字域中,低通滤波器的通带和阻带下截止频率均趋于0,\n\
所以如果是低通滤波器,程序默认在通带和阻带下截频位置(p1、s1)键入0;\n\
同理,\n\
因为在模拟域中,高通滤波器的通带和阻带上截止频率均趋于正无穷,\n\
所以在数字域中,高通滤波器的通带和阻带上截止频率均趋于0,\n\
所以如果是低通滤波器,程序默认在通带和阻带上截频位置(p2、s2)键入0;" << endl;
cout << endl << "请输入取样频率(Hz):"; cin >> fs;
cout << endl << "请输入通带起始频率p1(Hz):";
if (filter_type == IS_LP) { p1 = 0; cout << p1; }
else cin >> p1;
cout << endl << "请输入通带截止频率p2(Hz):";
if (filter_type == IS_HP) { p2 = 0; cout << p2; }
else cin >> p2;
cout << endl << "请输入阻带起始频率s1(Hz):";
if (filter_type == IS_LP) { s1 = 0; cout << s1; }
else cin >> s1;
cout << endl << "请输入阻带截止频率s2(Hz):";
if (filter_type == IS_HP) { s2 = 0; cout << s2; }
else cin >> s2;
cout << endl << "请输入阻带衰减常数(dB):"; cin >> As;
cout << endl;
cout << "运算结果为:" << endl;
}
void data_output()
{
cout << "data_output_for_detect…" << endl;
cout << "c1 = " << c1 << endl;
cout << "c2 = " << c2 << endl;
cout << "N = " << N << endl;
cout << "M = " << M << endl;
cout << "所选窗函数类型为:";
switch (window_type.type)
{
case RECTANG:cout << "RECTANG" << endl; break;
case HANNING:cout << "HANNING" << endl; break;
case HAMMING:cout << "HAMMING" << endl; break;
case BLACKMN:cout << "BLACKMN" << endl; break;
default:throw"error:data_output!"; break;
}
hn_output();
hn_calculate();
wn_output();
wn_calculate();
que_calculate();
}
void complication()
{
system("color 0A");
//input();
filter_type = IS_LP, fs = 10000, p1 = 0, p2 = 2000, s1 = 0, s2 = 3000, As = 40;
//filter_type = IS_BP, fs = 22000, p1 = 3500, s1 = 3000, p2 = 4500, s2 = 5000, As = 50;
change();
data_output();
}
int main()
{
try
{
complication();
}
catch (const char* cc)
{
cout << cc << endl;
exit(0);
}
return 0;
}
4.2代码效果图
4.3运行结果
五、日志
暂无。