🏆个人主页:企鹅不叫的博客
🌈专栏
⭐️ 博主码云gitee链接:代码仓库地址
⚡若有帮助可以【关注+点赞+收藏】,大家一起进步!
【初阶与进阶C++详解】第二篇:C&&C++互相调用(创建静态库)并保护加密源文件
【初阶与进阶C++详解】第三篇:类和对象上(类和this指针)
【初阶与进阶C++详解】第四篇:类和对象中(类的六个默认成员函数)
【初阶与进阶C++详解】第五篇:类和对象下(构造+static+友元+内部类
【初阶与进阶C++详解】第六篇:C&C++内存管理(动态内存分布+内存管理+new&delete)
【初阶与进阶C++详解】第七篇:模板初阶(泛型编程+函数模板+类模板+模板特化+模板分离编译)
#include,不用加.h是为了和C语言区分,必须包含#include头文件以及using namespace std
void Teststring() { //以下字符串都默认有"\0" string s1; // 构造空的string类对象s1 string s2("hello bit"); // 用C格式字符串构造string类对象s2 string s3(s2); // 拷贝构造s3 string s4 = s2;//拷贝构造 string s5("abcdefg", 3);//初始化前3个 string s6(100,"A");//用100个A初始化 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
函数名称 功能说明 size(重点) 返回字符串有效字符长度 length 返回字符串有效字符长度 capacity 返回空间总大小 empty (重点) 检测字符串释放为空串,是返回true,否则返回false clear (重点) 清空有效字符,不改变底层空间的大小 reserve (重点) 为字符串预留空间,可以填充 resize (重点) 修改字符个数上线,并且可以添加字符 reserve和resize:
reserve (size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:reserve (n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间,不填c的话,默认是给0。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变,reserve只修改capacity大小,不修改size大小,resize既修改capacity大小,也修改size大小。
函数名称 功能说明 operator[] (重点) 返回pos位置的字符,const string类对象调用 begin+ end begin获取第一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器 rbegin + rend rbegin获取最后一个字符的迭代器 + rend获取第一个字符位置的迭代器 范围for C++11支持更简洁的范围for的新遍历方式 template<class T = char> class basic_string { pubulic: basic_string(const T* str) { //开空间存储,方便增删查改 size_t len = strlen(str); _str = new T(len + 1);//预留\0 strcpy(_str, str); } //减少拷贝,可以读,可以修改 T& operator[](size_t pos) { return _str[pos]; } private: const T* _str; size_t _size; size_t _capacity; }; int main () { string s("hello world"); //1.下标+[] for (int i = 0; i < s.size(); ++i) { //将每个字符加一 s[i] += 1; cout << s[i] << " "; } //2.1 正向迭代器(类似指针,链表需要,区间是左闭右开,可读可写) //可以使用auto简化 //auto it = s.begin(); string::iterator it = s.begin(); while (it != s.end()) { //将每个字符加一 (*it) += 1; ++it; } //2.2 反向迭代器() string::reverse_iterator rit = s.rbegin(); while (rit != s.rend()) { //将每个字符加一 (*rit) += 1; ++rit; } //2.3 正向const迭代器(此时迭代器只能读,不能写) string::const_iterator cit = s.begin(); while (cit != s.end()) { //此时不能写 //(*cit) += 1; ++cit; } //2.4 反向向const迭代器(此时迭代器只能读,不能写) // string::const_reverse_iterator crit = s.begin(); //3.范围for for (auto ch : s) { cout << ch << endl; } cout << endl;; 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
函数名称 功能说明 c_str(重点) 返回C格式字符串 find+npos(重点) 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 substr 在str中从pos位置开始,截取n个字符,然后将其返回 int main() { //1.c_str //返回一个指向数组的指针,该数组包含一个以空字符结尾的字符序列(即一个 C 字符串),为了和C相适应 //下面打印出来是一样的 string str("hello"); cout << str << endl; cout << str.c_str() << endl; //2.find在字符串中查找内容 string file("file.cpp"); size_t found = file.find('.'); //npos是static const size_t npos = -1;无符号为最大值 //从found开始,直到npos结束 if (found != string::npos) { //3.substr截取字符串 string suffix = file.substr(found, file.size()-found); cout << suffix << endl; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
class string { //实现深浅拷贝 public: string(const char* str) :_str(new char[strlen(str)+1]) { strcpy(_str, str); } ~string() { if (_str) { delete[]_str; } } const char* c_str() const { return _str; } char& operator[](size_t pos) { assert(pos < strlen(_str)); return _str[pos]; } size_t size() { return strlen(_str); } private: char* _str; }; void Teststring() { string s1("hello!"); string s2(s1); }
- 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
class string { //实现深浅拷贝 public: //浅拷贝,不能将str直接初始化_str,str是常量字符串直接给_str会造成权限放大 //构造函数,记得给缺省值 string(const char* str = "") :_size(strlen(str)) , _capacity(_size) { //所以另外给_str开一段空间,多一个给'\0' _str = new char[_capacity + 1]; strcpy(_str, str); } //无参默认构造,默认给\0 string() :_size(0) ,_capacity(_size) { _str = new char[1]; _str[0] = '\0'; } //深拷贝 //传统写法-拷贝构造 string(const string& s) :_size(strlen(s._str)) ,_capacity(_size) { //开辟空间,然后将开辟的空间地址给_str _str = new char[_capacity + 1]; strcpy(_str, s._str); } void swap(string& s) { //交换_str和tmp._s,就相当于给this->_str开辟了一块空间,当拷贝函数结束,tmp就会被自动释放 std::swap(_str, s._str);//调用std中函数 std::swap(_size, s._size); std::swap(_capacity, s._capacity); } //现在写法-利用构造函数构造一个临时对象,然后利用swap将临时对象换给新的对象 //S2(S1) string(const string& s) : _str(nullptr)//置空,开始_str是个随机数,交给tmp,_str后,释放会引起问题 , _size(0) , _capacity(0) { string tmp(s._str);//利用构造函数给tmp对象开辟一块空间 //tmp与this交换 swap(tmp); } //析构函数 ~string() { if (_str) { delete[]_str; _str = nullptr; _size = _capacity = 0; } } const char* c_str() const { return _str; } char& operator[](size_t pos) { assert(pos < strlen(_str)); return _str[pos]; } //用引用返回防止深拷贝 string& operator=(const string& s) { //防止自己给自己赋值 if (this != &s) { 传统写法 首先创建一个tmp用来开辟所需空间,防止开辟失败导致原数据丢失 //char* tmp = new char(s._capacity + 1); //strcpy(tmp, s._str); 不知道传过来的空间有多大,从而无法确定应该准备多大空间,所以删除原来的空间,重新计算所需空间大小 //delete[]_str; //_str = tmp; //_size = s._size; //_capacity = s._capacity; //新写法 string tmp(s._str); swap(tmp); } return *this; } //更加简洁的写法 //s是传值传参 string& operator=(string s) { swap(s); return *this; } size_t size()const { return _size; } size_t capacity()const { return _capacity; } string& operatpr+=(char ch) { push_back(ch); return *this; } void reseve(size_t n) { if (n > _capacity) { char* tmp = new char[n + 1]; strcpy(tmp, _str); delete[]_str; _str = tmp; _capacity = n; } } void resize(size_t n, char ch = '\0') { if (n < _size) { _size = n; _str[_size] = '\0'; } else { if (n > _capacity) { reseve(n); } for (size_t i = _size; i < n; ++i) { _str[i] = ch; } _size = n; _str[_size] = '\0'; } } //尾插一个字符 void push_back(char ch) { //判断是不是满了 if (_capacity == _size) { reseve(_capacity == 0 ? 4 : _capacity * 2); } _str[_size] = ch; ++_size; _str[_size] = '\0'; } //尾插一个字符串 void append(const char* str) { size_t len = _size + strlen(str); if (len > _capacity) { reserve(len); } strcpy(_str + _szie, str); _size = len; } ostream& operator<<(ostream& out, const string& s) { for (auto ch : s) { out << ch; } return out; } istream& operator>>(istream& in, const string& s) { char ch; ch = in.get(); char buff[128] = {'\0'}; size_t i = 0; while (ch != ' ' || ch != '\0') { buff[i++] = ch; if (i == 127) { s += buff; memset(buff, '\0', 128); i = 0; } ch = in.get(); } s += buff; return in; } bool operator<(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) < 0; } bool operator==(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) == 0; } bool operator>(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) > 0; } bool operator<=(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) <= 0; } bool operator>=(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) >= 0; } bool operator!=(const string& s1, const string& s2) { return strcmp(s1.c_str(), s2.c_str()) != 0; } //插入一个字符 string& insert(size_t pos, char ch) { assert(pos < _size); if (_size == _capacity) { reserve(_capacity == 0 ? 4 : _capacity*2); } //不能用size_t,后面end减小的时候可能会变成-1 int end = _size; //end类型是int,pos类型是size_t,两者比较,int会整型提升unsinged int //如果pos是size_t的话,会死循环 while (end >= (int)pos) { _str[end+1] = _str[end]; end--; } _str[pos] = ch; ++_size; return *this; } //插入一个字符串 string& insert(size_t pos, const char* str) { assert(pos <= _size); size_t len = strlen(_size); if (len + _size > _capacity) { reserve(_size+len); } //往后挪动len长度 size_t end = _size+len; while (end >= pos+len) { _str[end] = _str[end-len]; --end; } strncpy(_str + pos, str, len); _size += len; return *this; } //删除 string& earse(size_t pos, size_t len == npos) { assert(pos < _size); //如果删除长度超过字符串长度,或者删除完毕了 if (len == npos || pos + len >= _size) { _str[pos] = '\0'; _size = pos; } //直接覆盖 else { size_t begin = pos + len; while (begin <= _size) { _str[begin-len] = _str[begin]; ++begin; } _string&size -= len; } return *this; } //从pos位置开始寻找一个字符,找到就范围字符位置,没找到就返回npos size_t find(char ch, size_t pos) { while (pos < _size) { if (_str[pos] == ch) { return pos; } pos++; } return npos; } //从pos位置开始找一段字符串,我们可以使用strstr字符串查找函数 size_t find(const char* str, size_t pos) { const char* p = strstr(_str+pos, str); if (p == nullptr) { return npos; } else { return p - _str; } } //void claer() private: char* _str; size_t _size;//有效字符的个数 size_t _capacity;//存储有效字符的空间 const static size_t npos;//这里是声明不能给缺省值 }; const static size_t string::npos = -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
- 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
功能:将数字常量转换为字符串
//下面将输入的i转化成字符串 int main() { int i; cin >> i; string s = to_string(i); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
功能:将的字符串转化为十进制
stoi(字符串,起始位置,n进制),将 n 进制的字符串转化为十进制 示例: stoi(str, 0, 2); //将字符串 str 从 0 位置开始到末尾的 2 进制转换为十进制
- 1
- 2
- 3
string s1("hello world"); string s2(s1);
- 1
- 2
如果是浅拷贝运行以上代码会报错,理由是s1和s2都指向同一个空间,到析构函数的时候,会调用两次析构函数,该控件会释放两次,为避免浅拷贝,我们要给新对象开辟一个空间进行深拷贝,在上面模拟实现中有深拷贝实现