引言
在 C++ 中,std::string 提供了丰富的成员函数来访问和修改字符串中的字符。通过这些函数,程序员可以灵活地处理字符串中的各个元素,无论是读取特定位置的字符,还是修改字符串的内容。此外,std::string 类还确保了访问的安全性和高效性,例如提供边界检查的函数以防止非法操作。理解这些元素访问与修饰的函数,是编写健壮、灵活的字符串操作代码的基础。
1.string类的元素访问函数
std::string类提供了多种元素访问函数,用来访问或修改字符串中的单个字符,主要的访问函数如下:
1.1 at() 与 front()
1.1.1 at()
at() 用于通过索引(也称下标)访问字符串中的字符。与 operator[] 不同,at()执行边界检查,如果索引超出范围,会抛出 std::out_of_range 异常,从而提高了操作的安全性。
(1)函数原型
char& at (size_t pos);
const char& at (size_t pos) const;
- 通过索引 pos 访问字符串中的字符。
- 如果索引合法,返回对应位置的字符引用。
- 如果索引超出范围,抛出 out_of_range 异常。
(2)示例代码
#include <iostream>
using namespace std;
int main()
{
string str = "Hello";
// 安全地访问字符串中的字符
try
{
str.at(1) = 'a'; // 修改字符
cout << str << endl; // 输出 "Hallo"
// 尝试访问越界的字符,抛出异常
cout << str.at(10) << endl;
}
catch (const out_of_range& e)
{
cerr << "Exception: " << e.what() << endl;
}
return 0;
}
(3)优缺点
优点:提供了边界检查,防止索引超出字符串长度时导致未定义行为。适用于需要严格检查的场景,尤其是在用户输入或动态索引时。
缺点:较 operator[] 稍慢,因为多了一步边界检查。
1.1.2 operator[] (下标操作符)
operator[] 是 std::string 类中的下标操作符,用于通过索引访问字符串中的字符。
(1)函数原型
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
- 它提供了两种形式:非常量版本可以修改字符串中的字符,常量版本则只能读取字符。
- 与 at() 不同,operator[]不执行边界检查,因此如果访问越界会导致未定义行为。
(2)示例代码
#include <iostream>
using namespace std;
int main()
{
string s1 = "Hello";
const string s2 = "henu";
cout << s1[1] << endl;//e
s1[1] = 'a';
//s2[2] = 'a';//报错,表达式必须是可修改的左值
cout << s1 << endl;//Hallo
return 0;
}
(3)注意事项:
- operator[] 的效率很高,因为它不进行边界检查。
- 如果需要更安全的操作,建议使用 at() 函数,它会抛出异常处理越界问题。
1.3 front() 与 back()
(1)front
front()用于返回对字符串的第一个字符的引用。非常量版本可修改字符,常量版本只能读取字符。
只能在非空字符串上调用,如果字符串为空,行为未定义。
char& front();
const char& front() const;
#include <iostream>
using namespace std;
int main()
{
string s1 = "Hello";
const string s2 = "henu";
cout << s1.front() << endl;//H
cout << s2.front() << endl;//h
s1.front() = 'L';
cout << s1.front() << endl;//L
return 0;
}
(2)back()
back()用于返回对字符串的第一个字符的引用。非常量版本可修改字符,常量版本只能读取字符。
只能在非空字符串上调用,如果字符串为空,行为未定义。
char& back(); // 非常量版本,可修改字符
const char& back() const; // 常量版本,只能读取字符
#include <iostream>
using namespace std;
int main()
{
string str = "Hello";
// 访问最后一个字符
cout << str.back() << endl; // 输出 'o'
// 修改最后一个字符
str.back() = '!';
cout << str << endl; // 输出 "Hell!"
return 0;
}
总结:
- operator[] 和 at():按索引访问字符串中的字符,at() 提供边界检查。
- front() 和 back():用于访问或修改字符串的第一个和最后一个字符。
这些访问函数提供了灵活的操作方式,既可以修改字符串内容,也可以确保访问的安全性。
2.string类的修饰函数
2.1 append()
- 功能:append()用于将字符串或其他类型的数据追加到当前字符串对象的末尾。
- 重载形式:append()有多种重载形式,可以追加不同的数据类型,包括C风格字符串、std::string对象、字符数组的指定子串等。
- 返回值:返回对修改后的字符串对象的引用(this),因此可以进行链式调用。
(1)函数原型
string (1) string& append (const string& str);
substring (2) string& append (const string& str, size_t subpos, size_t sublen);
c-string (3) string& append (const char* s);
buffer (4) string& append (const char* s, size_t n);
fill (5) string& append (size_t n, char c);
range (6) template <class InputIterator>
string& append (InputIterator first, InputIterator last);
initializer list(7) string& append (initializer_list<char> il);
(2)深入解析
1. string& append (const string& str)
将整个字符串 str 追加到当前字符串末尾。
string s1 = "Hello ";
string s2 = "henu";
s1.append(s2);
cout << s1 << endl;//Hello henu
cout << s2 << endl;//henu
2. string& append (const string& str, size_t subpos, size_t sublen)
从字符串 str subpos位置的字符开始sublen个字符,追加到当前字符。
string s1 = "Hello ";
string s2 = "henu";
s1.append(s2, 0, 2);
cout << s1 << endl;//Hello he
cout << s2 << endl;//henu
3. string& append (const char* s)
将 C 风格的字符串 s 追加到当前字符串。
string s1 = "Hello ";
s1.append("world");
cout << s1 << endl;//Hello world
4. string& append (const char* s, size_t n)
将 C 风格字符串 s 的前 n 个字符追加到当前字符串。
string s1 = "Hello ";
s1.append("world!!!", 6);
cout << s1 << endl;//Hello world!
5.string& append (size_t n, char c)
将 n 个字符 c 追加到当前字符串。
string s1 = "Hello ";
s1.append(5, 'x');
cout << s1 << endl;//Hello xxxxx
6. template <class InputIterator> string& append (InputIterator first, InputIterator last)
将范围 [first, last) 内的元素追加到当前字符串。这可以用于迭代器范围。
string s1 = "Hello ";
string s2 = "henu";
s1.append(s2.begin(), s2.end());
cout << s1 << endl;//Hello henu
7.string& append (initializer_list<char> il)
使用初始化列表追加字符。
string s1 = "Hello ";
s1.append({ 'W', 'o', 'r', 'l', 'd' });
cout << s1 << endl;//Hello World
这些不同形式的append()函数为字符串操作提供了丰富的灵活性,可以根据需求追加整个字符串、子串、字符数组、或者指定范围的字符。
在C++中,std::string类提供了两种常见的方式来将字符串追加到现有字符串:append()函数和operator+=运算符。尽管它们在效果上相似,都用于拼接字符串,但它们在使用上有一些细微差别。
2.2 operator+=
- 功能:operator+=运算符也是用于将字符串或其他数据追加到字符串对象末尾的运算符。它的功能和append()类似,但更加简洁,适合简单的字符串拼接操作。
- 重载形式:它同样支持多种数据类型,包括`std::string`对象、C风格字符串和单个字符等。
- 返回值:与append()一样,operator+=返回修改后的字符串对象的引用(*this),支持链式调用。
(1)函数原型
string (1) string& operator+= (const string& str);
c-string (2) string& operator+= (const char* s);
character (3) string& operator+= (char c);
initializer list (4) string& operator+= (initializer_list<char> il);
(2)深入解析
1. string& operator+= (const string& str)
将 std::string 对象 str 追加到当前字符串的末尾。
string s1 = "Hello ";
string s2 = "henu";
s1 += s2;
cout << s1 << endl;//Hello henu
2. string& operator+= (const char* s)
将C风格字符串 s 追加到当前字符串的末尾。
string s1 = "Hello ";
s1 += " World";
cout << s1 << endl;//Hello World
3. string& operator+= (char c)
将单个字符 c 追加到当前字符串的末尾。
string s1 = "Hello ";
s1 += "!";
cout << s1 << endl;//Hello !
4. string& operator+= (initializer_list<char> il)
将初始化列表中的字符追加到当前字符串的末尾。
string s1 = "Hello ";
s1 += {'W', 'o', 'r', 'l', 'd'}; // str 变为 "Hello World"
cout << s1 << endl;
这些运算符重载使得字符串拼接变得更加方便,简洁地处理不同类型的数据(字符串、字符数组、单个字符等)。
(3)与append()的区别与使用场景:
1. 简洁性:operator+=通常用于简洁的拼接操作,尤其适合简单的字符或字符串拼接;而`append()`可以提供更灵活的重载版本,适合更复杂的场景。
2. 重载灵活性:append()的重载更多,能更精细地控制如何拼接字符串。例如,指定要追加子串的起始位置和长度等。
3. 代码可读性:operator+=运算符在某些情况下代码更简洁、更易读,尤其是单个字符或简单字符串的拼接;而`append()`适合需要明确控制拼接逻辑的场合。
性能方面:
从性能上看,append()和operator+=基本没有明显的差异,除非在某些特定的优化场景下。编译器通常会对这两者进行类似的优化。
2.3 assign()
assign()函数用来将一个新值赋给字符串对象。支持多种重载形式。需要注意的是,assign的作用是赋值而不是拼接,会修改原字符串的内容。
(1)函数原型
string (1)
string& assign (const string& str);
substring (2)
string& assign (const string& str, size_t subpos, size_t sublen);
c-string (3)
string& assign (const char* s);
buffer (4)
string& assign (const char* s, size_t n);
fill (5)
string& assign (size_t n, char c);
range (6)
template <class InputIterator>
string& assign (InputIterator first, InputIterator last);
initializer list(7)
string& assign (initializer_list<char> il)
(2)深入解析
1.string& assign (const string& str)
从另一个字符串赋值
string s1 = "Hello";
string s2 = "henu";
s1.assign(s2);
cout << s1 << endl;//henu
cout << s2 << endl;//henu
2.string& assign (const string& str, size_t subpos, size_t sublen);
赋值部分字符串
string s1 = "Hello";
string s2 = "henu";
s1.assign(s2, 0, 4);
cout << s1 << endl;//henu
3.string& assign (const char* s)
从 C 风格字符串赋值
string s2 = "henu";
s2.assign("Hello World");
cout << s2 << endl;//Hello World
4.string& assign (size_t n, char c)
用指定字符重复赋值
string s1 = "Hello";
s1.assign(5, 'x');
cout << s1 << endl;//xxxxx
5.string& assign (const char* s, size_t n)
从字符指针赋值指定长度的字符串
string s1 = "Hello";
s1.assign("World", 5);
cout << s1 << endl;//World
6.string& assign (InputIterator first, InputIterator last)
使用迭代器赋值
string s1 = "Hello";
string s2 = ", henu";
s1.assign(s2.begin() + 2, s2.end());
cout << s1 << endl;//henu
7.string& assign (initializer_list<char> il)
使用初始化列表为字符串赋值
string str = "Hello";
str.assign({ 'W','o','r','l','d' });
cout << str << endl;//World
assign()函数灵活多样,可以根据不同的需求从字符串、字符指针、部分字符串、重复字符等来赋值给 std::string 对象。
2.4 insert()
insert()用于在字符串中的指定位置插入字符或字符串,注意,这里是插入,插入的字符不会覆盖原来的字符。
(1)函数原型
string (1) string& insert (size_t pos, const string& str);
substring (2) string& insert (size_t pos, const string& str, size_t subpos, size_t
sublen);
c-string (3) string& insert (size_t pos, const char* s);
buffer (4) string& insert (size_t pos, const char* s, size_t n);
fill (5) string& insert (size_t pos, size_t n, char c);
void insert (iterator p, size_t n, char c);
single character (6) iterator insert (iterator p, char c);
range (7) template <class InputIterator>
void insert (iterator p, InputIterator first, InputIterator last);
initializer list (8)
string& insert (const_iterator p, initializer_list<char> il)
(2)深入解析
好的,以下将每个 insert() 的示例分开写出,确保每个示例独立运行,便于理解与复制:
1.string& insert (size_t pos, const string& str)
插入整个字符串
string s1 = "Hello";
string s2 = " henu ";
s1.insert(5, s2);
cout << s1 << endl;//Hello henu
2.string& insert (size_t pos, const string& str, size_t subpos, size_t sublen)
在指定位置插入另一个字符串的的子串,该子串从subpos位置开始插入sublen个字符
string s1 = "Hello";
string s2 = " henu ";
s1.insert(5, s2, 0, 4);
cout << s1 << endl;//Hello hen
3.string& insert (size_t pos, const char* s)
插入 C 风格字符串
string s1 = "Hello";
s1.insert(5, " World");
cout << s1 << endl;//Hello World
4.string& insert (size_t pos, const char* s, size_t n)
插入字符缓冲区
string s1 = "Hello";
const char* but = " World!!!";
s1.insert(5, but, 7);
cout << s1 << endl;//Hello World!
5. string& insert (size_t pos, size_t n, char c);
void insert (iterator p, size_t n, char c)
插入重复字符
string s1 = "Hello";
s1.insert(0, 5, 'x');
s1.insert(s1.end(), 5, 'x');
cout << s1 << endl;//xxxxxHelloxxxxx
6.iterator insert (iterator p, char c)
在迭代器位置插入单个字符
string s1 = "Hello";
s1.insert(s1.begin() + 1, 'a');
cout << s1 << endl;//Haello
7. void insert (iterator p, InputIterator first, InputIterator last)
插入范围
string s1 = "代码";
string s2 = "编写";
s1.insert(s1.begin() + 2, s2.begin(), s2.end());
cout << s1 << endl;//代码编写
8. initializer list (8)
string& insert (const_iterator p, initializer_list<char> il)
通过初始化列表在字符串的指定位置插入一组字符
string str = "Hello, ";
str.insert(str.begin() + 7, { 'W','o','r','l','d' });
cout << str << endl;//Hello, World
2.5 replace()
replace用于替换字符串中的某些字符或字符串。
(1)函数原型
string (1)
string& replace (size_t pos, size_t len, const string& str);
string& replace (iterator i1, iterator i2, const string& str);
substring (2)
string& replace (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen);
c-string (3)
string& replace (size_t pos, size_t len, const char* s);
string& replace (iterator i1, iterator i2, const char* s);
buffer (4)
string& replace (size_t pos, size_t len, const char* s, size_t n);
string& replace (iterator i1, iterator i2, const char* s, size_t n);
fill (5)
string& replace (size_t pos, size_t len, size_t n, char c);
string& replace (iterator i1, iterator i2, size_t n, char c);
range (6)
template <class InputIterator>
string& replace (iterator i1, iterator i2,InputIterator first, InputIterator last);
initializer list (7)
string& replace (const_iterator i1, const_iterator i2, initializer_list<char> il);
(2) 深入解析
1.替换字符串
string& replace (size_t pos, size_t len, const string& str);
string& replace (iterator i1, iterator i2, const string& str);
string s1 = "Hello, henu";
string s2 = "World";
s1.replace(7, 4, s2);//s1从索引为7的字符开始后的4个字符用s2替换
cout << s1 << endl;//Hello, World
s1.replace(s1.begin(), s1.end(), s2);
cout << s1 << endl;//World
2.替换子字符串
string& replace (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen);
string s1 = "Hello, henu";
string s2 = "World";
s1.replace(7, 4, s2, 1, 4);
cout << s1 << endl;//Hello, orld
3. 替换C风格字符串
string& replace (size_t pos, size_t len, const char* s);
string& replace (iterator i1, iterator i2, const char* s);
string s1 = "Hello, henu";
s1.replace(7, 4, "World");
cout << s1 << endl;//Hello, World
s1.replace(s1.begin() + 7, s1.end(), "henu");
cout << s1 << endl;//Hello, henu
4.替换缓冲区的指定字符数
string& replace (size_t pos, size_t len, const char* s, size_t n);
string& replace (iterator i1, iterator i2, const char* s, size_t n);
string s1 = "Hello, henu";
const char* s2 = "World";
s1.replace(7, 4, s2, 4);//用s2的前四个字符替换
cout << s1 << endl;//Hello, Worl
s1.replace(s1.begin() + 7, s1.end(), "henu", 4);
cout << s1 << endl;//Hello, henu
5.用字符填充
string& replace (size_t pos, size_t len, size_t n, char c);
string& replace (iterator i1, iterator i2, size_t n, char c);
string s1 = "Hello, henu";
s1.replace(7, 4, 5, 'x');
cout << s1 << endl;//Hello, xxxxx
s1.replace(s1.begin() + 7, s1.end(), 4, 'a');
cout << s1 << endl;//Hello, aaaa
6.替换范围
template <class InputIterator>
string& replace (iterator i1, iterator i2,InputIterator first, InputIterator last);
string s1 = "Hello, henu";
string s2 = "World";
s1.replace(s1.begin() + 7, s1.end(), s2.begin(), s2.end());
cout << s1 << endl;//Hello, World
7.用初始化列表替换
initializer list (7)
string& replace (const_iterator i1, const_iterator i2, initializer_list<char> il);
string str = "Hello, henu";
str.replace(str.begin() + 7, str.end(), {'W','o','r','l','d'});
cout << str << endl;//Hello, World
2.6其它成员函数
(1)push_back()
push_back用于添加字符到字符串的末尾,是字符串的长度加一
void push_back (char c);
#include <iostream>
using namespace std;
int main()
{
string s1 = "Hello, hen";
s1.push_back('u');
cout << s1 << endl;//Hello, henu
return 0;
}
(2)pop_back()
pop_back用来删除字符串最后一个字符,字符串长度减一
void pop_back();
#include <iostream>
using namespace std;
int main()
{
string s1 = "Hello, henua";
s1.pop_back();
cout << s1 << endl;//Hello, henu
return 0;
}
通过对 C++ std::string 类的访问函数和修饰函数的深入了解,我们可以更灵活、有效地处理字符串操作。在编程实践中,选择合适的函数不仅能提高代码的可读性,还能提升程序的执行效率。掌握这些字符串操作的方法,能够帮助我们在应对复杂的字符串处理需求时游刃有余。
更多string成员函数:string::find - C++ Reference (cplusplus.com)