本篇的内容是记录使用string接口的测试与使用,方便后续使用时查阅使用
首先介绍
string::npos;
size_t(无符号整型)的最大值。NPOS 是一个静态成员常量值,具有 size_t 类型元素的最大可能值。当此值用作字符串成员函数中 len(或 sublen)参数的值时,表示“直到字符串末尾”。作为返回值,它通常用于指示不匹配。此常量使用值 -1 定义,由于 size_t 是无符号整数类型,因此它是此类型的最大可能可表示值。
引用头文件和展开命名空间
#include<iostream>
#include<string>
using namespace
1.测试string容量相关的接口:
1.1 string::size()
size_t size() const;
字符串的返回长度返回字符串的长度(以字节为单位)。
这是符合字符串内容的实际字节数,不包括'\0',不一定等于其存储容量。
请注意,对象在处理字节时不知道最终可能用于对其包含的字符进行编码的编码。因此,返回的值可能与多字节或可变长度字符序列(如 UTF-8)中编码字符的实际数目不对应。string::size 和 string::length 都是同义词,返回相同的值。
string// string::size #include <iostream> #include <string> int main () { std::string str ("Test string"); std::cout << "The size of str is " << str.size() << " bytes.\n"; return 0; }
输出:
The size of str is 11 bytes
1.2 string::clear()
void clear();
清除字符串擦除字符串的内容,该字符串将变为空字符串(长度为 0 个字符)。
其实就是将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
1.3 string::resize()
void resize (size_t n); void resize (size_t n, char c);
● 如果 n 小于当前字符串长度,则当前值将缩短为其前 n 个字符,并删除第 n 个字符以外的字符。 ● 如果 n 大于当前字符串长度,则通过在末尾插入任意数量的字符来扩展当前内容,以达到 n 的大小。 ● 如果指定了 c,则新元素将初始化为 c 的副本,否则,它们是值初始化的字符(null 字符)void Teststring1() { // 注意:string类对象支持直接用cin和cout进行输入和输出 string s("hello, zjc!!!"); cout << s.size() << endl; cout << s.length() << endl; cout << s.capacity() << endl; cout << s << endl; // 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小 s.clear(); cout << s.size() << endl; cout << s.capacity() << endl; // 将s中有效字符个数增加到10个,多出位置用'a'进行填充 // “aaaaaaaaaa” s.resize(10, 'a'); cout << s.size() << endl; cout << s.capacity() << endl; //将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充 //”aaaaaaaaaaa\0\0“ //注意此时s中有效个数已经增加到15个 s.resize(15); cout << s.size() << endl; cout << s.capacity() << endl; cout << s << endl; //将s中有效数字符缩小到5个 s.resize(5); cout << s.size() << endl; cout << s.capacity() <<endl; cout << s << endl; }
1.4 string::erase()
erase()函数用于从字符串中删除指定位置或指定范围的字符。它可以接受一个参数或两个参数。
1.当传递一个参数时,表示从指定位置开始删除到字符串的末尾的所有字符。
2.当传递两个参数时,表示从指定位置开始删除指定数量的字符。
3.l调用erase()后,字符串的长度会相应地减少,并且内存空间也可能会被重新分配以适应新的长度。
void Teststring2() { //clear()函数用于清空字符串的内容,将字符串变为空字符串,即不包含任何字符。 //调用clear()后,字符串的长度将变为0,但内存空间不会被释放,仍然保留着。 string s1("hello wolrd"); s1.clear(); cout << "s1: " << s1 <<endl; cout << s1.size()<<endl<< s1.capacity()<<endl; //erase()函数用于从字符串中删除指定位置或指定范围的字符。它可以接受一个参数或两个参数。 //当传递一个参数时,表示从指定位置开始删除到字符串的末尾的所有字符。 string s2("hello wolrd"); s2.erase(4); cout << "s2: " << s2 <<endl; cout << s2.size()<<endl<< s2.capacity()<<endl; //当传递两个参数时,表示从指定位置开始删除指定数量的字符。 //调用erase()后,字符串的长度会相应地减少,并且内存空间也可能会被重新分配以适应新的长度。 string s3("hello wolrd"); s3.erase(7,3); cout << "s3: " << s3 <<endl; cout << s3.size()<<endl<< s3.capacity(); }
1.5 string::reserve() 保留
void reserve (size_t n = 0);
请求更改容量请求使字符串容量适应计划的大小更改,长度不超过 n 个字符。
如果 n 大于当前字符串容量,则该函数会导致容器将其容量增加到 n 个字符(或更大(具体看编译器的设定))。
在所有其他情况下,它被视为收缩字符串容量的非绑定请求(在size大于n的情况下,请求缩小容积无效):容器实现可以自由地优化,并使字符串的容量大于 n。
此函数对字符串长度没有影响,并且无法更改其内容。void Teststring3() { string s; //测试reserve是否改变string中有效元素个数 s.reserve(100); cout << s.size()<<endl; cout << s.capacity() <<endl; // 测试reserve参数小于string的底层空间大小,是否会将空间缩小 s.reserve(50); cout << s.size()<<endl; cout << s.capacity() <<endl; //可以缩小空间 }
1.6 std::string::shrink_to_fit
void shrink_to_fit();
收缩以适合请求字符串减小其容量以适合其大小。
可以理解为请求string::size() 缩小后。为了缩小占有空间,使用shrink_to_fit()缩小,此时string::size()不变。string::capacity可能会缩小有可能不变,如果string::capacity缩小,那么一定大于等于string::size。
例:
// string::shrink_to_fit #include <iostream> #include <string> int main () { std::string str (100,'x'); std::cout << "1. capacity of str: " << str.capacity() << '\n'; str.resize(10); std::cout << "2. capacity of str: " << str.capacity() << '\n'; str.shrink_to_fit(); std::cout << "3. capacity of str: " << str.capacity() << '\n'; return 0; }
可能的输出:
1. capacity of str: 100 2. capacity of str: 100 3. capacity of str: 10
2.string数据插入删除相关的接口
2.1 std::string::push_back 尾插
void push_back (char c);
将字符附加到字符串
将字符 c 追加到字符串的末尾,使其长度增加 1。
// string::push_back #include <iostream> #include <fstream> #include <string> int main () { std::string str1("hello world"); std::string str2; for(auto e:str1) { str2.push_back(e); } std::cout << str2 << '\n'; return 0; }
将字符串str1的字符从前到后尾插到str2中
2.2 std::string::pop_back 尾删
void pop_back();
删除最后一个字符擦除字符串的最后一个字符,从而有效地将其长度减少 1。
#include <iostream> #include <string> int main () { std::string str1("hello world"); std::string str2; for(auto e:str1) { str2.push_back(e); } std::cout << str2 << '\n'; str2.pop_back(); str2.pop_back(); std::cout << str2 << '\n'; return 0; }
直接调用两次pop_back函数,删掉尾部两个字符。
2.3 std::string::insert 插入
这里我们
字符串 (1) string& insert (size_t pos, const string& str);子字符串 (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);char (6) iterator insert (iterator p, char c);range (7) template <class InputIterator> void insert (iterator p, InputIterator first, InputIterator last);这里我们主要用到1235这三个重载函数。
// inserting into a string #include <iostream> #include <string> int main () { std::string str="to be question"; std::string str2="the "; std::string str3="or not to be"; std::string::iterator it; // used in the same order as described above: str.insert(6,str2); // to be (the )question str.insert(6,str3,3,4); // to be (not )the question str.insert(10,"that is cool",8); // to be not (that is )the question str.insert(10,"to be "); // to be not (to be )that is the question str.insert(15,1,':'); // to be not to be(:) that is the question it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question str.insert (str.end(),3,'.'); // to be, not to be: that is the question(...) str.insert (it+2,str3.begin(),str3.begin()+3); // (or ) std::cout << str << '\n'; return 0; }
3.string查找相关的接口
3.1 std::string::find
字符串 (1) size_t find (const string& str, size_t pos = 0) const; C string (2) size_t find (const char* s, size_t pos = 0) const; 缓冲器 (3) size_t find (const char* s, size_t pos, size_t n) const; 字符 (4) size_t find (char c, size_t pos = 0) const;
在字符串中查找内容在字符串中搜索由其参数指定的序列的第一次匹配项,并返回第一个匹配项所在的第一个字符的位置。
指定 pos 时,搜索仅包括位置 pos 处或位置之后的字符,忽略任何可能出现的在 pos 之前包含字符的情况。
请注意,与成员find_first_of不同,每当搜索多个字符时,仅其中一个字符匹配是不够的,但整个(所搜索)序列必须匹配。参数
str
另一个包含要搜索的主题的字符串。
POS
要在搜索中考虑的字符串中第一个字符的位置。
如果这大于字符串长度,则函数永远不会找到匹配项。
注意:第一个字符由值 0(不是 1)表示:值 0 表示搜索整个字符串。s
指向字符数组的指针。
如果指定了参数 n (3),则要匹配的序列是数组中的前 n 个字符。
否则 (2),应为以 null 结尾的序列:要匹配的序列的长度由第一次出现 null 字符确定。n
要匹配的字符序列的长度。
c
要搜索的单个字符
size_t 是无符号整型(与成员类型相同)。string::size_type
返回值
第一个匹配项的第一个字符的位置。
如果未找到匹配项,该函数将返回 string::npos。void Teststring6() { //取出ur1中的域名 string ur1("http://www.cplusplus.com/reference/string/string/find/"); cout << ur1 << endl; size_t start = 0; size_t finish = ur1.find("://"); if(start == string::npos) { cout << "invalid ur1" << endl; return; } // string substr (size_t pos = 0, size_t len = npos) const; string address = ur1.substr(start,finish - start); cout << address << ' '; start += address.size()+3; do { finish = ur1.find('/',start); address = ur1.substr(start,finish - start); cout << address << ' '; start += address.size()+1; }while(finish!= (ur1.size()-1)); cout << endl; // 删除ur1的协议前缀 pos = ur1.find("://"); ur1.erase(0, pos + 3); cout << ur1 <<endl; }
使用find寻找C++图书馆网站的网址中://和/,来区分协议,域名等的。
string::size_type
3.2 std::string::rfind
std::string::rfind
string (1) size_t rfind (const string& str, size_t pos = npos) const;c-string (2) size_t rfind (const char* s, size_t pos = npos) const;buffer (3) size_t rfind (const char* s, size_t pos, size_t n) const;character (4) size_t rfind (char c, size_t pos = npos) const;查找字符串中最后一次出现的内容在字符串中搜索由其参数指定的序列的最后一次匹配项。
指定 pos 时,搜索仅包括从位置 pos 开始或之前开始的字符序列,忽略在 pos 之后开始的任何可能的匹配。这个与string::find类似,不过最大的区别是一个从前往后搜索,另一个从后往前搜索。
// string::rfind #include <iostream> #include <string> #include <cstddef> int main () { std::string str ("The sixth sick sheik's sixth sheep's sick."); std::string key ("sixth"); std::size_t found = str.rfind(key); if (found!=std::string::npos) str.replace (found,key.length(),"seventh"); std::cout << str << '\n'; return 0; }
这代码搜索sixth,并且替换成seventh,可以看到它是替换掉后面sixth而不是前面的sixth,可以证明该函数是从前后往前搜索的。
输出
The sixth sick sheik's seventh sheep's sick
string::find_first_of
string::find_first_not_of
string::find_last_of
string::find_list_not_of
这四个接口十分类似,这里不一一列举,主要讲解string::find_first_of,其他简单介绍。
3.3string::find_first_of
字符串 (1) size_t find_first_of (const string& str, size_t pos = 0) const;C 弦 (2) size_t find_first_of (const char* s, size_t pos = 0) const;缓冲器 (3) size_t find_first_of (const char* s, size_t pos, size_t n) const;字符 (4) size_t find_first_of (char c, size_t pos = 0) const;在字符串中查找字符在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。
指定 pos 时,搜索仅包括位置 pos 处或位置之后的字符,忽略 pos 之前可能出现的任何字符。参数
str
另一个包含要搜索的字符的字符串。
POS
要在搜索中考虑的字符串中第一个字符的位置。
如果这大于字符串长度,则函数永远不会找到匹配项。
注意:第一个字符由值 0(不是 1)表示:值 0 表示搜索整个字符串。s
指向字符数组的指针。
如果指定了参数 n (3),则搜索数组中的前 n 个字符。
否则 (2),应为以 null 结尾的序列:包含要匹配的字符的序列的长度由第一次出现 null 字符确定。n
要搜索的字符值数。
c
要搜索的单个字符。
size_t是无符号整型(与成员类型相同)。string::size_typestring::size_type
返回值
匹配的第一个字符的位置。
如果未找到匹配项,该函数将返回 string::npos。代码演示
// string::find_first_of #include <iostream> // std::cout #include <string> // std::string #include <cstddef> // std::size_t int main () { std::string str ("Please, replace the vowels in this sentence by asterisks."); std::size_t found = str.find_first_of("aeiou"); while (found!=std::string::npos) { str[found]='*'; found=str.find_first_of("aeiou",found+1); } std::cout << str << '\n'; return 0; }
找到任何字符匹配的第一个字符,即是字符串中“aeiou”的任意一个字符匹配,就把它替换成
‘*’。
输出
Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.
3.4 string::find_first_not_of
接口参数和string::find_first_of一样,但是查找的是字符串中缺少字符(没有出现的字符),返回它的位置。
3.5 string::find_last_of
接口参数和string::find_first_of一样,查找的是字符串中字符,返回它的位置,与string::find_first_of不同的是从后往前寻找。
3.6 string::find_last_not_of
接口参数和string::find_first_of一样,与 string::find_last_of类似但是查找的是字符串中缺少字符(没有出现的字符)。
4.string的遍历(含迭代器接口)
3种遍历方式:
需要注意的以下三种方式除了遍历string对象,还可以遍历修改string中的字符,
另外以下三种方式对于string而言,第一种使用最多void Teststring5() { string s("hello world"); //1.for + operator[] for(size_t i = 0; i< s.size();++i) cout << s[i] <<" "; cout << endl; //2.迭代器 string::iterator it = s.begin(); while(it != s.end()) { cout << *it << " "; ++it; } cout << endl; // string::reverse_iterator = s.rbegin(); //C++11之后。直接使用auto定义迭代器,让编译器推导迭代器的类型 auto rit = s.rbegin(); while(rit != s.rend()) { cout << *rit << endl; rit++; } //3.范围for(底层也是运用迭代器) for(auto ch : s) //如果要修改的话,使用引用 cout << ch << " "; cout << endl; }
4.1 std::string::begin
iterator end(); const_iterator end() const;
将迭代器返回到开头返回指向字符串的第一个字符的迭代器。(运用如上代码所示)
4.2 std::string::end
iterator end(); const_iterator end() const;
将迭代器返回到 end返回一个迭代器,该迭代器指向字符串的末尾字符。(运用如上代码所示)
过去结束字符是理论上的字符,它将跟随字符串中的最后一个字符。不得取消引用。
由于标准库的函数使用的范围不包括其关闭迭代器所指向的元素,因此此函数通常与 string::begin 结合使用,以指定包含字符串中所有字符的范围。
如果对象是空字符串,则此函数返回与 string::begin 相同的结果。
4.3 std::string::rbegin
reverse_iterator rbegin(); const_reverse_iterator rbegin() const;
返回反向迭代器以反向开始返回指向字符串最后一个字符(即其反向开头)的反向迭代器。
反向迭代器向后迭代:增加它们会使它们向字符串的开头移动。
rbegin 指向 member end 将指向的字符之前的字符。(运用如上代码所示)
4.4 std::string::rend
reverse_iterator rend(); const_reverse_iterator rend() const;
将反向迭代器返回到反向端返回一个反向迭代器,该迭代器指向字符串第一个字符(被视为其反向末尾)之前的理论元素。
string::rbegin 和 string::rend 之间的范围包含字符串的所有字符(顺序相反)。(运用如上代码所示)
5. string 子字符串
5.1 std::string::substr
string substr (size_t pos = 0, size_t len = npos) const;
生成子字符串
返回一个新构造的对象,其值初始化为此对象的子字符串的副本。子字符串是对象的一部分,它从字符位置开始并跨越字符(或直到字符串的末尾,以先到者为准)。
pos
要作为子字符串复制的第一个字符的位置。
如果这等于字符串长度,则该函数返回一个空字符串。
如果这大于字符串长度,则会抛出out_of_range。
注意:第一个字符由值 0(而不是 1)表示。
lens
要包含在子字符串中的字符数(如果字符串较短,则使用尽可能多的字符)。
值 string::npos 表示字符串末尾之前的所有字符。
返回值
一个字符串对象,具有此对象的子字符串。
例
// string::substr #include <iostream> #include <string> int main () { std::string str="We think in generalities, but we live in details."; // (quoting Alfred N. Whitehead) std::string str2 = str.substr (3,5); // "think" std::size_t pos = str.find("live"); // position of "live" in str std::string str3 = str.substr (pos); // get from "live" to the end std::cout << str2 << ' ' << str3 << '\n'; return 0; }
输出
think live in details.
演示了加lens和不加lens的情况
6.交换和替换string接口
6.1 std::string::replace
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); 缓冲器 (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); full (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);
主要用到前四个接口。
很简单的概括就是前面规划出要被替换的字符串和后面规划出要替换的字符串。
参数
pos
原来字符串位置
len
要替换的长度
例子
#include <iostream> #include <string> int main () { std::string base="this is a test string."; std::string str2="n example"; std::string str3="sample phrase"; std::string str4="useful."; // replace signatures used in the same order as described above: // Using positions: 0123456789*123456789*12345 std::string str=base; // "this is a test string." str.replace(9,5,str2); // "this is an example string." (1) str.replace(19,6,str3,7,6); // "this is an example phrase." (2) str.replace(8,10,"just a"); // "this is just a phrase." (3) str.replace(8,6,"a shorty",7); // "this is a short phrase." (4) str.replace(22,1,3,'!'); // "this is a short phrase!!!" (5) // Using iterators: 0123456789*123456789* str.replace(str.begin(),str.end()-3,str3); // "sample phrase!!!" (1) str.replace(str.begin(),str.begin()+6,"replace"); // "replace phrase!!!" (3) str.replace(str.begin()+8,str.begin()+14,"is coolness",7); // "replace is cool!!!" (4) str.replace(str.begin()+12,str.end()-4,4,'o'); // "replace is cooool!!!" (5) str.replace(str.begin()+11,str.end(),str4.begin(),str4.end());// "replace is useful." (6) std::cout << str << '\n'; return 0; }
7.比较赋值string接口
直接运用>、<、<=、>=、!=、==、运算比较即可
库函数已经进行运算符重载就不需要用类似string::compare()的接口增加记忆成本
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1("string");
string str2("string1");
string str3("string1");
cout << (str1 < str2) <<endl;
cout << (str1 == str2) <<endl;
cout << (str1 > str2) <<endl;
cout << (str3 < str2) <<endl;
cout << (str3 == str2) <<endl;
cout << (str3 > str2) <<endl;
}
输出: