让我们想看看二元四则运算都需要实现什么:
(1) 定制题目数量
(2) 是否有乘除法
(3) 题目数值范围
(4) 加减有无负数
(5) 除法有无余数
(6) 是否支持分数(真分数、假分数…)
(7) 是否支持小数(精确到多少位?)
(8) 打印中每行的间隔
为了实现以上功能,并且为了便于后期实现功能拓展,我们可以将其封装成类,通过在外界设置类的参数,实现不同的功能。可以将类定义如下:
1 class CTitle
2 {
3 public:
4 CTitle();
5 ~CTitle();
6 void setTitleCount(int titleCount); // 设置题量
7 void setMD(int hasMD); // 设置乘除法
8 void setBracket(int hasBracket); // 设置括号
9 void setNumRand(int numRand); // 设置数值范围
10 void setMinus(int hasMinus); // 设置负号
11 void setResidue(int hasResidue); // 设置余数
12 void setFraction(int hasFraction); // 设置分数
13 void setFractionType(int fractionType); // 设置是否支持假分数
14 void setDecimal(int hasDecimal); // 设置小数
15 void setDecimalLong(int decimalLong); // 设置小数位数
16 void newTitle(); // 新建题目
17 private:
18 int titleCount; // 题目数量
19 int hasMD; // 是否有乘除法
20 int hasBracket; // 是否有括号
21 int numRand; // 数值范围
22 int hasMinus; // 加减有无负数
23 int hasResidue; // 除法有无余数
24 int hasFraction; // 是否支持分数
25 int fractionType; // 是否支持假分数
26 int hasDecimal; // 是否支持小数
27 int decimalLong; // 小数位数
28 int decimalLongPow; // 小数位数
29
30 void newIntegerFormula(); // 新建整数运算公式
31 void newDecimalFormula(); // 新建小数运算公式
32 void newFractionFormula(); // 新建分数运算公式
33 void recordTitle(string szTitle); // 记录题目至文件
34 void recordAnswer(string szAnswer); // 记录答案至文件
35 void reduceFraction(int &nume, int &deno);// 化简分数
36 };
接下来,我们需要实现类的功能接口,并且对类的属性实现初始化
1 CTitle::CTitle()
2 {
3 titleCount = 0; // 题量
4 hasMD = 0; // 是否有乘除法
5 numRand = 0; // 数值范围
6 hasMinus = 0; // 加减有无负数
7 hasResidue = 0; // 除法有无余数
8 hasFraction = 0; // 是否支持分数
9 fractionType = 0; // 是否支持假分数
10 hasDecimal = 0; // 是否支持小数
11 decimalLong = 0; // 小数位数
12 decimalLongPow = 0; // 小数位数
13 }
14 CTitle::~CTitle()
15 {
16 }
17 // 设置行间距
18 void CTitle::setTitleCount(int titleCount)
19 {
20 this->titleCount = titleCount;
21 }
22 // 设置乘除法
23 void CTitle::setMD(int hasMD)
24 {
25 this->hasMD = hasMD;
26 }
27 // 设置数值范围
28 void CTitle::setNumRand(int numRand)
29 {
30 this->numRand = numRand;
31 }
32 // 设置负号
33 void CTitle::setMinus(int hasMinus)
34 {
35 this->hasMinus = hasMinus;
36 }
37 // 设置余数
38 void CTitle::setResidue(int hasResidue)
39 {
40 this->hasResidue = hasResidue;
41 }
42 // 设置分数
43 void CTitle::setFraction(int hasFraction)
44 {
45 this->hasFraction = hasFraction;
46 }
47 // 设置是否支持假分数
48 void CTitle::setFractionType(int fractionType)
49 {
50 this->fractionType = fractionType;
51 }
52 // 设置小数
53 void CTitle::setDecimal(int hasDecimal)
54 {
55 this->hasDecimal = hasDecimal;
56 }
57 // 设置小数位数
58 void CTitle::setDecimalLong(int decimalLong)
59 {
60 this->decimalLong = decimalLong;
61 this->decimalLongPow = pow(10, decimalLong);
62 }
接着,我们为类添加方法,让类可以按需求生成不同类型的运算题目。那么,如何才能使类可以随机生成不同类型的运算呢?通过对题目进行分析,我们发现所有可能出现的运算类型共有4中,他们分别是:
(1)整数运算
(2)整数运算 & 小数运算
(3)整数运算 & 分数运算
(4)整数运算 & 分数运算 & 小数运算
1 void CTitle::newTitle()
2 {
3 srand(time(0));
4 int numType = 1 + hasDecimal + hasFraction;
5 int titleType = 1;
6 for (int i = 0; i < titleCount; i++)
7 {
8 switch(numType)
9 {
10 // 运算中仅有整数运算
11 case 1:
12 newIntegerFormula();
13 break;
14 // 运算中包含包含两种运算,整数+小数 或 整数+分数
15 case 2:
16 titleType = rand() % 2 + 1;
17 if (titleType == 1)
18 {
19 newIntegerFormula();
20 }
21 else
22 {
23 if (hasDecimal == 1)
24 {
25 newDecimalFormula();
26 }
27 else if (hasFraction == 1)
28 {
29 newFractionFormula();
30 }
31 }
32 break;
33 // 运算中包含小数运算和分数运算
34 case 3:
35 titleType = rand() % 3 + 1;
36 if (titleType == 1)
37 {
38 newIntegerFormula();
39 }
40 else if (titleType == 2)
41 {
42 newDecimalFormula();
43 }
44 else
45 {
46 newFractionFormula();
47 }
48 break;
49 }
50 }
51 }
接下来我们需要解决的问题就是如何生成整数运算、小数运算以及分数运算并计算其结果。在本例中,我们用文件分别对运算表达式和运算结果进行存储。将表达式存储于Title.txt文件内,将运算结果存储于Answer.txt文件内。
所以,我们先要在Ctitle的构造函数内加入如下代码,以保证每次类初始化时文件内容会被清空。
1 FILE *fp = NULL;
2 errno_t err;
3 if ((err = fopen_s(&fp, "Title.txt", "w")) == 0)
4 {
5 fclose(fp);
6 }
7 if ((err = fopen_s(&fp, "Answer.txt", "w")) == 0)
8 {
9 fclose(fp);
10 }
并且增加写入表达式和写入答案的方法
1 // 记录题目至文件
2 void CTitle::recordTitle(string szTitle)
3 {
4 FILE *fp = NULL;
5 errno_t err;
6 if ((err = fopen_s(&fp, "Title.txt", "a")) == 0)
7 {
8 fprintf_s(fp, "%sn", szTitle.c_str());
9 fclose(fp);
10 }
11 }
12 // 记录答案至文件
13 void CTitle::recordAnswer(string szAnswer)
14 {
15 FILE *fp = NULL;
16 errno_t err;
17 if ((err = fopen_s(&fp, "Answer.txt", "a")) == 0)
18 {
19 fprintf_s(fp, "%sn", szAnswer.c_str());
20 fclose(fp);
21 }
22 }
接下来我们实现创建整数运算的方法,在这里与要注意以下问题:
(1)除法运算时,除数不能为0
(2)若运算不能还有余数,要保证生成的除法运算均可以整除
(3)若运算可以还有余数,要保证生成的结果为: 5 ÷ 2 = 2...1 ,而非2.5
1 // 新建整数运算公式
2 void CTitle::newIntegerFormula()
3 {
4 string szTitle = "";
5 string szAnswer = "";
6 char caTitle[100] = { "" };
7 char caAnswer[100] = { "" };
8 int num1 = rand() % numRand + 1;// 随机整数1,默认是正数
9 int num2 = rand() % numRand + 1;// 随机整数2,默认是正数
10 int op = rand() % 2 + 1; // 运算符,默认仅有加减运算
11 // 设置四则运算
12 if (hasMD == 1)
13 {
14 op = rand() % 4 + 1;
15 }
16 switch (op)
17 {
18 case 1:
19 // 加减运算中包含负数
20 if (hasMinus == 1)
21 {
22 num1 = rand() % (numRand * 2) - numRand;
23 num2 = rand() % (numRand * 2) - numRand;
24 }
25 if (num2 < 0)
26 {
27 // 记录题目
28 sprintf_s(caTitle, "%d+(%d)", num1, num2);
29 szTitle += caTitle;
30 recordTitle(szTitle);
31 // 记录答案
32 sprintf_s(caAnswer, "%d", num1+num2);
33 szAnswer += caAnswer;
34 recordAnswer(szAnswer);
35 }
36 else
37 {
38 // 记录题目
39 sprintf_s(caTitle, "%d+%d", num1, num2);
40 szTitle += caTitle;
41 recordTitle(szTitle);
42 // 记录答案
43 sprintf_s(caAnswer, "%d", num1 + num2);
44 szAnswer += caAnswer;
45 recordAnswer(szAnswer);
46 }
47 break;
48 case 2:
49 // 加减运算中包含负数
50 if (hasMinus == 1)
51 {
52 num1 = rand() % (numRand * 2) - numRand;
53 num2 = rand() % (numRand * 2) - numRand;
54 }
55 if (num2 < 0)
56 {
57 // 记录题目
58 sprintf_s(caTitle, "%d-(%d)", num1, num2);
59 szTitle += caTitle;
60 recordTitle(szTitle);
61 // 记录答案
62 sprintf_s(caAnswer, "%d", num1 - num2);
63 szAnswer += caAnswer;
64 recordAnswer(szAnswer);
65 }
66 else
67 {
68 // 记录题目
69 sprintf_s(caTitle, "%d-%d", num1, num2);
70 szTitle += caTitle;
71 recordTitle(szTitle);
72 // 记录答案
73 sprintf_s(caAnswer, "%d", num1 - num2);
74 szAnswer += caAnswer;
75 recordAnswer(szAnswer);
76 }
77 break;
78 case 3:
79 // 记录题目
80 sprintf_s(caTitle, "%d×%d", num1, num2);
81 szTitle += caTitle;
82 recordTitle(szTitle);
83 // 记录答案
84 sprintf_s(caAnswer, "%d", num1 * num2);
85 szAnswer += caAnswer;
86 recordAnswer(szAnswer);
87 break;
88 case 4:
89 // 除数为0
90 while (num2 == 0)
91 {
92 num2 = rand() % numRand + 1;
93 }
94 // 无余数的除法
95 if(hasResidue == 0)
96 {
97 // 保证可以整除
98 while (num1 % num2 != 0)
99 {
100 num1 = rand() % numRand + 1;
101 }
102 // 记录题目
103 sprintf_s(caTitle, "%d÷%d", num1, num2);
104 szTitle += caTitle;
105 recordTitle(szTitle);
106 // 记录答案
107 sprintf_s(caAnswer, "%d", num1 / num2);
108 szAnswer += caAnswer;
109 recordAnswer(szAnswer);
110 }
111 // 有余数的除法
112 else
113 {
114 // 记录题目
115 sprintf_s(caTitle, "%d÷%d", num1, num2);
116 szTitle += caTitle;
117 recordTitle(szTitle);
118 // 记录答案
119 sprintf_s(caAnswer, "%d...%d", num1 / num2, num1 % num2);
120 szAnswer += caAnswer;
121 recordAnswer(szAnswer);
122 }
123 break;
124 }126 }
接下来实现小数运算,在这里,小数的位数是可以自主选定的,所以如果小数位数选择的是2位,那么在记录如文件时也要保证多余位数不会被记录。如double类型默认写入文件是2.510000,那我们只能保留2.51,并将保留后的结果写入文件。
1 // 新建小数运算公式
2 void CTitle::newDecimalFormula()
3 {
4 string szTitle = "";
5 string szAnswer = "";
6 string szOp = "";
7 string szNum1 = "";
8 string szNum2 = "";
9 char caTitle[100] = { "" };
10 char caAnswer[100] = { "" };
11 char caNum1[100] = { "" };
12 char caNum2[100] = { "" };
13 double dAnswer = 0;
14 int num1 = rand() % numRand + 1;// 随机整数1,默认是正数
15 int num2 = rand() % numRand + 1;// 随机整数2,默认是正数
16 double dotNum1 = (rand() % (decimalLongPow) +1);// 随机小数1
17 double dotNum2 = (rand() % (decimalLongPow)+1);// 随机小数2
18 int op = rand() % 2 + 1; // 运算符,默认仅有加减运算
19 dotNum1 = dotNum1 / decimalLongPow;
20 dotNum2 = dotNum2 / decimalLongPow;
21 sprintf_s(caNum1, "%lf", num1 + dotNum1);
22 szNum1 += caNum1;
23 szNum1 = szNum1.substr(0, szNum1.length() - 6 + decimalLong);
24 sprintf_s(caNum2, "%lf", num2 + dotNum2);
25 szNum2 += caNum2;
26 szNum2 = szNum2.substr(0, szNum2.length() - 6 + decimalLong);
27 // 设置四则运算
28 if (hasMD == 1)
29 {
30 op = rand() % 4 + 1;
31 }
32 switch (op)
33 {
34 case 1:
35 // 加减运算中包含负数
36 if (hasMinus == 1)
37 {
38 num1 = rand() % (numRand * 2) - numRand;
39 num2 = rand() % (numRand * 2) - numRand;
40 szNum1 = "";
41 szNum2 = "";
42 sprintf_s(caNum1, "%lf", num1 + dotNum1);
43 szNum1 += caNum1;
44 szNum1 = szNum1.substr(0, szNum1.length() - 6 + decimalLong);
45 sprintf_s(caNum2, "%lf", num2 + dotNum2);
46 szNum2 += caNum2;
47 szNum2 = szNum2.substr(0, szNum2.length() - 6 + decimalLong);
48 }
49 if (num2 < 0)
50 {
51 // 记录题目
52 szOp = "+";
53 szNum2 = "(" + szNum2 + ")";
54 // 记录答案
55 dAnswer = num1 + dotNum1 + num2 + dotNum2;
56 }
57 else
58 {
59 // 记录题目
60 szOp = "+";
61 // 记录答案
62 dAnswer = num1 + dotNum1 + num2 + dotNum2;
63 }
64 break;
65 case 2:
66 // 加减运算中包含负数
67 if (hasMinus == 1)
68 {
69 num1 = rand() % (numRand * 2) - numRand;
70 num2 = rand() % (numRand * 2) - numRand;
71 szNum1 = "";
72 szNum2 = "";
73 sprintf_s(caNum1, "%lf", num1 + dotNum1);
74 szNum1 += caNum1;
75 szNum1 = szNum1.substr(0, szNum1.length() - 6 + decimalLong);
76 sprintf_s(caNum2, "%lf", num2 + dotNum2);
77 szNum2 += caNum2;
78 szNum2 = szNum2.substr(0, szNum2.length() - 6 + decimalLong);
79 }
80 if (num2 < 0)
81 {
82 // 记录题目
83 szOp = "-";
84 szNum2 = "(" + szNum2 + ")";
85 // 记录答案
86 dAnswer = num1 + dotNum1 - num2 - dotNum2;
87 }
88 else
89 {
90 // 记录题目
91 szOp = "-";
92 // 记录答案
93 dAnswer = num1 + dotNum1 - num2 - dotNum2;
94 }
95 break;
96 case 3:
97 // 记录题目
98 szOp = "×";
99 // 记录答案
100 dAnswer = (num1 + dotNum1) * (num2 + dotNum2);
101 break;
102 case 4:
103 // 除数为0
104 while (num2 == 0 && dotNum2 == 0)
105 {
106 num2 = rand() % numRand + 1;
107 dotNum2 = (rand() % (decimalLong)+1);
108 }
109 // 记录题目
110 szOp = "÷";
111 // 记录答案
112 dAnswer = (num1 + dotNum1) / (num2 + dotNum2);
113 break;
114 }
115 // 记录题目
116 szTitle = szNum1 + szOp + szNum2;
117 recordTitle(szTitle);
118 // 记录答案
119 sprintf_s(caAnswer, "%lf", dAnswer);
120 szAnswer += caAnswer;
121 szAnswer = szAnswer.substr(0, szAnswer.length() - 6 + decimalLong);
122 recordAnswer(szAnswer);124 }
最后需要进行的就是生成分数,在这里,我们需要注意:
(1)是否进行假分数的运算
(2)要对分数的运算结果进行约分,将分数化为最简。并且将假分数化简。如5/2要化简为2‘1/2(二又二分之一)
1 // 新建分数运算
2 void CTitle::newFractionFormula()
3 {
4 string szTitle = "";
5 string szAnswer = "";
6 char caTitle[100] = { "" };
7 char caAnswer[100] = { "" };
8 int deno1 = rand() % numRand + 1;// 随机分母1,默认是正数
9 int deno2 = rand() % numRand + 1;// 随机分母2,默认是正数
10 int nume1 = rand() % numRand + 1;// 随机分子1,默认是正数
11 int nume2 = rand() % numRand + 1;// 随机分子2,默认是正数
12 int nweNume = 0;
13 int nweDeno = 0;
14 // 支持假分数
15 if (fractionType == 1)
16 {
17 // 分母为0或1
18 while (deno1 == 0 || deno1 == 1)
19 {
20 deno1 = rand() % numRand + 1;
21 }
22 while (deno2 == 0 || deno1 == 1)
23 {
24 deno2 = rand() % numRand + 1;
25 }
26 }
27 // 不支持假分数
28 if (fractionType == 0)
29 {
30 // 分母为0或1
31 while (nume1 == 0 || nume1 == 1)
32 {
33 nume1 = rand() % numRand + 1;
34 }
35 while (nume2 == 0 || nume2 == 1)
36 {
37 nume2 = rand() % numRand + 1;
38 }
39 if (deno1 < nume1)
40 {
41 int temp = deno1;
42 deno1 = nume1;
43 nume1 = temp;
44 }
45 if (deno2 < nume2)
46 {
47 int temp = deno2;
48 deno2 = nume2;
49 nume2 = temp;
50 }
51 }
52 int op = rand() % 2 + 1; // 运算符,默认仅有加减运算
53 // 设置四则运算
54 if (hasMD == 1)
55 {
56 op = rand() % 4 + 1;
57 }
58 switch (op)
59 {
60 case 1:
61 // 记录题目
62 sprintf_s(caTitle, "%d/%d+%d/%d", nume1, deno1, nume2, deno2);
63 szTitle += caTitle;
64 recordTitle(szTitle);
65 // 记录答案
66 nweNume = nume1*deno2 + deno1*nume2;
67 nweDeno = deno1*deno2;
68 break;
69 case 2:
70 // 记录题目
71 sprintf_s(caTitle, "%d/%d-%d/%d", nume1, deno1, nume2, deno2);
72 szTitle += caTitle;
73 recordTitle(szTitle);
74 // 记录答案
75 nweNume = nume1*deno2 - deno1*nume2;
76 nweDeno = deno1*deno2;
77 reduceFraction(nweNume, nweDeno);
78 break;
79 case 3:
80 // 记录题目
81 sprintf_s(caTitle, "%d/%d×%d/%d", nume1, deno1, nume2, deno2);
82 szTitle += caTitle;
83 recordTitle(szTitle);
84 // 记录答案
85 nweNume = nume1*nume2;
86 nweDeno = deno1*deno2;
87 break;
88 case 4:
89 // 记录题目
90 sprintf_s(caTitle, "%d/%d÷%d/%d", nume1, deno1, nume2, deno2);
91 szTitle += caTitle;
92 recordTitle(szTitle);
93 // 记录答案
94 nweNume = nume1*deno2;
95 nweDeno = deno1*nume2;
96 break;
97 }
98 reduceFraction(nweNume, nweDeno); // 化简
99 if (nweNume == 0)
100 {
101 recordAnswer("0");
102 }
103 else if (nweDeno == 1)
104 {
105 sprintf_s(caAnswer, "%d", nweNume);
106 szAnswer += caAnswer;
107 recordAnswer(szAnswer);
108 }
109 else if (nweNume < nweDeno)
110 {
111 sprintf_s(caAnswer, "%d/%d", nweNume, nweDeno);
112 szAnswer += caAnswer;
113 recordAnswer(szAnswer);
114 }
115 else if (nweNume > nweDeno)
116 {
117 if (nweNume%nweDeno != 0)
118 {
119 sprintf_s(caAnswer, "%d'%d/%d", nweNume / nweDeno, nweNume%nweDeno, nweDeno);
120 szAnswer += caAnswer;
121 recordAnswer(szAnswer);
122 }
123 else
124 {
125 sprintf_s(caAnswer, "%d", nweNume / nweDeno);
126 szAnswer += caAnswer;
127 recordAnswer(szAnswer);
128 }
129 }
130 else
131 {
132 recordAnswer("1");
133 }
134 }
135 // 化简分数
136 void CTitle::reduceFraction(int &nume, int &deno)
137 {
138 int temp;
139 int a = nume;
140 int b = deno;
141 int gcd = 0; // 最大公约式
142 if (a < b)
143 {
144 temp = a;
145 a = b;
146 b = temp;
147 }
148 while (b != 0)
149 {
150 temp = a % b;
151 a = b;
152 b = temp;
153 }
154 gcd = a;
155 nume = nume / gcd;
156 deno = deno / gcd;
157 }
至此,我们的类就编写完成了。接下来只需要在主函数生成类,并进行类方法的调用就行了。
1 #include "iostream"
2 #include "time.h"
3 #include "CTitle.h"
4 #include "CTitle.h"
5 using namespace std;
6 void setting();
7 CTitle title;
8 int lineSpacing = 0;
9 int main()
10 {
11 setting();
12 title.newTitle();
13 // 从文件打印题目
14 FILE *fp = NULL;
15 FILE *fp2 = NULL;
16 errno_t err;
17 char caTitle[100];
18 char caAnsewr[100];
19 char myansewr[100];
20 int mark = 1;
21 if ((err = fopen_s(&fp, "Title.txt", "r")) == 0 && (err = fopen_s(&fp2, "Answer.txt", "r")) == 0)
22 {
23 // 读取题目
24 while ((fscanf_s(fp, "%s", caTitle, 100) != EOF))
25 {
26 // 读取答案
27 fscanf_s(fp2, "%s", caAnsewr, 100);
28 do
29 {
30 cout << caTitle << " = ";
31 cin >> myansewr;
32 if (strcmp(myansewr, caAnsewr) == 0)
33 {
34 cout << "√" << endl;
35 mark = 1;
36 }
37 else
38 {
39 cout << "×" << endl;
40 mark = 0;
41 }
42 for (int i = 0; i < lineSpacing; i++)
43 {
44 cout << endl;
45 }
46 } while (mark == 0);
47 }
48 cout << "恭喜你完成今日作业" << endl;
49 }
50 return 0;
51 }
52 void setting()
53 {
54 int input = 0;
55 cout << "请完成如下设置" << endl;
56 cout << "设置今日题量:";
57 cin >> input;
58 title.setTitleCount(input);
59 cout << endl;
60 cout << "设置数值范围绝对值:";
61 cin >> input;
62 title.setNumRand(input);
63 cout << endl;
64 do
65 {
66 cout << "加减有无负数,1有0无:";
67 cin >> input;
68 }
69 while (input != 0 && input != 1);
70 title.setMinus(input);
71 cout << endl;
72 do
73 {
74 cout << "是否有乘除法,1有0无:";
75 cin >> input;
76 }
77 while (input != 0 && input != 1);
78 title.setMD(input);
79 cout << endl;
80 if (input == 1)
81 {
82 do
83 {
84 cout << "整数除法有无余数,1有0无:";
85 cin >> input;
86 }
87 while (input != 0 && input != 1);
88 title.setResidue(input);
89 cout << endl;
90 }
91
92 do
93 {
94 cout << "是否支持小数,1有0无:";
95 cin >> input;
96 }
97 while (input != 0 && input != 1);
98 title.setDecimal(input);
99 cout << endl;
100 if (input == 1)
101 {
102 cout << "设置小数位数(1~5):";
103 cin >> input;
104 title.setDecimalLong(input);
105 cout << endl;
106 }
107 do
108 {
109 cout << "是否支持分数,1有0无:";
110 cin >> input;
111 }
112 while (input != 0 && input != 1);
113 title.setFraction(input);
114 cout << endl;
115 if (input == 1)
116 {
117 cout << "设置是否支持假分数,1有0无:";
118 cin >> input;
119 title.setFractionType(input);
120 cout << endl;
121 }
122 cout << "设置打印行间隔:";
123 cin >> input;
124 lineSpacing = input;
125 cout << endl;
126 }
恩,对于这一次的作业,我只完成了二元式的生成和运算,没有涉及到多元式,所以没有写上括号生成与运算的问题。本来只是想简单写写,好久没有用C++写过程序了,没想到写着写着就写了这么多行,但好像也没有实现什么功能,只是保证了最基础的运行。还是要继续提升啊。
原文链接: https://www.cnblogs.com/libaoquan/p/5271351.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/230132
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!