数组倒序

将一组数组倒序排序,如{1,2,3,4,5}=>{5,4,3,2,1}

错误写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

using namespace std;

int main() {
// 数组倒序
int arr_02[] = { 1,2,3,4,5 };
length = sizeof(arr_02) / sizeof(arr_02[0]);
for (int i = 0; i < length; i++)
{
int reverse_index = length - 1 - i;
if (arr_02[i] == arr_02[reverse_index]) {
continue;
}
else {
int tmp = arr_02[i];
arr_02[i] = arr_02[reverse_index];
arr_02[reverse_index] = tmp;
}
}

for (int i = 0; i < length; i++)
{
cout << arr_02[i];
}



return 0;
}

解释:当判断到数组中间时,也就是arr_02[i] == arr_02[reverse_index]会跳过这次循环而非打断循环,正确的应该是停止循环或者length/2

正确写法1(推荐):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

int main() {
// 数组倒序
int arr_02[] = { 1,2,3,4,5 };
length = sizeof(arr_02) / sizeof(arr_02[0]);
for (int i = 0; i < length / 2; i++) // 长度÷2,表示将前半部分和后半部分互换位置
{
int reverse_index = length - 1 - i;
int tmp = arr_02[i];
arr_02[i] = arr_02[reverse_index];
arr_02[reverse_index] = tmp;
}

for (int i = 0; i < length; i++)
{
cout << arr_02[i];
}



return 0;
}

正确写法2(只适合索引长度为奇数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

using namespace std;

int main() {
// 数组倒序
int arr_02[] = { 1,2,3,4,5 };
length = sizeof(arr_02) / sizeof(arr_02[0]);
for (int i = 0; i < length; i++)
{
int reverse_index = length - 1 - i;
if (arr_02[i] == arr_02[reverse_index]) {
break; // 当执行到中间部分停止循环,数组长度为偶数就不能这么写,因为无法获得到中间索引,所以break永远不会被执行到
}
else {
int tmp = arr_02[i];
arr_02[i] = arr_02[reverse_index];
arr_02[reverse_index] = tmp;
}
}

for (int i = 0; i < length; i++)
{
cout << arr_02[i];
}



return 0;
}

冒泡排序

错误写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>

using namespace std;

void BubbleSort(int arr[],int length) {

for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
if (arr[i] < arr[j]) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}

int main() {
int arr[] = { 5,4,3,2,1 };

BubbleSort(arr,5);

for(int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}


return 0;
}

错误原因:虽然可以正确的对数组进行排序,但并不是冒泡排序

正确展示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>

using namespace std;

void BubbleSort(int arr[],int length) {

for (int i = 0; i < length - 1; i++)
{
for (int j = 0; j < length - 1 - i; j++)
{
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}

int main() {
int arr[] = { 5,4,3,2,1 };

BubbleSort(arr,5);

for(int i = 0; i < 5; i++)
{
cout << arr[i] << " ";
}


return 0;
}

饮品制作(多态案例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <string>

using namespace std;

/*
制作饮品案例:
1. 制作咖啡
2. 制作茶

抽象类:
1. 制作饮品抽象类

制作咖啡步骤:
1. 煮水
2. 冲泡咖啡
3. 倒入杯中
4. 加糖和牛奶

制作茶步骤:
1. 煮水
2. 冲泡茶
3. 倒入杯中
4. 加柠檬
*/

class MakeDrinks {
public:
void BoilWater() {
cout << "煮水" << endl;
}

void PourIntoCup() {
cout << "倒入杯中" << endl;
}

virtual void PrepareCoffe() {};
virtual void BrewTea() {};
virtual void AddSugarAndMilk() {};
virtual void AddLemon() {};
};

class MakeCoffee : public MakeDrinks {
public:
void PrepareCoffe() {
cout << "冲泡咖啡" << endl;
}

void AddSugarAndMilk() {
cout << "加糖和牛奶" << endl;
}
};

class MakeTea : public MakeDrinks {
public:
void BrewTea() {
cout << "冲泡茶" << endl;
}

void AddLemon() {
cout << "加柠檬" << endl;
}
};

int main() {
MakeDrinks* makeCoffee = new MakeCoffee();
makeCoffee->BoilWater();
makeCoffee->PrepareCoffe();
makeCoffee->PourIntoCup();
makeCoffee->AddSugarAndMilk();
cout << "*****************************************"<< endl;
MakeDrinks* makeTea = new MakeTea();
makeTea->BoilWater();
makeTea->BrewTea();
makeTea->PourIntoCup();
makeTea->AddLemon();


return 0;
}

出错原因:虽然代码没问题,但是有更好的优化空间

优化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <string>

using namespace std;

/*
制作饮品案例:
1. 制作咖啡
2. 制作茶

抽象类:
1. 制作饮品抽象类

制作咖啡步骤:
1. 煮水
2. 冲泡咖啡
3. 倒入杯中
4. 加糖和牛奶

制作茶步骤:
1. 煮水
2. 冲泡茶
3. 倒入杯中
4. 加柠檬
*/

class MakeDrinks {
public:
// 煮水
virtual void BoilWater() = 0;

// 冲泡
virtual void Brew() = 0;

// 倒入杯中
virtual void PourIntoCup() = 0;

// 加调料
virtual void AddCondiments() = 0;

void MakeDrink() {
BoilWater();
Brew();
PourIntoCup();
AddCondiments();
}
};

class MakeCoffee : public MakeDrinks {
public:
void BoilWater() override {
cout << "煮水" << endl;
}

void Brew() override {
cout << "冲泡咖啡" << endl;
}

void AddCondiments() override {
cout << "加糖和牛奶" << endl;
}

void PourIntoCup() override {
cout << "倒入杯中" << endl;
}
};

class MakeTea : public MakeDrinks {
public:
void BoilWater() override {
cout << "煮水" << endl;
}

void Brew() override {
cout << "冲泡茶叶" << endl;
}

void AddCondiments() override {
cout << "加柠檬" << endl;
}

void PourIntoCup() override {
cout << "倒入杯中" << endl;
}
};

int main() {
MakeDrinks *makeDrinks = new MakeCoffee();
makeDrinks->MakeDrink();
cout << "---------------------" << endl;
makeDrinks = new MakeTea();
makeDrinks->MakeDrink();


return 0;
}

计算机组装(多态案例)

错误示范:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <string>

using namespace std;
// 零件基类(抽象类)
class CPU {
public:
virtual void calculate() = 0;
};

class GraphicsCard {
public:
virtual void display() = 0;
};

class Memory {
public:
virtual void storeData() = 0;

};

// 电脑类
class Computer {
public:
CPU* cpu;
GraphicsCard* graphicsCard;
Memory* memory;

Computer(CPU* cpu, GraphicsCard* graphicsCard, Memory* memory) {
this->cpu = cpu;
this->graphicsCard = graphicsCard;
this->memory = memory;
}

void run() {
cpu->calculate();
graphicsCard->display();
memory->storeData();
}

// 防止内存泄露
~Computer() {
if (cpu != nullptr) {
delete cpu;
cpu = nullptr;
}

if (graphicsCard != nullptr) {
delete graphicsCard;
graphicsCard = nullptr;
}

if (memory != nullptr) {
delete memory;
memory = nullptr;
}
}
};

// 具体实现类
class IntelCPU : public CPU {
public:
void calculate() override {
std::cout << "Intel CPU 计算中..." << std::endl;
}
};

class AmdCPU : public CPU {
public:
void calculate() override {
std::cout << "Amd CPU 计算中..." << std::endl;
}
};

class NvidiaGraphicsCard : public GraphicsCard {
public:
void display() override {
std::cout << "Nvidia 显卡 显示中..." << std::endl;
}
};

class AmdGraphicsCard : public GraphicsCard {
public:
void display() override {
std::cout << "Amd 显卡 显示中..." << std::endl;
}
};

class SamsungMemory : public Memory {
public:
void storeData() override {
std::cout << "Samsung 内存 存储数据中..." << std::endl;
}
};

class KingstonMemory : public Memory {
public:
void storeData() override {
std::cout << "Kingston 内存 存储数据中..." << std::endl;
}
};


int main() {
Computer *computer_01 = new Computer(new IntelCPU(), new NvidiaGraphicsCard(), new SamsungMemory());
Computer *computer_02 = new Computer(new AmdCPU(), new AmdGraphicsCard(), new KingstonMemory());
Computer *computer_03 = new Computer(new AmdCPU(), new NvidiaGraphicsCard(), new KingstonMemory());

cout << "电脑_01开启:" << endl;
computer_01->run();
cout << endl;

cout << "电脑_02开启:" << endl;
computer_02->run();
cout << endl;

cout << "电脑_03开启:" << endl;
computer_03->run();
cout << endl;

delete computer_01;
delete computer_02;
delete computer_03;


return 0;
}

错误原因:

如果一个类包含虚函数,它几乎总是需要一个虚析构函数。 这是C++的一个重要原则,特别是当你计划通过基类指针管理派生类对象时。

原代码虽然可能在某些编译器上”看起来”正常工作,但实际上存在未定义行为,这可能导致难以调试的问题。

正确示范:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <iostream>
#include <string>

using namespace std;
// 零件基类(抽象类)
class CPU {
public:
virtual void calculate() = 0;
virtual ~CPU() = 0;
};

class GraphicsCard {
public:
virtual void display() = 0;
virtual ~GraphicsCard() = 0;
};

class Memory {
public:
virtual void storeData() = 0;
virtual ~Memory() = 0;
};

// 实现纯虚析构函数,防止报错
CPU::~CPU() {}
GraphicsCard::~GraphicsCard() {}
Memory::~Memory() {}

// 电脑类
class Computer {
public:
CPU* cpu;
GraphicsCard* graphicsCard;
Memory* memory;

Computer(CPU* cpu, GraphicsCard* graphicsCard, Memory* memory) {
this->cpu = cpu;
this->graphicsCard = graphicsCard;
this->memory = memory;
}

void run() {
cpu->calculate();
graphicsCard->display();
memory->storeData();
}

// 防止内存泄露
~Computer() {
if (cpu != nullptr) {
delete cpu;
cpu = nullptr;
}

if (graphicsCard != nullptr) {
delete graphicsCard;
graphicsCard = nullptr;
}

if (memory != nullptr) {
delete memory;
memory = nullptr;
}
}
};

// 具体实现类
class IntelCPU : public CPU {
public:
void calculate() override {
std::cout << "Intel CPU 计算中..." << std::endl;
}

~IntelCPU() override {
std::cout << "Intel CPU 析构函数" << std::endl;
}
};

class AmdCPU : public CPU {
public:
void calculate() override {
std::cout << "Amd CPU 计算中..." << std::endl;
}

~AmdCPU() override {
std::cout << "Amd CPU 析构函数" << std::endl;
}
};

class NvidiaGraphicsCard : public GraphicsCard {
public:
void display() override {
std::cout << "Nvidia 显卡 显示中..." << std::endl;
}

~NvidiaGraphicsCard() override {
std::cout << "Nvidia 显卡 析构函数" << std::endl;
}
};

class AmdGraphicsCard : public GraphicsCard {
public:
void display() override {
std::cout << "Amd 显卡 显示中..." << std::endl;
}

~AmdGraphicsCard() override {
std::cout << "Amd 显卡 析构函数" << std::endl;
}
};

class SamsungMemory : public Memory {
public:
void storeData() override {
std::cout << "Samsung 内存 存储数据中..." << std::endl;
}

~SamsungMemory() override {
std::cout << "Samsung 内存 析构函数" << std::endl;
}
};

class KingstonMemory : public Memory {
public:
void storeData() override {
std::cout << "Kingston 内存 存储数据中..." << std::endl;
}

~KingstonMemory() override {
std::cout << "Kingston 内存 析构函数" << std::endl;
}
};


int main() {
Computer *computer_01 = new Computer(new IntelCPU(), new NvidiaGraphicsCard(), new SamsungMemory());
Computer *computer_02 = new Computer(new AmdCPU(), new AmdGraphicsCard(), new KingstonMemory());
Computer *computer_03 = new Computer(new AmdCPU(), new NvidiaGraphicsCard(), new KingstonMemory());

cout << "电脑_01开启:" << endl;
computer_01->run();
cout << endl;

cout << "电脑_02开启:" << endl;
computer_02->run();
cout << endl;

cout << "电脑_03开启:" << endl;
computer_03->run();
cout << endl;

delete computer_01;
delete computer_02;
delete computer_03;


return 0;
}

迭代器删除错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void test01() {
set<int> st1;

st1.insert(1);
st1.insert(2);
st1.insert(3);

st1.clear();
cout << "size:" << st1.size() << endl;

for (int i = 0; i < 20; i++)
{
int random = rand() % 20;
st1.insert(random);
}

PrintSet(st1); // 0 1 2 4 5 7 9 11 14 15 16 18
set<int>::iterator beg = st1.begin();
advance(beg, 4);
set<int>::iterator era01 = st1.erase(beg);
cout << "删除后下个元素是: " << *era01 << endl;
PrintSet(st1); // 0 1 2 4 7 9 11 14 15 16 18

set<int>::iterator end = st1.end();
advance(end, -1);
set<int>::iterator era02 = st1.erase(beg, end);
cout << "删除后下个元素是: " << *era01 << endl;
PrintSet(st1);
}

以上代码中,反复使用了beg这个迭代器,实际上,当第一次erase(beg);时,就已经擦除了这个迭代器指向的数据(类似于指针变成了野指针)

其次,由于set容器是双向迭代器,所以不支持advance(end, -1)这种写法

修改方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void test01() {
set<int> st1;

st1.insert(1);
st1.insert(2);
st1.insert(3);

st1.clear();
cout << "size:" << st1.size() << endl;

for (int i = 0; i < 20; i++)
{
int random = rand() % 20;
st1.insert(random);
}

PrintSet(st1); // 0 1 2 4 5 7 9 11 14 15 16 18
set<int>::iterator beg = st1.begin();
advance(beg, 4);
set<int>::iterator era01 = st1.erase(beg);
cout << "删除后下个元素是: " << *era01 << endl;
PrintSet(st1); // 0 1 2 4 7 9 11 14 15 16 18

// 第二次删除:删除从第4个元素到倒数第3个元素的范围
beg = st1.begin();
advance(beg, 3); // 指向4
set<int>::iterator end = st1.end();
set<int>::iterator del_end = prev(end, 3); // 安全获取倒数第三个元素的位置

set<int>::iterator era02 = st1.erase(beg, del_end);
cout << "删除后下个元素是: " << *era02 << endl;
PrintSet(st1);
}

当删除beg指向的数据后,就应该将beg重置

对于双向迭代器,通过prev(end, 3)可以更安全的获取到尾部的迭代器