stl-string

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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
#include<iostream>
using namespace std;
#include<cstdio>
//string就是管理字符串的类
#include<string>

//库里面定义
template<class T>
class basic_string
{
private:
T* _str;
//...
};


//编码 --值--符号建立映射关系--编码表(用值和符号建立对应关系)
// ASCILL编码表---表示英文编码
// unicode ---(包含ascill)表示全世界文字编码
//又包含utf -8,utf-16
//gbk -- 中国自己量身定做的编码表
// 汉字可以用2个字节,
//
//typrdef basic_string<char> string,我们用的是typedef后出来的,模板的

//int main()
//{
// string s1("hello");
// char str2[] = "吃饭";
// cout << sizeof(char) << endl;
// cout << sizeof(wchar_t) << endl;//2个字节,wstring
//
// return 0;
//}



//初始化

void init()
{
string s1;//无调用构造函数
string s2("hello world");//构造函数
string s3(s2);//拷贝构造
//cin >> s1;
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
//substring (3)

//string(const string & str, size_t pos, size_t len = npos);
//利用字串进行初始化,pos是从0开始,从string里面先后数len个长度进行拷贝


string s4(s2, 2, 6);
cout << s4 << endl;//llo wo
string s5(s2, 2);//默认从坐标为2的地方往后截取所有的s2
cout << s5 << endl;//ello world

//string (const char* s, size_t n);
string s7("hello world", 3);//取前3个字符
cout << s7 << endl;
//string(size_t n, char c);连续弄n个c
string s8(3, '!');//!!!
}


void func()
{
string s1("hello");
//不计算‘\0’,这两个对于string没什么区别,size是后出现为了保证容器的一致性
cout << s1.size() << endl;//5
cout << s1.length() << endl;//5
cout << s1.max_size() << endl;//没什么意义
cout << s1 << endl;
//计算容量
cout << s1.capacity() << endl;//15
s1.clear();//把有效数据都清理掉,空间保留,变成空字符串,0个字符
cout << s1 << endl;
cout << s1.capacity() << endl;
if (s1.empty())//判断此字符串是否为空,即是否长度为0
{
cout << "not" << endl;
}


}


//char& operator[] (size_t pos);这里的引用返回是因为这个数组是在堆上开辟的,出了作用域还在,并且可以对其中的字符进行修改,或者调用,还可以减少拷贝(不是主要目的)


void operatoracess()
{
string s1("hello world");
for (size_t i = 0; i < s1.length(); i++)
{
cout << s1[i];//[]是断言终止程序,检查错误
s1[i] += 1;
}
cout << endl;
for (size_t i = 0; i < s1.length(); i++)
{
s1.at(i) -= 1;//和上面是一样的
cout << s1.at(i) << endl;//at是抛异常检查错误,建议还是使用[ ]
}
cout << endl;

}

//对字符串进行尾部添加字符或字符串
void add()
{
string s;
s.push_back('a');
s.append("bcde");//尾插bcd
cout << s << endl;//abcd
s += '!';//也可以利用运算符重载进行实现尾插,推荐,abcd!
}


//只交换字符
//abc-bcd-qwlkj变成 jkl-wqd-cbcba
//
class Solution {
public:
//计算最后一个单词的长度如“hello world ”g

int lengthOfLastWord(string s) {
int end=s.size()-1;
while(s[end]==' ')
{
s.erase(end,1);//无法使用
end--;


}

size_t pos=s.rfind(" ");

string sub=s.substr(pos+1);
return sub.size();




}




};

//遍历,1.迭代器2.范围for
void test_string1()
{

string s1("hello");
string::iterator it=s1.begin();//s1.begin(),是第一个数据的地址,s1.end()是最后一个数据的后一个的地址
//这个iterator是定义在string里面,it现在指向了第一个数据的地址
//现在可以先想象成一个像指针一样的类型
//
while(it!=s1.end())//直到结尾就结束了,但是不建议用<
{
cout<<*it<<" ";//*就是取他的数据
++it;//到下一个地址
}
cout<<endl;
//除了可以读还可以写
it=s1.begin();//s1.begin(),是第一个数据的地址,s1.end()是最后一个数据的后一个的地址
//这个iterator是定义在string里面,it现在指向了第一个数据的地址
//现在可以先想象成一个像指针一样的类型
//
while(it!=s1.end())//直到结尾就结束了
{
*it-=1;//*就是取他的数据
++it;//到下一个地址
}
cout<<endl;


//范围for,auto可以自动识别
//for(auto e:s1)//把s1里面每个字符取出来赋值给e,不需要自己++,自动判断结束
//{
// cout<<e<<" ";
//}
cout<<endl;

//要修改就要用引用
//for(auto& e:s1)
//{
// e-=1;
//}
cout<<endl;

//反向迭代器
//倒着遍历
string::reverse_iterator rit=s1.rbegin();//rbegin(),是最后一个数据的地址
//为了简化代码也可以直接auto推到
//
//auto rit=s1.rbegin()
//
while(rit!=s1.rend())//rend()是第一个数据的前一个地址
{
cout<<*rit<<" ";//olleh,反过来遍历
++rit;//反向迭代器的++,是往左走的
}
cout<<endl;

//迭代器遍历的意义是什么呢:所有的容器都可以用迭代器这种访问修改
//1.对于string类来说,利用[]都足够好用,确实可以不用迭代器
//2。对于其他容器(数据结构)也可以使用,如list,map,set,这些是不支持[],因为只有像数组一样的东西才支持[]遍历和下标,
//结论::对于string得会用迭代器,但是我们还是喜欢下标加[],

//还有const迭代器,普通迭代器是可读可写的
string cstr("hello world");
//funcion(cstr);
string::const_iterator re=s1.begin();//只读不写,同理还有反向迭代器
//cbegin()就是const迭代器,但是我们平时都不太用,

}



//对于容量的函数
void test_string3()
{
string s1;
s1.reserve(100);//可以设置容量的大小,容量就是100,加上原来的容量
string s2;
s2.resize(100,'x');//也是可以设置容量的大小,同时还可以对其进行初始化,如将s1有效数据的后面全部设置成x,如果没有第二个参数,则默认是‘\0’
}





//对于find,c_str ,rfind的认识与理解
void test_string2()
{

string s2="hello world";
cout<<s2.c_str()<<endl;//将string转变成c语言的形式字符串,char*,以\0截至
string file("test.txt");
//我们要以c语言的形式打开一个文件
//FILE* fout=fopen(s2.c_str(),"w"); //fopen第一个参数是char*,所以用这函数

//要求取出文件的后缀

size_t pos=file.find('.');//在file里面查找‘x’的位置,find的返回值是size_t,下标从0开始,查找第一个符合的坐标,否则就返回-1

string s1(file,pos);
cout<<s1<<endl;
if(pos!=string::npos)
{
string suffix=file.substr(pos);
cout<<suffix<<endl;
}

//rfind()//可以从后面完前找,找到第一个.,方便找后缀名
//https://blog.csdn.net/m0_61567378?spm=1000.2115.3001.5343
string url("http://blog.csdn.net/m0_61567378?spm=1000.2115.3001.5343");
//找协议头
size_t pos1=url.find(':');//:前面的就是协议头

string protocol=url.substr(0,pos1-0);//取得字串就是从0开始,到pos1位置,长度为pos1的字串,也就是http
cout<<protocol<<endl;

//找域名,
size_t pos2=url.find('/',pos1+3);//find默认从0开始找,现在我们给定他从pos1+3位置处开始找,也就是b开始,往后找,找到/的位置

string domain=url.substr(pos1+3,pos2-pos1-3);
cout<<domain<<endl;

//统一资源定位
string uri=url.substr(pos2+1);
cout<<uri<<endl;


}



//
void test_string4()
{

//insert不太推荐用,O(n),效率低

string s="hell";
s.insert(0,"owlod");//在头上插入一个owlod,是从第0个位置往后插入
s.insert(0,1,'x');//在头上插入一个x,是
s.insert(4,"xx");//从第4个位置往后插入xx
cout<<s<<endl;

//要挪动数据效率很低,
s.erase(4,2);//从4位置,删除两个长度的字符
cout<<s<<endl;
s.erase(s.size()-1,1);//尾删
s.erase(3);//第二个参数不给值就后面全部都删除了

//尾删也可以
//s.pop_back();

//输入一整行的数据,包括‘ ’
getline(cin,s);//第一个参数是流


}



void test_string5()
{

string s1="hello";
string s2="string";
cout<<(s1<s2)<<endl;//h<s所以就是小于

cout<<("hello"<s2)<<endl;//char*的也可以比较
cout<<(string("hello")<s2)<<endl;//这样也是可以的
}



//字符串与整形的转化


void test_string6()
{

int val=stoi("1234");//转变成int
cout<<val<<endl;//1234
double val1=stod("123");
//转变成字符串
string str=to_string(12.345);
string s=to_string(123456);


string str = to_string(12.345);

}


//浅拷贝,完成值拷贝,将每个字节一起拷贝
//对于指针类型的就不可以靠浅拷贝
//浅拷贝抄作业连名字都没改,完完全全的抄
//深拷贝就是抄作业改了名字,不完全的抄
//

classm my_string
{
private:
char* _str;
public:
//构造函数
my_string(const char* str)
:_str(new char[strlen(str)+1])
{
strcpy(_str,str);
}

//拷贝构造要用深拷贝
my_string(const my_string& s)
:_str(new char[strlen(str)+1])
{
strcpy(_str,s.str);
}

}

void test_string7()
{


}




int main()
{
// init();
// func();
// operatoracess();
// add();
// Solution sl;

// sl.reverseOnlyLetters("Test1ng-Leet=code-Q!");
//test_string1();
//test_string3();
//test_string2();
//test_string4();
Solution ts;
string s="hello world ";
//int k=ts.lengthOfLastWord(s);
//cout<<k<<endl;
//test_string6();

string s1 = "A man, a plan, a canal: Panama";

isPalindrome(s1);

return 0;

}

stl-string
http://example.com/2022/03/17/stl-string/
作者
Zevin
发布于
2022年3月17日
许可协议