-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGenmanString.h
More file actions
340 lines (328 loc) · 8.55 KB
/
Copy pathGenmanString.h
File metadata and controls
340 lines (328 loc) · 8.55 KB
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
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#ifndef GenmanStrings
#define GenmanStrings
#endif
#include <cstring>//for strlen() &s
#include <iostream>
#include <stdexcept>
//参考文献 https://space.shantou.university/posts/4415/german_strings/
//一种很酷的字符串设计,用于数据库等情形,尝试自己实现。
//字符串状态标识,用于区分生命周期。只实现持久化状态persistent。
/*
mainpage: yuliusw.github.io
e-mail: 2023011673@bistu.edu.cn
*/
class GenmanString
{
//private:
public:
int __len;//为方便内存测试改为public
union base //使用 union 字段确保长短字符串仅有一种实现,因为使用指针进行长字符串构造时的重分配,舍弃了capacity,详见参考文献;
{ //因此对字符串的增删改操作开销较大,适合静态字符串情形(读取,分析);
struct L {
char* __ptr;
char prefix[4];
}longStr;
struct S { //为保证内存对齐,封装一个struct
char inlined[16];
}shortStr;
}B;
//public:
GenmanString() {
__len = 0;
B.shortStr.inlined[0] = '\0';
};
GenmanString(const char src) {
__len = 1;
B.shortStr.inlined[0] = src;
B.shortStr.inlined[1] = '\0';
}
GenmanString(const char* src) {
if (src == nullptr) //空字符串初始化,std::string 的实现是不包括空字符的
{
__len = 0;
B.shortStr.inlined[0] = '\0';
}
else //分别实现短字符串和长字符串初始化
{
int lemgth = strlen(src);
__len = lemgth;
if (lemgth > 15) //str____len()不包括空字符,确保短字符串预留足够空间
{
for (int i = 0; i < 4; i++)
{
B.longStr.prefix[i] = src[i]; //[0]~[3]
}
B.longStr.__ptr = new char[lemgth - 3]; //lemgth+1(空字符)-4(prefix)
for (int i = 0; i < lemgth - 4; i++)
{
B.longStr.__ptr[i] = src[i + 4]; //src[4]~lemgth
}
}
else
{
strcpy(B.shortStr.inlined, src);
}
}
};
GenmanString(const int len) {
__len = len;
if (len > 15)
{
B.longStr.__ptr = new char[len - 3];
}
else
{
B.shortStr.inlined[0] = '\0';
}
};
GenmanString(const GenmanString& other) {
this->__len = other.__len;
if (__len > 15)
{ //debug:堆栈错误
//strcpy(this->B.longStr.prefix, other.B.longStr.prefix);
//操作prefix时不能使用strcpy,因为strcpy的终止条件为\0;但prefix不存\0,但long.ptr可以使用strcpy;
for (int i = 0; i < 4; i++)
{
this->B.longStr.prefix[i] = other.B.longStr.prefix[i];
}
B.longStr.__ptr = new char[__len - 3];
strcpy(B.longStr.__ptr, other.B.longStr.__ptr); //开新内存并且复制长字符串的内容
}
else
{
strcpy(this->B.shortStr.inlined, other.B.shortStr.inlined); //用类对象存储内容
}
};
GenmanString (GenmanString&& other) {
//对于移动构造函数,将成员union的值直接赋值给新对象(两者的union成员不共用地址),无需考虑字符串长短。
//不实现union的移动构造并使用this->B = &other.B 是因为 B是字符串对象内固定大小的空间,union的移动构造将导致对两个对象析构时重复析构第一个union空间。
this->__len = other.__len;
this->B = other.B;
other.B.longStr.__ptr = nullptr;
}
~GenmanString(void) { //析构函数中仅需要析构长字符串中的__ptr所指向内存块,剩余的成员将由默认析构函数提供;
if (__len > 15)
{
delete(B.longStr.__ptr);
}
};
GenmanString& operator =(const GenmanString& other) { //完全复制,实现长赋值长,短赋值短,短赋值长,长赋值短
if (this == &other)
return *this;
else
{
int prelen = this->__len;
this->__len = other.__len;
if (prelen > 15 && __len > 15)
{
delete(this->B.longStr.__ptr);
for (int i = 0; i < 4; i++)
{
B.longStr.prefix[i] = other.B.longStr.prefix[i];
}
B.longStr.__ptr = new char[__len - 3];
strcpy(B.longStr.__ptr, other.B.longStr.__ptr);
}
else if (prelen > 15 && __len < 15)
{
delete(this->B.longStr.__ptr);
this->B.shortStr.inlined[0] = '\0';
strcpy(B.shortStr.inlined, other.B.shortStr.inlined);
}
else if (prelen <= 15 && __len <= 15)
{
strcpy(B.shortStr.inlined, other.B.shortStr.inlined);
}
else
{
for (int i = 0; i < 4; i++)
{
B.longStr.prefix[i] = other.B.longStr.prefix[i];
}
B.longStr.__ptr = new char[__len - 3];
strcpy(B.longStr.__ptr, other.B.longStr.__ptr);
}
}
return *(this);
};
char& operator[](int indexx) {
if (indexx > this->__len)
{
std::cout << "数组越界" << std::endl;
}
if (this->__len > 15)
{
if (indexx < 4)
{
return this->B.longStr.prefix[indexx];
}
else
{
return this->B.longStr.__ptr[indexx - 4];
}
}
return this->B.shortStr.inlined[indexx - 1];
};
GenmanString operator+(GenmanString& str4) {
if (str4.__len == 0)
{
return *(new GenmanString(*this));
}
int new_length = this->__len + str4.__len;
GenmanString* res = new GenmanString(new_length+1);
if (new_length > 15) //为\0留一位
{ //复制this内容,复制后最后一位字符占用了__ptr[this->len-5]
if (this->__len > 15)
{
//strcpy(res->B.longStr.prefix, this->B.longStr.prefix); debug 今天发现堆栈溢出了,strcpy判定条件是空字符,prefix没有空字符;
for (int i = 0; i < 4; i++)
{
res->B.longStr.prefix[i] = this->B.longStr.prefix[i];
}
strcpy(res->B.longStr.__ptr, this->B.longStr.__ptr);
}
else
{
for (int i = 0; i < 4; i++)
{
res->B.longStr.prefix[i] = this->B.shortStr.inlined[i];
}
for (int i = 4; i < this->__len; i++)
{
res->B.longStr.__ptr[i - 4] = this->B.shortStr.inlined[i];
}
}
int nowindex = this->__len - 4; //方便后续复制
if (str4.__len > 15)
{
for (int i = 0; i < 4; i++)
{
res->B.longStr.__ptr[nowindex + i] = str4.B.longStr.prefix[i]; //最后一位在[this.len]
}
nowindex += 4;
for (int i = 0; i < str4.__len - 4; i++)
{
res->B.longStr.__ptr[nowindex] = str4.B.longStr.__ptr[i];
nowindex++;
}
}
else
{
for (int i = 0; i < str4.__len; i++)
{
res->B.longStr.__ptr[nowindex] = str4.B.shortStr.inlined[i];
nowindex++;
}
}//
//复制完毕,添加\0
res->B.longStr.__ptr[new_length - 4] = '\0';
} //
else //处理结果为短字符串的情况,此情况下只有短字符串相加得出
{
strcpy(res->B.shortStr.inlined, this->B.shortStr.inlined); //有效字符最后位占用this.len - 1
int nowindex = this->__len - 1;
for (int i = 0; i < str4.__len; i++)
{
res->B.shortStr.inlined[nowindex + i] = str4.B.shortStr.inlined[i];
}//复制完毕,添加\0
res->B.shortStr.inlined[new_length] = '\0';
}
return *res;
};
friend std::ostream& operator<<(std::ostream& cout, GenmanString & g) {
if (g.__len>15) {
for (int i = 0; i < 4; i++)
{
cout << g.B.longStr.prefix[i];
}
cout << g.B.longStr.__ptr;
}
else
{
cout << g.B.shortStr.inlined;
}
return cout;
};
GenmanString& operator<<(const char* c) {
int coun = strlen(c);
if (this->__len > 15) {
char* new_ptr = new char[ this->__len +coun- 3 ];
strcpy(new_ptr, this->B.longStr.__ptr);
int j = 0;
for (int i = this->__len - 4 ;i < this->__len+coun-4; i++)
{
new_ptr[i] = c[j]; j++;
}
this->__len += coun;
delete(this->B.longStr.__ptr);
this->B.longStr.__ptr = new_ptr;
}
else
{
if (coun+this->__len>15)
{
char mid[4]; //对union区的修改将导致原数据失效,因此这里需要一个中间变量暂存
char* new_ptr = new char[this->__len + coun - 3];
if (this->__len<4)
{
strcpy(mid, this->B.shortStr.inlined);
int nowindex = 4-this->__len;
int j = 0; //2
for (int i = this->__len; i < 4; i++)
{
mid[i] = c[j];
j++;
}
j = 0;
for (int i = nowindex; i < coun; i++)
{
new_ptr[j] = c[i];
j++;
}
}
else
{
for (int i = 0; i < 4; i++)
{
mid[i] = this->B.shortStr.inlined[i];
}
int j = 0;
for (int i = 4; i < this->__len; i++)
{
new_ptr[j] = this->B.shortStr.inlined[i];
j++;
}
for (int i =0; i < coun; i++)
{
new_ptr[j] = c[i];
j++;
}
}
for (int i = 0; i < 4; i++)
{
this->B.longStr.prefix[i] = mid[i];
}
this->B.longStr.__ptr = new_ptr;
this->__len += coun;
this->B.longStr.__ptr[this->__len - 4] = '\0';
}
else
{
int j = this->__len;
for (int i = 0; i < coun; i++)
{
this->B.shortStr.inlined[j] = c[i];
j++;
}
this->__len += coun;
this->B.shortStr.inlined[this->__len+1] = '\0';
}
}
return *this;
};
GenmanString& operator+=(const char* c) {
return *this << c;
}
};