1.题目描述

目前国际计重最基本的单位是克。在古代各个国家的计重单位是不同的。

中国使用斤、两、钱来表示重量,其中1斤=10两,1两=10钱

中国计重单位与克的关系为:1斤=500克,1两=50克,1钱=5克

英国使用磅、盎司、打兰来表示重量,其中1磅=16盎司,1盎司=16打兰

英国计重单位与克的关系为:1磅=512克,1盎司=32克,1打兰=2克

以下参考代码包含了抽象类Weight,中国计重和英国计重都继承了抽象类。

中国计重类新增了斤、两、钱三个属性,并新增了一个操作:计重转换Convert。

Convert能够把输入的克数转成中国计重,例如1234克转成2斤4两6钱4克,并且把数值放入斤、两、钱、克四个属性中

英国计重类新增了磅、盎司、打兰三个属性,并新增了两个操作:

1、计重转换Convert,功能与上述类似,例如2345克转成4磅9盎司4打兰1克,并且把数值放入对应的四个属性中

2、计重等价,重载类型转换运算符,实现将英国计重类的对象转换成中国计重类的对象,例如英国计重类对象en(2磅2盎司11打兰1克)等价于(转换成)中国计重类对象cn(2斤2两2钱1克)。

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
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
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;

class CN; //提前声明
class EN; //提前声明

// 抽象类
class Weight
{
protected:
char kind[20]; //计重类型
int gram; // 克
public:
Weight(const char tk[] = "no name", int tg = 0)
{
strcpy(kind, tk);
gram = tg;
}
virtual void print(ostream& out) = 0; // 输出不同类型的计重信息
};

// 中国计重
class CN : public Weight
{
private:
int jin;
int liang;
int qian;
public:
CN(int j, int l, int q, int g, const char* k) :jin(j), liang(l), qian(q), Weight(k, g) {}
void Convert(int g)
{
jin = g / 500;
g -= jin * 500;
liang = g / 50;
g -= liang * 50;
qian = g / 5;
g -= qian * 5;
gram = g;
}
void print(ostream& out)
{
out << *this;
}
friend ostream& operator<<(ostream& os, const CN& res);

};

// 英国计重
class EN : public Weight
{
protected:
int bang;
int si;
int lan;
public:
EN(int b, int s, int l, int g, const char* k) :bang(b), si(s), lan(l), Weight(k, g) {}
void Convert(int g)
{
bang = g / 512;
g -= bang * 512;
si = g / 32;
g -= si * 32;
lan = g / 2;
g -= lan * 2;
gram = g;
}
operator CN() const {
int totalGrams = gram;
totalGrams += lan * 2;
totalGrams += si * 32;
totalGrams += bang * 512;

int jin = totalGrams / 500;
totalGrams %= 500;
int liang = totalGrams / 50;
totalGrams %= 50;
int qian = totalGrams / 5;
totalGrams %= 5;

return CN(jin, liang, qian, totalGrams, "中国计重");
}
void print(ostream& out)
{
out << *this;
}
friend ostream& operator<<(ostream& os, const EN& res);
};
ostream& operator<<(ostream& os, const CN& res)
{
os << "中国计重:" << res.jin << "斤" << res.liang << "两" << res.qian << "钱" << res.gram << "克" << endl;
return os;
}
ostream& operator<<(ostream& os, const EN& res)
{
os << "英国计重:" << res.bang << "磅" << res.si << "盎司" << res.lan << "打兰" << res.gram << "克" << endl;
return os;
}
// 以全局函数方式重载输出运算符,代码3-5行....自行编写
// 重载函数包含两个参数:ostream流对象、Weight类对象,参数可以是对象或对象引用
// 重载函数必须调用参数Weight对象的print方法

// 主函数
int main()
{
int tw;
// 创建一个中国计重类对象cn
// 构造参数对应斤、两、钱、克、类型,其中克和类型是对应基类属性gram和kind
CN cn(0, 0, 0, 0, "中国计重");
cin >> tw;
cn.Convert(tw); // 把输入的克数转成中国计重
cout << cn;

// 创建英国计重类对象en
// 构造参数对应磅、盎司、打兰、克、类型,其中克和类型是对应基类属性gram和kind
EN en(0, 0, 0, 0, "英国计重");
cin >> tw;
en.Convert(tw); // 把输入的克数转成英国计重
cout << en;

// 使用类型转换运算符 自动调用 EN 的类型转换运算符
cn = en; // 把英国计重转成中国计重
cout << cn;
return 0;
}

类型转换运算符的应用

1.题目概述

X字母可以放大和缩小,变为n行X(n=1,3,5,7,9,…,21)。

现假设一个n行(n>0,奇数)X图案,遥控器可以控制X图案的放大与缩小。遥控器有5个按键,1)show,显示当前X图案;2)show++, 显示当前X图案,再放大图案,n+2;3)++show,先放大图案,n+2,再显示图案;4)show–,显示当前X图案,再缩小图案,n-2;5)–show,先缩小图案,n-2,再显示图案。假设X图案的放大和缩小在1-21之间。n=1时,缩小不起作用,n=21时,放大不起作用。

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
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*例如,3行x图案如下:
xxx
x
xxx */

#include <iostream>
using namespace std;

class CXGraph
{
char** x;
int N;
public:
CXGraph(){}
CXGraph(int n)
{
N = n;
x = new char*[n];
for (int i = 0; i < n; ++i)
{
x[i] = new char[n];
}

int temp = n;
for (int i = 0; i < ((n+1)/2); i++)
{
for (int j = 0; j < i; j++)
{
x[i][j] = ' ';
x[n - i - 1][j] = ' ';
}
for (int j = i; j < temp; j++)
{
x[i][j] = 'X';
x[n - i - 1][j] = 'X';
}
temp --;
}
}

CXGraph(const CXGraph& tmp)
{
N = tmp.N;
x = new char* [N];
for (int i = 0; i < N; ++i)
{
x[i] = new char[N];
}


for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
x[i][j] = tmp.x[i][j];
}
}

}
~CXGraph()
{
for (int i = 0; i < N; i++)
{
delete []x[i];
}
delete[]x;
}

//这里规范来说,应该全部加const,但是当时编译时出了问题,发现把const去掉就好了
//结尾贴出改进方法--作为类成员函数重载
friend CXGraph operator++(CXGraph& a);//前缀运算++a
friend CXGraph operator++(CXGraph& a, int b);//后缀运算a++
friend CXGraph operator--(CXGraph& a);
friend CXGraph operator--(CXGraph& a, int b);
friend ostream& operator<<(ostream& os, const CXGraph& x);
CXGraph& operator=(const CXGraph& a);
};

CXGraph operator++(CXGraph& a)
{
if (a.N == 21) return a;
for (int i = 0; i < a.N; ++i)
delete[] a.x[i];
delete[] a.x;
a.N += 2;
a.x = new char* [a.N];
for (int i = 0; i < a.N; ++i)
a.x[i] = new char[a.N];
int temp = a.N;
for (int i = 0; i < ((a.N + 1) / 2); i++)
{
for (int j = 0; j < i; j++)
{
a.x[i][j] = ' ';
a.x[a.N - i - 1][j] = ' ';
}
for (int j = i; j < temp; j++)
{
a.x[i][j] = 'X';
a.x[a.N - i - 1][j] = 'X';
}
temp--;
}
return a;
}

CXGraph operator++(CXGraph& a, int b)
{
if (a.N == 21) return a;
CXGraph t(a);
for (int i = 0; i < a.N; ++i)
{
delete[] a.x[i];
}
delete[] a.x;

a.N += 2;
a.x = new char* [a.N];
for (int i = 0; i < a.N; ++i)
{
a.x[i] = new char[a.N];
}

int temp = a.N;
for (int i = 0; i < ((a.N + 1) / 2); i++)
{
for (int j = 0; j < i; j++)
{
a.x[i][j] = ' ';
a.x[a.N - i - 1][j] = ' ';
}
for (int j = i; j < temp; j++)
{
a.x[i][j] = 'X';
a.x[a.N - i - 1][j] = 'X';
}
temp--;
}
return t;
}

CXGraph operator--(CXGraph& a)
{
if (a.N == 1) return a;
for (int i = 0; i < a.N; ++i)
{
delete[] a.x[i];
}
delete[] a.x;

a.N -= 2;
a.x = new char* [a.N];
for (int i = 0; i < a.N; ++i)
a.x[i] = new char[a.N];
int temp = a.N;
for (int i = 0; i < ((a.N + 1) / 2); i++)
{
for (int j = 0; j < i; j++)
{
a.x[i][j] = ' ';
a.x[a.N - i - 1][j] = ' ';
}
for (int j = i; j < temp; j++)
{
a.x[i][j] = 'X';
a.x[a.N - i - 1][j] = 'X';
}
temp--;
}
return a;
}

CXGraph operator--(CXGraph& a, int b)
{
if (a.N == 1) return a;
CXGraph t(a.N);
for (int i = 0; i < a.N; ++i)
{
delete[] a.x[i];
}
delete[] a.x;

a.N -= 2;
int temp = a.N;
a.x = new char* [a.N];
for (int i = 0; i < a.N; ++i)
a.x[i] = new char[a.N];

for (int i = 0; i < ((a.N + 1) / 2); i++)
{
for (int j = 0; j < i; j++)
{
a.x[i][j] = ' ';
a.x[a.N - i - 1][j] = ' ';
}
for (int j = i; j < temp; j++)
{
a.x[i][j] = 'X';
a.x[a.N - i - 1][j] = 'X';
}
temp--;
}

return t;
}

ostream& operator<<(ostream& os, const CXGraph& x)
{
int t = x.N;
for (int i = 0; i < (x.N+1)/2; i++)
{
for (int j = 0; j < t; j++)
{
cout << x.x[i][j] ;
}
cout << endl;
t--;
}

t += 2;
for (int i = (x.N + 1) / 2; i < x.N; i++)
{
for (int j = 0; j < t; j++)
{
cout << x.x[i][j];
}
cout << endl;
t++;
}

return os;
}

CXGraph& CXGraph::operator=(const CXGraph& a)
{
for (int i = 0; i < N; ++i) {
delete[] x[i];
}
delete[] x;

N = a.N;
x = new char* [N];
for (int i = 0; i < N; ++i) {
x[i] = new char[N];
for (int j = 0; j < N; ++j) {
x[i][j] = a.x[i][j];
}
}

return *this;
}

int main()
{
int t, n;
string command;
cin >> n;
CXGraph xGraph(n);
cin >> t;
while (t--)
{
cin >> command;
if (command == "show++")
{
cout << xGraph++ << endl;
}
else if (command == "++show")
{
cout << ++xGraph << endl;
}
else if (command == "show--")
{
cout << xGraph-- << endl;
}
else if (command == "--show")
{
cout << --xGraph << endl;
}
else if (command == "show")
{
cout << xGraph << endl;
}
}
return 0;
}

3.要点

1.运算符重载的两种形式

  • 类成员函数(有this指针)ps:二元运算符以成员函数形式重载,左操作数必须为类对象,目标对象作为左操作数

  • 友元函数(无this指针)

  • 一般单目运算符最好重载为类的成员函数,双目运算符则重载为类的友元函数

  • 一些双目运算符不能重载为友元函数:=、()、[]、->

  • 若需要修改对象的状态,最好选择成员函数重载

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
CXGraph& operator++()//++a
{
if (N == 21) return *this;

// 释放原有内存
for (int i = 0; i < N; ++i)
delete[] x[i];
delete[] x;

N += 2;
x = new char* [N];
for (int i = 0; i < N; ++i)
x[i] = new char[N];

int temp = N;
for (int i = 0; i < ((N + 1) / 2); i++) {
for (int j = 0; j < i; j++) {
x[i][j] = ' ';
x[N - i - 1][j] = ' ';
}
for (int j = i; j < temp; j++) {
x[i][j] = 'X';
x[N - i - 1][j] = 'X';
}
temp--;
}

return *this;
}

!!!CXGraph CXGraph::operator++(int)【a++】返回的是局部变量,而返回局部变量(临时对象)的引用属于悬空引用,不正确。所以与前置加加不同,这里不返回引用。

3.关于<<和>>的运算符重载

1
2
friend ostream& operator<<(ostream& os,const CXGraph& t);
friend istream& operator>>(istream& is,CXGraph& t);

1.题目概述

定义一个矩阵类MyMatrix,并且在类中进行运算符重定义,用*实现矩阵相乘。要求必须对运算符进行重载,如果用函数如multiply(matrix,matrix)去实现矩阵之间的运算一律记0分。

必须包含以下析构函数,其中n是矩阵的阶数,data是存放矩阵数据的二维动态数组:

MyMatrix::~MyMatrix() { // 释放空间 for (int i = 0; i < n; i++) { delete[] data[i]; } delete[] data; }

矩阵相乘的具体内容不在此赘述

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
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <iostream>
using namespace std;

class MyMatrix
{
private:
int** data;
int my_n;
public:
MyMatrix()
{
my_n = 100;
data = new int* [100];
for (int i = 0; i < 100; i++)
{
data[i] = new int[100];
}
}
MyMatrix(int n, int** t)
{
my_n = n;
data = new int* [n];
for (int i = 0; i < n; i++)
{
data[i] = new int[n];
}

for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
data[i][j] = t[i][j];
}
}
}

MyMatrix(const MyMatrix& m)
{
my_n = m.my_n;
data = new int* [m.my_n];
for (int i = 0; i < m.my_n; i++)
{
data[i] = new int[m.my_n];
}

for (int i = 0; i < my_n; i++)
{
for (int j = 0; j < my_n; j++)
{
data[i][j] = m.data[i][j];
}
}

}

MyMatrix operator*(MyMatrix m)
{
int** arr = new int* [my_n];
for (int i = 0; i < my_n; i++)
{
arr[i] = new int[my_n];
}

for (int i = 0; i < my_n; i++)
{
for (int j = 0; j < my_n; j++)
{
int num = 0;
for (int k = 0; k < my_n; k++)
{
num += data[i][k] * m.data[k][j];
}
arr[i][j] = num;
}
}

MyMatrix res(my_n, arr);

for (int i = 0; i < my_n; i++)
{
delete[] arr[i];
}
delete[] arr;

return res;
}

MyMatrix& operator=(const MyMatrix& m) {
if (this == &m) return *this;

for (int i = 0; i < my_n; i++) {
delete[] data[i];
}
delete[] data;

my_n = m.my_n;
data = new int* [my_n];
for (int i = 0; i < my_n; i++) {
data[i] = new int[my_n];
for (int j = 0; j < my_n; j++) {
data[i][j] = m.data[i][j];
}
}

return *this;
}

~MyMatrix() {
for (int i = 0; i < my_n; i++)
{
delete[] data[i];
}
delete[] data;
}

void print()
{
for (int i = 0; i < my_n; i++)
{
cout << data[i][0];
for (int j = 1; j < my_n; j++)
{
cout<< " " << data[i][j] ;
}

if (i != my_n - 1) cout << endl;
}
}
};


int main()
{
int c;
int n;
cin >> c >> n;

int** arr = new int* [n];
for (int i = 0; i < n; i++)
{
arr[i] = new int[n];
}

MyMatrix** m = new MyMatrix*[c];



for (int i = 0; i < c; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
cin >> arr[j][k];
}
}
m[i] = new MyMatrix(n, arr);
}

MyMatrix res = *(m[0]);
for (int i = 1; i < c; i++) {
res = res * (*m[i]);
}

res.print();

for (int i = 0; i < n; i++)
{
delete[] arr[i];
}
delete[] arr;

for (int i = 0; i < c; i++) {
delete m[i];
}
delete[] m;

return 0;
}

重点:

1.主函数中,构造res时会调用拷贝构造函数,由于MyMatrix类中数据涉及到指针,所以要写深拷贝。

2.在做乘法时,res * (*m[i])会返回一个临时对象,这个对象将对res重新赋值,所以设计到赋值运算符的重载。

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
34
35
36
37
import rclpy
from rclpy.node import Node
import requests
from example_interfaces.msg import String
from queue import Queue

class NovelPubNode(Node):
def __init__(self,node_name):
super().__init__(node_name)
self.get_logger().info(f'{node_name},启动!!!!')
self.novels_queue=Queue() #创建队列 存数据
self.novel_publisher_ = self.create_publisher(String,'novel',10)
self.timer_ = self.create_timer(5,self.timer_callback)#创建定时器

def timer_callback(self):
#self.novel_publisher_.publish()
if self.novels_queue.qsize()>0:#判断队列大小
line=self.novels_queue.get()
msg=String()#组装
msg.data=line
self.novel_publisher_.publish(msg)
self.get_logger().info(f'发布了:{msg}')

def download(self,url):
response = requests.get(url)
response.encoding = 'utf-8'
text = response.text
self.get_logger().info(f'下载{url},{len(text)}')
for line in response.text.splitlines():
self.novels_queue.put(line)#按行分割

def main():
rclpy.init()
node = NovelPubNode('novel_pub')
node.download('http://0.0.0.0:8000/novel1.txt')
rclpy.spin(node)
rclpy.shutdown()

ps:

1.执行ros2 run demo_python_topic novel_pub_node时要同时在另一个终端打开服务器python3 -m http.s
erver(这里没注意到当时拖了好几周才解决)

2.ros2 topic echo /novel早于ros2 run demo_python_topic novel_pub_node才能接受到完整的内容

先启动订阅者,再启动发布者(服啦 每次都先启动完发布者,再开订阅者,我说怎么有时候可以收到最后两行。。。)

加号运算符

1.成员函数承载运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person
{
public:

//成员函数重载运算符
Person operator+(Person& p)
{
Person t;
t.m_A = this->m_A + p.m_A;
t.m_B = this->m_B + p.m_B;

return t;
}


int m_A;
int m_B;
};
//成员函数重载+的本质:p3=p1.operator+(p2)

2.全局函数重载运算符

1
2
3
4
5
6
7
8
9
10
//全局函数重载加号
Person operator+(Person& p1, Person& p2)
{
Person t;
t.m_A = p1.m_A+ p2.m_A;
t.m_B = p1.m_B + p2.m_B;

return t;
}
//全局函数重载本质调用:p3=operator+(p1,p2)

ps:运算符重载也可以发生函数重载

1
2
3
4
5
6
7
8
9
10
11
void test01()
{
Person p1;
Person p2;
p1.m_A = 10;
p1.m_B = 10;
p2.m_A = 10;
p2.m_B = 10;

Person p3 = p1 + p2;
}

左移运算符重载

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
class Person
{
friend ostream& operator<<(ostream& cout, Person& p);//友元函数 访问私有变量
public:
Person(int a, int b)
{
m_A = a;
m_B = b;
}
private:
int m_A;
int m_B;
};

//只能用全局函数重载左移运算符
//cout输出流对象只能有一个,所以要用引用的方式
ostream& operator<<(ostream &cout,Person &p)
{
cout << "m_A=" << p.m_A << "m_B=" << p.m_B;


return cout;
}

void test01()
{
Person p(10, 10);

cout << p << endl;
}

递增运算符重载

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
class MyInteger
{
friend ostream& operator<<(ostream& cout, MyInteger myint);

public:
MyInteger()
{
m_Num = 0;
}

//重载++运算符 前置
//返回引用是为了一直对一个数据进行操作
MyInteger& operator++()
{
m_Num++;
return *this;
}

//重载++运算符 后置
//返回值 而不是引用
MyInteger operator++(int) //int 代表占位参数,可以用于区分前置和后置
{
MyInteger temp = *this;
m_Num++;

return temp;
}
private:
int m_Num;
};

//左移运算符重载
ostream& operator<<(ostream& cout, MyInteger myint)
{
cout << myint.m_Num;
return cout;
}

void test01()
{
MyInteger myint;

cout << ++myint << endl;//输出1
}

void test02()
{
MyInteger myint;

cout << myint++ << endl;//输出0
cout << myint << endl;//输出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
34
35
36
37
38
39
40
41
42
43
44
45
46
class Person
{
public:
Person(int age)
{
m_Age = new int(age);
}

~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}

Person& operator=(Person& p)
{
//先判断是否有属性在堆区,如果有先释放干净,再进行深拷贝
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//深拷贝
m_Age = new int(*p.m_Age);
return *this;
//this是一个指向当前对象的指针,类型为Person*
//*this表示当前对象本身(而不是指针)
}

int* m_Age;
};

void test01()
{
Person p1(18);
Person p2(20);
Person p3(30);

p3 = p2 = p1;//因为重载时的返回类型是对象的引用,所以可以连续运算

cout << "p1的年龄" << *p1.m_Age;
cout << "p1的年龄" << *p2.m_Age;
}

关系运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Person
{
public:
Person(string name, int age)
{
m_Name = name;
m_Age = age;
}

bool operator==(Person& p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return true;
}

return false;
}

string m_Name;
int m_Age;
};

函数调用运算符重载

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
class MyPrint
{
public:

void operator()(string test)
{
cout << test << endl;
}
};

void test01()
{
MyPrint myPrint;
myPrint("hello world");//执行这条语句 会有输出:hello world
//由于使用起来非常类似于函数调用,因此称为仿函数
}

//仿函数非常灵活,没有固定写法
//加法类
class MyAdd
{
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}
};

void test02()
{
MyAdd myadd;
int ret = myadd(100, 100);

//匿名对象的调用 类名()
cout << MyAdd()(100, 100) << endl;
}

1.题目

定义一个电话号码类CTelNumber,包含1个字符指针数据成员,以及构造、析构、打印及拷贝构造函数。

字符指针是用于动态创建一个字符数组,然后保存外来输入的电话号码

构造函数的功能是为对象设置键盘输入的7位电话号码,

拷贝构造函数的功能是用原来7位号码的对象升位为8位号码对象,也就是说拷贝构造的对象是源对象的升级.电话升位的规则是原2、3、4开头的电话号码前面加8,原5、6、7、8开头的前面加2。

注意:电话号码只能全部是数字字符,且与上述情况不符的输入均为非法

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
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
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;

class CTelNumber
{
private:
char* str;
public:
CTelNumber(const char* num);
CTelNumber(const CTelNumber& c);
~CTelNumber();
void print();
};

CTelNumber::CTelNumber(const char* num)
{
str = new char[9];
strncpy(str, num , 7);
str[7] = '\0';
}

CTelNumber::CTelNumber(const CTelNumber& c)
{
str = new char[9];
strcpy(str, c.str);

if (str[0] == '2' || str[0] == '3' || str[0] == '4')
{
str[0] = '8';
}
else
{
str[0] = '2';
}
for (int i = 1; i < 8; i++)
{
str[i] = c.str[i - 1];
}
str[8] = '\0';
}

CTelNumber::~CTelNumber()
{
delete[]str;
}

void CTelNumber::print()
{
cout << str << endl;
}

bool isValid(char* s)
{
if (strlen(s) != 7 || s[0] == '1' || s[0] == '0' || s[0] == '9')
{
return false;
}

for (int i = 0; i < 7; i++)
{
if (s[i] > '9' || s[i] < '0')
{
return false;
}
}
return true;
}

int main()
{
int t;
cin >> t;

for (int i = 0; i < t; i++)
{
char* pn = new char[8];
cin >> pn;
bool flag = isValid(pn);
if (flag)
{
CTelNumber c1(pn);
CTelNumber c2(c1);
c2.print();
}
else
{
cout << "Illegal phone number" << endl;
}
}
return 0;
}

长教训了真的 下次我一定一定一定仔细读题
题目说234前面加8
5678前面加2
我一直都忘记了9这个数字开头也会是非法
一直只考虑了01开头非法
就多考虑这一点点 我前两天下午交的第一遍就可以对了!
后面我就是一直改一直试 我说怎么就不对我一定要做出来
后面实在是过不了了 我就把我的答案和题目发给AI 让它帮我改 我仔细对照了一下 我说那几个主要的函数都没有问题啊 而且我那三个测试样例可以过两个 到底是什么鬼
然后我就把AI的答案放进去测试就过了
虽然过了但我一直耿耿于怀 刚刚直接把前面写的全删了 我说我直接重开 我一定要找出来哪里有问题
最后的最后就是我发现…也是很眼瞎了 也是很执着了 也是长教训了!
所以把这道题写进来,希望自己以后多考虑一点。。。要不又是浪费时间在小问题上了。

1.创建链表

1
2
3
4
5
6
7
8
9
10
11
12
13
Node* createList()
{
Node* head = (Node*)malloc(sizeof(Data));
if (!head)
{
cout << "head malloc failed" << endl;
return nullptr;
}
//初始化为NULL
memset(head, 0, sizeof(Node));

return head;
}

其实这块就是创建了链表的head节点

链表的内存空间是不连续的,这块和顺序表有区别

2.创建节点

1
2
3
4
5
6
7
8
9
10
11
12
13
Node* createNode(Data val)
{
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode)
{
cout << "newNode malloc failed" << endl;
return nullptr;
}

newNode->data = val;
newNode->next = NULL;
return newNode;
}

3.插入数据

3.1头插

1
2
3
4
5
6
void push_front(Node* list, Data val)
{
Node* newNode = createNode(val);
newNode->next = list->next;//先让新节点接上首元节点
list->next = newNode;//头节点连上新节点
}

3.2尾插

1
2
3
4
5
6
7
8
9
10
11
void push_back(Node* list, Data val)
{
Node* curNode = list;
while (curNode->next)
{
curNode = curNode->next;
}//找到最后一个节点
Node* newNode = createNode(val);//尾节点指向新节点
curNode->next = newNode;//连接

}

3.3指定位置插入

1
2
3
4
5
6
7
8
9
10
11
12
13
void insert_pos(Node* list, int pos, Data val)
{
Node* curNode = list;
//先找到pos的前一个元素
for (int i = 0; i < pos && curNode->next; i++)
{
curNode = curNode->next;
}

Node* newNode = createNode(val);
newNode->next = curNode->next;
curNode->next = newNode;
}

3.4指定元素插入

1
2
3
4
5
6
void insert_item(Node* list, Node* item, Data val)
{
Node* newNode = createNode(val);
newNode->next = item->next;
item->next = newNode;
}

4.删除数据

4.1头删

1
2
3
4
5
6
7
void pop_front(Node* list)
{

Node* delNode = list->next;
list->next = delNode->next;
free(delNode);
}

4.2尾删

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void pop_back(Node* list)
{
//如果链表为空直接退出
if (empty(list)) return;

Node* curNode = list;
while (curNode->next && curNode->next->next)
{
curNode = curNode->next;//是倒数第二个节点
}
free(curNode->next);
curNode->next = NULL;

}

4.3删除指定元素

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
void removeOne(Node* list, Data val)
{
//如果链表为空直接退出
if (empty(list)) return;

Node* preNode = list;
Node* curNode = list->next;
while (curNode)
{
if (curNode->data == val)
{
break;
}
preNode = curNode;
curNode = curNode->next;
}
if (curNode)
{
preNode->next = curNode->next;
free(curNode);

}

}

void removeAll(Node* list, Data val)
{
if (empty(list)) return;

Node* preNode = list;
Node* curNode = list->next;
Node* delNode = NULL;
while (curNode)
{
if (curNode->data == val)
{
preNode->next = curNode->next;
delNode = curNode;
}
else {
preNode = curNode;//不是要删除的元素就移动preNOde
}

curNode = curNode->next;
//根据情况来释放
if (delNode)
{
free(delNode);
delNode = NULL;
}
}
}

5.其他

5.1排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void sort(Node* list)
{
if (empty(list)) return;

for (Node* i = list->next; i->next; i=i->next)
{
for (Node* curNode = list->next; curNode->next; curNode = curNode->next)
{
if (curNode->data > curNode->next->data)
{
Data t = curNode->data;
curNode->data = curNode->next->data;
curNode->next->data = t;
}
}
}

5.2 反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void reverse(Node* list)
{
if (empty(list)) return;

Node* preNode = NULL;
Node* curNode = list->next;
Node* nextNode = NULL;

while (curNode)
{
nextNode = curNode->next;
curNode->next = preNode;
preNode = curNode;
curNode = nextNode;
}
list->next = preNode;
}

5.3清空

1
2
3
4
5
6
7
8
9
10
11
12
void clear(Node* list)
{
Node* curNode = list->next;
Node* delNode = NULL;
while (curNode)
{
delNode = curNode;
curNode = curNode->next;
free(delNode);
}
list->next = NULL;
}

5.4销毁

1
2
3
4
5
6
void destroy(Node** list)
{
clear(*list);
free(*list);
(*list) = NULL;
}

5.5判断是否为空

1
2
3
4
5
bool empty(Node* list)
{

return list->next==NULL;
}

6.输出

1
2
3
4
5
6
7
8
9
10
11
void showlist(Node* list)
{
if (list == NULL) return;
Node* curNode = list->next;
while (curNode)
{
cout << curNode->data << " ";
curNode = curNode->next;
}
cout << endl;
}

0%