目录
一 概念
二 常见构造
三 string类对象的容量操作
1 size 和 length
2 capacity
3 reverse
4 resize
5 clear
6 empty
四 string类对象的访问及遍历操作
1 operator [ ]
2 begin + end
3 rbegin + rend
4 范围for
五 string类对象的修改操作
1 push_back
2 append
3 operator+=
4 insert
5 erase
6 replace
7 swap
8 pop_back
六 string其他操作
1 c_str
2 find
3 rfind
4 find_first_of + find_last_of
5 find_first_not_of + find_last_not_of
6 substr
七 string补充
1 getline
2 to_string
3 stoi
C++/C++11中std::string是个模板类,它是一个标准库。使用string类型必须首先包含
std::string是C++中的字符串。字符串对象是一种特殊类型的容器,专门设计来操作字符序列
int main()
{
string s1; //空字符串
string s2("hello world");// 构造string类对象
string s3(10, 'x');//包含n个字符
string s4 = s2;//拷贝构造
string s5(s2);//拷贝构造
string s6 = "hello string";//隐形转换
const string& s7 = "hello const string";//临时对象具有常属性
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
cout << s4 << endl;
cout << s6 << endl;
cout << s7 << endl;
//这些类是可以改变的
s1 = s2;
cout << s1 << endl;
s1 = "world";
cout << s1 << endl;
s1 = 'x';
cout << s1 << endl;
return 0;
}
size_t size() const;
size_t length() const;
size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()
int main()
{
string s1("hello world");
cout << s1.size() << endl;
cout << s1.length() << endl;
return 0;
}
输出结果: 11 11
size_t capacity() const;
int main()
{
string str("Test string");
cout << "size: " << str.size() << "\n";
cout << "length: " << str.length() << "\n";
cout << "capacity: " << str.capacity() << "\n";
return 0;
}
void reserve (size_t n = 0);
为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。(只影响容量, 不影响数据)
int main()
{
string s1("hello world");
cout << s1.capacity() << endl;
s1.reserve(500);//需要多少空间, 提前开好
cout << s1.capacity() << endl;
s1.reserve(100);//在vs2022下 空间容量不会缩小
cout << s1.capacity() << endl;
return 0;
}
void resize (size_t n);
void resize (size_t n, char c);
resize(size_tn) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用\0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。
既影响容量 也影响数据
int main()
{
string s1("hello world");
cout << s1.size() << endl;
cout << s1.capacity() << endl;
cout << s1 << '\n' << endl;
// > capacity --> 扩容+尾插
//s1.resize(100);
s1.resize(100, 'x');
cout << s1.size() << endl;
cout << s1.capacity() << endl;
cout << s1 << '\n' << endl;
// size < n < capacity -> 尾插
string s2("hello world");
cout << s2.size() << endl;
cout << s2.capacity() << endl;
cout << s2 << endl;
s2.resize(12);
cout << s2.size() << endl;
cout << s2.capacity() << '\n' << endl;
// n < size -> 删除数据,保留前n个
string s3("hello world");
cout << s3.size() << endl;
cout << s3.capacity() << endl;
cout << s3 << endl;
s3.resize(5);
cout << s3 << endl;
cout << s3.size() << endl;
cout << s3.capacity() << '\n' << endl;
string s5;
s5.resize(100, '#');
cout << s5 << endl;
return 0;
}
void clear();
将string中有效字符清空,不改变底层空间大小。
int main()
{
string s("hello world");
cout << s.size() << endl;
cout << s.capacity() << endl;
s.clear();
cout << s << endl;
cout << s.size() << endl;
cout << s.capacity() << endl;
return 0;
}
bool empty() const;
返回字符串是否为空(即其长度是否为 0)。
int main()
{
string s("hello world");
cout << s.empty() << endl;
s.clear();
cout << s.empty() << endl;
return 0;
}
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
int main()
{
//operator []
string s1("hello world");
for (size_t i = 0; i < s1.size(); i++)
{
cout << s1[i] << " ";
//底层是这样-->cout << s1.operator[](i) << " "
}
cout << endl;
s1[0] = 'x';
cout << s1 << endl;
}
补充:
字符串中元素的访问是允许的,一般可使用两种方法访问字符串中的单一字符:下标操作符[] 和 成员函数at()。
两者均返回指定的下标位置的字符。第 1 个字符索引(下标)为 0,最后的字符索引为 length()-1。
需要注意的是,这两种访问方法是有区别的:
下标操作符 [] 在使用时不检查索引的有效性,如果下标超出字符的长度范围,会示导致未定义行为。对于常量字符串,使用下标操作符时,字符串的最后字符(即 '\0')是有效的。对应 string 类型对象(常量型)最后一个字符的下标是有效的,调用返回字符 '\0'。
函数 at() 在使用时会检查下标是否有效。如果给定的下标超出字符的长度范围,系统会抛出 out_of_range 异常。
int main()
{
try
{
string s1("hello world");
cout << s1.at(10) << endl;
cout << s1.at(11) << endl;
}
catch (const exception& e)
{
cout << e.what() << endl;
}
return 0;
}
下标操作符 [] 和函数 at() 均返回字符的“引用”
iterator begin(); const_iterator begin() const;
iterator end(); const_iterator end() const;
begin()函数返回一个迭代器,指向字符串的第一个元素
end()函数返回一个迭代器,指向字符串的末尾(最后一个字符的下一个位置)
int main()
{
string s1("hello world");
// iterator用法像指针
string::iterator it = s1.begin();
while (it != s1.end())// s.end()指向'\0'
{
cout << *it << " ";
++it;
}
cout << endl;
reverse(s1.begin(), s1.end());//左闭右开区间
cout << s1 << endl;
const string s2("hello world");
s1[0] = 'x';
//s2[0] = 'x' --> error
cout << s1 << endl;
//遍历s2
string::const_iterator itt = s2.begin();
while (itt != s2.end())
{
cout << *itt << " ";
++itt;
}
}
const_iterator it 本质保护迭代器指向的数据 *it不能修改
const iterator it 包含的迭代器本身不能修改 it不能修改 不符合我们的需求
对于迭代器可以遍历顺序表, 链表, 栈等数据结构
reverse_iterator rbegin(); const_reverse_iterator rbegin() const;
reverse_iterator rend(); const_reverse_iterator rend() const;
rbegin()返回一个逆向迭代器,指向字符串的最后一个字符。
rend()函数返回一个逆向迭代器,指向字符串的开头(第一个字符的前一个位置)
void func(const string& s)
{
string::const_reverse_iterator it = s.rbegin();
while (it != s.rend())
{
cout << *it << " ";
++it;
}
cout << endl;
}
int main()
{
string s1("hello world");
string::reverse_iterator it1 = s1.rbegin();
while (it1 != s1.rend())
{
cout << *it1 << " ";
++it1;
}
cout << endl;
func(s1);
return 0;
}
int main()
{
string s1("hello world");
for (auto e : s1)
{
cout << e << " ";
}
cout << endl;
return 0;
}
void push_back (char c);
将字符附加到字符串
int main()
{
string s1("hello");
s1.push_back('#');
cout << s1 << endl;
return 0;
}
//输出 hello#
string& append(const string& str);
string& append(const string& str, size_t subpos, size_t sublen);
string & append(const char* s);
string& append(const char* s, size_t n);
string& append(size_t n, char c);
string s1("123"), s2("abc");
s1.append(s2); // s1 = "123abc"
s1.append(s2, 1, 2); // s1 = "123abcbc"
s1.append(3, 'K'); // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3); // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)
int main()
{
string s1("hello");
s1.push_back(' ');
s1.append("world");
cout << s1 << endl;
string s2 = "xxxx";
s2.append(s1);
cout << s2 << endl;
s2.append(++s1.begin(), --s1.end());
cout << s2 << endl;
return 0;
}
string& operator+= (const string& str);
string & operator+= (const char* s);
string& operator+= (char c);
int main()
{
string s1("hello");
string s2("world");
string ret1 = s1 + s2;
cout << ret1 << endl;
string ret2 = s1 + "xx";
cout << ret2 << endl;
string ret3 = "xx" + s1;
cout << ret3 << endl;
string ret4 = 'a' + s1;
cout << ret4 << endl;
return 0;
}
string& insert (size_t pos, const string& str);
string& insert (size_t pos, const char* s);
string& insert (size_t pos, const char* s, size_t n);
string& insert (size_t pos, size_t n, char c);
insert 成员函数可以在 string 对象中插入(头插)另一个字符串,返回值为对象自身的引用
int main()
{
string s1("Limitless"), s2("00");
s1.insert(2, "123");//在p0位置插入字符串
cout << s1 << endl;
s1.insert(3, s2);
cout << s1 << endl;
s1.insert(3, 5, 'X');//在p0位置插入n个字符
cout << s1 << endl;
s1.insert(3, "abc", 2);//在p0位置插入字符串前两个字符
cout << s1 << endl;
return 0;
}
sequence(1)
string& erase(size_t pos = 0, size_t len = npos);character(2)
iterator erase(const_iterator p);range(3)
iterator erase(const_iterator first, const_iterator las
三种用法:
(1)erase(pos, n); 删除从pos开始的n个字符,比如erase(0, 1)就是删除第一个字符
(2)erase(position); 删除position处的一个字符(position是个string类型的迭代器)
(3)erase[first, last); 删除从first到last之间的字符(first和last都是迭代器)
int main()
{
string s1("hello world");
s1.erase(9, 1);
cout << s1 << endl;
s1.erase(4);//不指明n, 默认把4位置(包括4位置)后面所有的删除
cout << s1 << endl;
s1.erase(s1.begin());
cout << s1 << endl;
s1.erase(s1.begin(), s1.end() - 1);
cout << s1 << endl;
return 0;
}
替换字符串中以字符 pos 开头的部分,并替换跨越len 字符
string& replace (size_t pos, size_t len, const string& str);
string& replace (iterator i1, iterator i2, const string& str);
int main()
{
string s1("hello world hello yf");
cout << s1 << endl;
s1.replace(5, 2, "abc");//s1 pos位置开始往后2个位置被abc覆盖
cout << s1 << endl;
return 0;
}
void swap (string& str);
int main()
{
string s2("hello world");
string s3("yf");
s2.swap(s3);
cout << s2 << endl;
cout << s3 << endl;
return 0;
}
尾删
void pop_back();
int main()
{
string s2("hello world hello yf");
s2.pop_back();
cout << s2 << endl;
return 0;
}
const char* c_str() const;
c_str()是封装的String类中的一个函数,它返回当前字符串的首字符地址。换种说法,c_str()函数返回一个指向正规C字符串的指针常量,内容与本string串相同。这是为了与C语言兼容,在C语言中没有string类型,故必须通过string类对象的成员函数c_str()把string对象转换成C中的字符串样式。
注意:一定要使用strcpy()等函数来操作c_str()返回的指针
int main()
{
char* c;
string s = "1234";
c = s.c_str();// --> error
//c最后指向的内容是垃圾,因为s对象被析构,其内容被处理,同时编译器将会报错
return 0;
}
改正如下
int main()
{
char* cstr;
string str("Please split this phrase into tokens");
cstr = new char[str.size() + 1];
strcpy(cstr, str.c_str());
cout << cstr << endl;
}
size_t find(const string& str, size_t pos = 0) const;
size_t find(const char* s, size_t pos = 0) const;
size_t find(const char* s, size_t pos, size_t n) const;
size_t find(char c, size_t pos = 0) const;
string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos。(返回值可以看成是一个int型的数)(从前向后找)
int main()
{
string s1("hello world");
string s2("world");
cout << s1 << endl;
//1.从下标0位置开始找字符
size_t pos1 = s1.find(' ', 0);
cout << pos1 << endl;
//2.从下标0位置找字符串
size_t pos2 = s1.find("world", 0);
cout << pos2 << endl;
//3.从下标0位置找string
size_t pos3 = s1.find(s2, 0);
cout << pos3 << endl;
//从下标0位置开始找s前n个的字符串
size_t pos4 = s1.find("woaaa", 0, 2);
cout << pos4 << endl;
return 0;
}
查找字符串中最后一次出现的内容(从后向前找)
size_t rfind(const string& str, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos, size_t n) const;
size_t rfind(char c, size_t pos = npos) const;
int main()
{
string s1("hello world world");
cout << s1.size() << endl;
string s2("world");
//1.从下标5位置往前开始找字符
size_t pos1 = s1.rfind(' ', 5);
cout << pos1 << endl;
//2.从下标最后一个元素位置往前找字符串
size_t pos2 = s1.rfind("world");
cout << pos2 << endl;
//3.从下标最后一个元素位置往前找string
size_t pos3 = s1.rfind(s2);
cout << pos3 << endl;
//从下标16位置开始往前找s前n个的字符串
size_t pos4 = s1.rfind("woaaa", 16, 2);
cout << pos4 << endl;
return 0;
}
size_t find_first_of(const string& str, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos, size_t n) const;
size_t find_first_of(char c, size_t pos = 0) const;size_t find_last_of(const string& str, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos, size_t n) const;
size_t find_last_of(char c, size_t pos = npos) const;
在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。
在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。
int main()
{
string s("hello world hello yf");
cout << "lenth == " << s.size() << endl;
//找l或者l 第一次出现的位置
size_t pos1 = s.find_first_of("ll");
cout << pos1 << endl;
//找l或者o 第一次出现的位置
size_t pos2 = s.find_first_of("lo");
cout << pos2 << endl;
//找l或者o 最后一次出现的位置
size_t pos3 = s.find_last_of("lo");
cout << pos3 << endl;
//从下标5往前找
size_t pos4 = s.find_last_of('o', 5);
cout << pos4 << endl;
return 0;
}
在字符串中搜索与其参数中指定的任何字符都不匹配的第一个字符。
在字符串中搜索与其参数中指定的任何字符都不匹配的最后一个字符。
size_t find_first_not_of(const string& str, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos, size_t n) const;
size_t find_first_not_of(char c, size_t pos = 0) const;size_t find_last_not_of(const string& str, size_t pos = npos) const;
size_t find_last_not_of(const char* s, size_t pos = npos) const;
size_t find_last_not_of(const char* s, size_t pos, size_t n) const;
size_t find_last_not_of(char c, size_t pos = npos) const;
int main()
{
string s("hello world hello yf");
cout << "lenth == " << s.size() << endl;
//找第一次不是 l 或者 l 的位置
size_t pos1 = s.find_first_not_of("ll");
cout << pos1 << endl;
//找第一次不是 l 或者 o 的位置
size_t pos2 = s.find_first_not_of("lo");
cout << pos2 << endl;
//找最后一次不是 l 或者 o 的位置
size_t pos3 = s.find_last_not_of("lo");
cout << pos3 << endl;
//从下标5往前找
size_t pos4 = s.find_last_not_of('o', 5);
cout << pos4 << endl;
return 0;
}
find 和find_first_of find_last_of find_first_not_of find_last_not_of 的共同点:
查找成功时返回所在位置,失败返回string::npos的值,string::npos一般是MAX_INT(即2^32 - 1)
不同点:
find(): 查找字符串中第一次出现字符c、字符串s的位置;
find_first_of()等: 查找字符串中字符c、字符数组s中任意一个字符出现的位置。
string substr (size_t pos = 0, size_t len = npos) const;
返回一个新构造的对象,其值初始化为此对象的子字符串的副本
int main()
{
string s("hello world");
size_t pos = s.find("world");
cout << pos << endl;
string sub = s.substr(pos);
cout << sub << endl;
return 0;
}
输入字符串 但是有空格的时候
当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。以下面的语句为例:
int main()
{
string s;
getline(cin, s);
cout << s << endl;
size_t pos = s.rfind(' ');
if (pos != string::npos)
{
cout << s.size() - pos - 1 << endl;
}
else
{
cout << s.size() << endl;
}
return 0;
}
返回表示为 val 的字符串
int main()
{
string s1 = to_string(123);
string s2 = to_string(100.1111);
cout << s1 << endl;
cout << s2 << endl;
return 0;
}
补充:
对于将数字转换为字符串来说
可以用 itoa
char * itoa ( int value, char * str, int base )
int main()
{
int i;
char buffer[33];
printf("Enter a number: ");
scanf("%d", &i);
itoa(i, buffer, 10);
printf("decimal: %s\n", buffer);
itoa(i, buffer, 16);
printf("hexadecimal: %s\n", buffer);
itoa(i, buffer, 2);
printf("binary: %s\n", buffer);
return 0;
}
输出:
Enter a number: 1750
decimal: 1750
hexadecimal: 6d6
binary: 11011010110 |
解析 str 并将其内容解释为指定基数的整数,该整数作为 int 值返回.
int main()
{
string s1("123");
string s2("100.11111");
int ret1 = stoi(s1);
int ret2 = stoi(s2);
cout << ret1 << endl;
cout << ret2 << endl;
return 0;
}
补充:
对于字符串的话 可以用aoti
int atoi (const char * str)
分析 C 字符串,将其内容解释为整数,该整数作为 类型的值返回
本节的内容很多, 但是难度不大, 根据代码很容易上手, 但是STL的string的某些设计还是有些缺陷的, 会感觉要记住的很多, 我觉得不用全部去记, 记住肯定是记不住的, 把本节写到的这些记住就可以了, 因为其他没讲到的我们实际当中也不怎么会用, 要用的时候再去查一下也无妨, 我们最主要的是理解用法就可以了.
继续加油!