提醒:
本片博客只是小编的听课笔记,介意勿看。
基础
包含在头文件<string>,才能使用string类似函数接口。
string常见构造类
cpp
string s1;
cin>>s1;//无参构造
string s2(s1);//拷贝构造
string s1("jfksa");//传参构造
三种遍历方式
cpp
//三种遍历方式
//s.begin()返回第一个字符
//s.end();返回最后一个字符的下一个位置(\0位置)
//一operator【】
for (int i = 0; i < s2.size(); i++) {
cout << s2[i];
}
cout << endl;
//二.迭代器iterator
string::iterator it = s2.begin();//it类似于指针,但本质可能和是运算符重载
while (it != s2.end()) {
cout << *it;//*it类似于解引用。本质也像是运算符重载
it++;
}
cout << endl;
//三。范围for进行遍历
//范围for进行遍历
string s3("llpphh");
for (auto ch : s3) {
cout << ch << " ";
}
cout << endl;
迭代器和范围for的去区别
两则底层逻辑相同,但是对于迭代器来讲可以在迭代器中修改变量值(因为底层类似指针可以直接修改对应地址的·1值),而对于范围for来讲,(auto ch: s2)相当于是一个拷贝,修改ch的值并不能修改实参的值,所以需要用引用(auto& ch: s2)才能修改变量的值。
auto
使用价值:方便类型推导
cpp
string::ioterator it= //变量名太长
auto it = ; //简化
typeid(变量名).name()//判断变量类型
string迭代器
cpp
iterator //正向
const_iterator //const
reverse_iterator //反向
const_reverse_iterator //const 反向
对应案列如下
cpp
string s4("hello world");
//正向
string::iterator it1 = s4.begin();
while (it1 != s4.end()) {
cout << *it1;
it1++;
}
cout << endl;
//反向迭代器
string::reverse_iterator rit = s4.rbegin();
while (rit != s4.rend()) {
cout << *rit;
rit++;
}
cout << endl;
const string s5("hello world");
//const迭代器
string::const_iterator it2 = s5.begin();
while (it2 != s5.end()) {
cout << *it2;
it2++;
}
cout << endl;
//const反向迭代器
string::const_reverse_iterator it3 = s5.rbegin();
while (it3 != s5.rend()) {
cout << *it3;
it3++;
}
cout << endl;
string 容器
size()/length()
cpp
//size获取字符长度
string s2("lvpanhao");
cout << s2.size() << endl;//经常用
cout << s2.length() << endl;//不具有通用性
capacity()扩容
s.reverse(n)//提前开n个空间
s.clear()//清除字符串/不清楚容量
cpp
s.push_back('x');//尾插字符
s.append("aaaaaaaa");//尾插字符串
insert/头插
cpp
s.insert('x'/"hujkf");//可以是字符也可以是字符串
erase//指定位置删除字符
cpp
s.erase(pos ,n)//pos位置删除n个字符
s.erase(s.begin());//迭代器版本头删
replace();//替换
cpp
replace(pos,n,'%%');//pos的n个位置替换成%%
substr//构建子串、
cpp
string s5("lvpanhao");
cout << s5.substr(2, 3) << endl;//下表为2 长度为3的子串
find//查找指定字符/指定字符串
cpp
int pos=s.find(' ');//返回找到字符的下标
//把所有空格替换为%
//替换所有空格为%
string s4("hello world I am Lihua");
int pos = s4.find(' ');
while (pos != string::npos) {
s4.replace(pos, 1, "%%");
pos = s4.find(' ');//每次从头开始找替换为int pod=s.find(' ',pos);//从某个位置开始找字符
}
cout << s4 << endl;
rfind/倒着找
cpp
//利用场景
//倒着找文件后缀方法
int pos1 = s6.rfind('.');
cout << s6.substr(pos1) << endl;
string s7("test.cpp.zip");
int pos2 = s7.rfind('.');
cout << s7.substr(pos2) << endl;
ind_first_of("abcd")//查找abcd所在位置
find_last_of("abcd")//倒着找查找不是abcd的全替换
cpp
string s8("hello world i love you");
//把aeiou字符改为*
size_t pos3 = s8.find_first_of("aeiou");
while (pos3 != string::npos) {
s8.replace(pos3,1,"*");
pos3 = s8.find_first_of("aeiou",pos3+1);
}
cout << s8 << endl;
getline()遇到换行才终止
cpp
string s1;
getline(cin,s1,)
//自己加终止条件
getLine(cin,s1,'*');//默认遇到*终止
c_str()
相当于一个字符一个字符读取字符串,遇到,'\0'会终止读取。
字符串匹配
strstr算法
strstr(const char* str1,const char* str2);
str2字串/str1主串
字串str2返回str1中的第一个位置字符
优化拷贝构造(赋值重载)
传统拷贝构造(赋值重载)
cpp
//拷贝构造
string& string(const string& s1){
//必须先自己申请空间
_str=new char[n];
strcpy(_str,s1._str);
_size=s1.size;
_capacity=s1._capacity;
}
//赋值重载
string& string(const string& s1){
//必须先自己申请空间
delete[] _str;
_str=new char[n];
strcpy(_str,s1._str);
_size=s1.size;
_capacity=s1._capacity;
}
现代拷贝构造
//利用交换函数
string& string(const string& s1){
string tem(s1);
(this)->swap(tem);
}
最简单拷贝构造/赋值重载
cpp
string& string(string s1){
//s1是局部变量直接进行交换
swap(s1);//this->swap(s1);
}
写时拷贝
对于拷贝构造,对自定义类型完成神拷贝,浅拷贝(一个字节一个字节拷贝)并不能满足,原因如下
1.析构两次
2.修改内容时修改两个指针指向的内容
对于写时拷贝只试用满足原因1,并不能满足条件2(自己进行扩容规深拷贝)
string类模拟实现
cpp
string.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace lph {
class string {
public:
typedef char* iterator;
重载无参函数
//string()
// :_str(nullptr)
// ,_size(0)
// ,_capacity(0)
//{}
带参数构造
//string(const char* str) {
// _size = strlen(str);
// _capacity = _size;
// _str = new char[_size + 1];
// strcpy(_str, str);
//}
//迭代器begin使用
iterator begin() {
return _str;
}
//end使用
iterator end() {
return _str + _size;
}
// 全缺省
string(const char* str = "") {
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
//输出
const char* c_str() {
return _str;
}
//获取size大小
size_t size() {
return _size;
}
//获取总空间大小
size_t capacity() {
return _capacity;
}
//循环遍历
char& operator[](size_t pos) {
assert(pos < _size);
return _str[pos];
}
//拷贝构造
string(const string& s) {
_str = new char[s._capacity+1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
//赋值重载
//s1=s2
string& operator=(const string& s) {
delete[] _str;
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
return *this;
}
//扩容
void reserve(size_t n);
//三个尾插
void push_back(char ch);
void append(const char* str);
string& operator+=(char ch);
string& operator+=(const char* str);
~string() {
delete[] _str;
_size = _capacity = 0;
}
//中间插入
void insert(size_t pos, char ch);
void insert(size_t pos, const char* str);
//删除字符
void erase(size_t pos, size_t len);
//查找指定字符
size_t find(char ch, size_t pos = 0);
//查找指定字串
size_t find(const char* str, size_t pos);
//从某个位置获取多长的字符
string substr(size_t pos, size_t len);
private:
char* _str;
size_t _size;
size_t _capacity;
};
void test1();
void test2();
void test3();
//比较函数实现
bool operator<(string& s1, string& s2);
bool operator<=(string& s1, string& s2);
bool operator>(string& s1, string& s2);
bool operator>=(string& s1, string& s2);
bool operator==(string& s1, string& s2);
bool operator!=( string& s1, string& s2);
}
cpp
string.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"string.h"
namespace lph {
void test1() {
cout << "::test1::" << endl;
string s1;
string s2("hello world");
cout << s1.c_str() << endl;
cout << s2.c_str() << endl;
cout << s2.size() << endl;
cout << s2.capacity() << endl;
cout << s2[6] << endl;
//普通遍历
for (size_t i = 0; i < s2.size(); i++) {
cout << s2[i];
}
cout << endl;
//for遍历
for (auto ch : s2) {
cout << ch;
}
cout << endl;
//迭代器遍历
string::iterator it = s2.begin();
while (it != s2.end()) {
cout << *it;
it++;
}
cout << endl;
cout << endl;
cout << endl;
cout << endl;
}
void test2() {
cout << "::test2::" << endl;
string s1("hello world");
s1.push_back('x');
cout << s1.c_str() << endl;
s1 += 'p';
cout << s1.c_str() <<endl;
string s2("hello world");
s2 += " lvpanhao";
cout << s2.c_str() <<endl;
//头插
cout << "::test::" << endl;
string s3("hello world");
s3.insert(5, 'x');
cout << s3.c_str() <<endl;
string s4("hello world");
s4.insert(5, "@@@@@");
cout << s4.c_str() << endl;
cout << "::test::" << endl;
string s5("hello world");
s5.erase(5, 10);
cout << s5.c_str() << endl;
string s6("hello world");
s6.erase(5, 3);
cout << s6.c_str() << endl;
}
void test3() {
string s1("hello world");
cout << s1.find('o',0) << endl;
string s2("hello lvpanhao world");
string s= s2.substr(6,8);
cout << s.c_str() << endl;
string copy(s2);
cout << copy.c_str() << endl;
string s3=(copy = s);
cout << s3.c_str() << endl;
string s4("hello");
string s5("woshi");
cout << (s4 < s5) << endl;
cout << (s4 == s5) << endl;
cout << (s4 > s5) << endl;
//拷贝构造
string s6("lvpanhao");
string s7("nihao");
string s8(s6);
cout << s8.c_str() << endl;
//赋值重载
s6=s7;
cout << s6.c_str() << endl;
}
void string::reserve(size_t n) {
if (n > _capacity) {
char* tem = new char[n + 1];
strcpy(tem, _str);
delete[] _str;
_str = tem;
_capacity = n;
}
}
void string::push_back(char ch) {
//扩容
if (_size == _capacity) {
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
_str[_size] = ch;
_size++;
_str[_size] = '\0';
}
string& string::operator+=(char ch) {
push_back(ch);
return *this;
}
void string::append(const char* str) {
//扩容
size_t len = strlen(str);
if (len + _size > _capacity) {
reserve(len + _size > 2 * _capacity ? len + _size : 2 * _capacity);
}
strcpy(_str + _size, str);
_size += len;
}
string& string::operator+=(const char* str) {
append(str);
return *this;
}
//中间插入
void string::insert(size_t pos, char ch) {
if (_size == _capacity) {
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
size_t end = _size + 1;
while (end >= pos) {
_str[end] = _str[end - 1];
end--;
}
_str[pos] = ch;
_size+=1;
}
void string::insert(size_t pos, const char* str) {
assert(pos < _size);
size_t len = strlen(str);
if (_size + len > _capacity) {
//扩容
reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);
}
size_t end = _size + len;
while (end >= pos + len) {
_str[end] = _str[end - len];
end--;
}
for (size_t i = 0; i < len; i++) {
_str[pos++] = str[i];
}
_size += len;
}
//删除字符
void string::erase(size_t pos, size_t len) {
if (len > _size - pos) {
_str[pos] = '\0';
_size = pos;
}
else {
for (size_t i = pos + len; i <= _size; i++) {
_str[pos++] = _str[i];
}
_size -= len;
}
}
//查找指定字符
size_t string::find(char ch, size_t pos) {
for (size_t i = pos; i < _size; i++) {
if (ch == _str[i]) {
return i;
}
}
return -1;
}
//查找指定字串
size_t string::find(const char* str, size_t pos) {
assert(pos < _size);
char* ptr = strstr(_str+pos, str);
if (ptr == nullptr) {
return -1;
}
else {
return ptr - _str;
}
}
//从某个位置获取多长的字符
string string::substr(size_t pos, size_t len) {
assert(pos < _size);
if (len > _size - pos) {
len = _size - pos;
}
string sub;
sub.reserve(len);
for (size_t i = 0; i < len; i++) {
sub += _str[pos + i];
}
return sub;
}
//比较函数实现
bool operator<(string& s1, string& s2) {
return strcmp(s1.c_str(), s2.c_str())<0;
}
bool operator<=( string& s1, string& s2) {
return (s1 < s2) || (s1 == s2);
}
bool operator>( string& s1,string& s2) {
return !(s1 <= s2);
}
bool operator>=(string& s1, string& s2) {
return !(s1 < s2);
}
bool operator==(string& s1,string& s2) {
return strcmp(s1.c_str(), s2.c_str()) == 0;
}
bool operator!=(string& s1,string& s2) {
return !(s1 == s2);
}
//自定义插入
ostream& operator<<(ostream& out, string& s) {
for (auto ch : s) {
out << ch;
}
return out;
}
istream& operator>>(istream& ci, string& s) {
char ch;
//ci >> ch;//遇到空格或换行会默认未字符串
ch = ci.get();
while (ch != ' ' || ch != '\0') {
s += ch;
//ci >> ch;
ch = ci.get();
}
return ci;
}
}
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"string.h"
int main() {
lph::test1();
lph::test2();
lph::test3();
return 0;
}