1 string容器
C风格字符串(以空格符结尾的字符数组)太过复杂,不适合大程序开发,所以C++标准库定义了一种string类。
C++的字符串与C语言的字符串比较:
- C语言:char*是一个指针。
- C++:
- string是一个类,内部封装了char*,用来管理这个容器。
- string类中封装了很多的功能函数,例如:find、copy、delete、replace、insert等。
- 不用考虑内存释放和越界的问题。
string管理char*所分配的内存。每一个string的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。
1.1 string容器的构造
// string构造
void test1(){
// 无参构造,创建一个空字符串
string str1; // 等于string str = string();
//通过一个string去构造另一个string
string str2 = string("hello world");
//通过一个char(字符)数组去构造一个string
const char* array = "hello world";
string str3 = string(array);
// 通过指定数量的指定字符,构造一个字符串
string str4 = string(5,'A'); // 内容是:AAAAA
};
1.2 string的赋值
// string赋值
void test2(){
string str1;
// 通过等号赋值,等号已经被string进行了运算符重载
// 通过字符串赋值
str1 = "hello world";
// 通过字符数组赋值
const char* arr = "abc";
str1 = arr;
// 通过字符赋值
str1 = 'a';
// assign函数。都是&引用,即可以链式操作。
str1.assign("hello world");
str1.assign(arr);
str1.assign(5,'A');
// string& assign(const char* s, int n); 把字符串s的前n个字符赋值给string
str1.assign("hello world",5);
cout << str1 << endl;
// string& assign(const char* s, int start, int n); 将s从start开始n个字符赋值给字符串
str1.assign("hello world",3,4); // llo w
}
1.3 string存取字符操作
// string的存取字符操作
void test3(){
// 通过下标访问
// char& operator[](int n); 通过[]访问
// char& at(int n); 通过at访问
string str1 = "hello world";
cout << str1[2] << endl;
cout << str1.at(4) << endl;
str1[2] = 'a';
str1.at(4) = 'a';
cout << str1 << endl;
// 使用了&引用(取别名)
// 使用字符引用返回值,存储字符串中指定下标位字符的引用。
char& c = str1[4];
// 修改引用的值,这里引用的是字符串中的字符数组中的指定下标位的元素,所以c改变,数组中也会对应改变。
c = '!';
cout << str1 << endl;
// 注意:
// 一旦字符串中的字符数组内存重新分配了,使用之前的引用再进行空间访问,可能会出现问题。
// 重写分配的情况:c++中,字符串长度小于16位时,空间开辟在栈上,超过16位,重新分配内存。
// c_str: 将C++风格的字符串转换成C风格的字符串(返回的是C++的string类中维护的那个字符数组的指针)
cout << (int*)str1.c_str() << endl; // 原来地址
str1 = "12345678901234"; // 重新赋值,长度未超过16位,不会重新分配内存,地址不发生改变
cout << c << endl; // 输出引用
str1 = "12345678901234567"; // 重新赋值,长度超过16位,会重新分配内存,地址发生改变
cout << (int*)str1.c_str() << endl; // 新地址
// cout << c << endl; //地址改变,引用的c地址已经被释放了
}
1.4 string拼接
// string拼接
void test4(){
string str = "hello";
// +
string str1 = str + "world";
// += 后面跟需要加上的字符或字符串或者字符数组
str += "world";
// append函数
// string& append(const char* s);
str.append("world");
// string& append(const char* s, int n); 把字符串前n个字符拼接到当前字符串结尾
str.append("world",5);
// string& append(const string& str); 把字符串拼接到当前字符串结尾,同 +=
// string& append(const string& str, int start, int n); 把字符串从start开始n个字符拼接到当前字符串结尾
str.append("world",3,4);
// string& append(int n, char c); 把n个字符c拼接到当前字符串结尾
str.append(5,'A');
cout << str << endl;
}
1.5 string查找和替换
// string查找和替换
void test5(){
string str = "hello world! hello1 world1!";
// 查找 find:第一次出现的位置,返回首字符的位置下标
// int find(const string& str, int pos); 从pos位置开始查找字符串str第一次出现的位置,pos默认是0
// int find(const char* s, int pos); 从pos位置开始查找字符串s第一次出现的位置
// int find(const char* s, int pos, int n); 从pos位置开始查找字符串s前n个字符第一次出现的位置
// int find(char c, int pos); 从pos位置开始查找字符c第一次出现的位置
cout << str.find("world") << endl;
cout << str.find("world1", 10) << endl;
cout << str.find("world1", 5, 5) << endl;
cout << str.find('1') << endl;
// 如果找不到,返回-1
cout << str.find("hello2") << endl; //这个却并不是-1
int res = str.find("hello2"); // 现在是-1
cout << res << endl;
// 查找rfind :最后一次出现的位置,从后往前找
// int rfind(const string& str, int pos) const; // 查找字符串str最后一次出现的位置,pos默认最大值
// int rfind(const char* s, int pos, int n) const; // 查找字符串s的前n个字符最后一次出现的位置
// int rfind(const char c, int pos) const; // 查找字符c最后一次出现的位置
cout << str.rfind("world") << endl;
cout << str.rfind("world1", 10) << endl; // 从后往前找,从pos往前找,即从10->0的位置找
// 替换
// string& replace(int start, int n, const string& str); 从start位置开始,删除n个字符,并用字符串str替换
// string& replace(int start, int n, const char* s); 从start位置开始,删除n个字符,并用字符串s替换
cout << str.replace(0,5,"no") << endl; // 返回的是这个string对象本身,即str也会发生改变
cout << str << endl;
}
1.6 string的比较
// string比较
void test6(){
// 字符串大小比较规则:比的是字典顺序(更加深入来说,就是字符在字符集中的映射的数字)
// 依次比较字符串中的每一位字符,如果字符相同,继续比较后面的一位字符,直到某一位的比较可以确定大小关系,返回大小关系
// 仍然可以使用> < >= <= == !=来比较,但是有一定局限性。
// 局限性:比较结果是bool类型,无法充足的表示每一种比较结果(大于,小于,等于)。
// 因此string提供了compare函数,返回一个int类型:
// 0:相等;
// 1:str1大于str2;
// -1:str1小于str2
string str1 = "abe";
string str2 = "abc";
cout << str1.compare(str2) << endl;
}
1.7 string的子串获取
// string子串的获取
void test7(){
// pos:起始下标,从pos开始获取子串,默认0,不要越界,越界报错。
// n:长度,获取多少个字符,可以越界,将剩余的字符串全部获取。
// string substr(int pos, int n) const; // 返回从pos开始的n个字符组成的新字符串
string str = "hello world";
cout << str.substr(0,5) << endl;
cout << str.substr(6) << endl;
cout << str.substr(6,20) << endl;
cout << str << endl; // 不会对原字符串产生影响
}
1.8 string的插入和删除
// string的插入和删除
void test8(){
// string& insert(int pos, const char* s); // 在pos位置插入字符串s
// string& insert(int pos, const string& str); // 在pos位置插入字符串str
// string& insert(int pos, int n, char c); // 在pos位置插入n个字符c
// string& erase(int pos, int n = npos); // 删除从pos开始的n个字符,默认所有npos
string str = "hello world";
str.insert(0,"123");
cout << str << endl;
str.insert(1,"123",2); // 在第1个位置开始,插入字符串的前两个字符
cout << str << endl;
str.insert(1,"123456",3,2); // 在第1个位置,插入字符串的从第3个字符开始的2个字符
cout << str << endl;
// 删除
str.erase(0,5);
cout << str << endl;
}