前言
string是C++标准库的一个重要的部分,主要用于字符串处理。这篇文章主要介绍了C++ string的用法和例子,需要的朋友可以参考下。
首先,做一个总结,string主要用于字符串处理,对于字符串操作,有以下几点需要解决:
- 如何创建字符串对象,创建字符串的方法
- 如何获取字符串的长度、判断一个字符串是否为空、清空字符串
- 如何获取字符串内的单个字符
- 如何在字符串后添加新的字符串或字符
- 如何在字符串中间任何位置插入新的字符串或字符
- 如何删除字符串中某一段字符串或字符
- 如何用新的字符串或字符替换原字符串中某一段字符串或字符
- 如何交换两个字符串的内容
- 如何在原字符串中查找是否存在某字符串或某些字符
- 如何获得字符串中的某个子字符串或字符
- 如何比较两个字符串是否相同
- 如何实现对多个字符串的拼接
- 如何从用户输入处获得字符串,如何输出字符串
- 如何将string类字符串转换为C语言中的字符串数组
解决以上问题对应的函数:
- 创建:
=
()
assign
- 长度 :
length
size
是否为空:empty
清空:clear
- 获取单个字符:
[]
at
- 添加:
+=
append
- 插入:
insert
- 删除:
erase
- 替换:
replace
- 交换:
swap
- 查找:
find
rfind
find_first_of
find_last_of
find_first_not_of
find_last_not_of
- 子字符串或字符:
substr
- 比较:
relational operators
compare
- 拼接:
+
- 输入、输出:
<<
>>
getline
c_str
data
Member functions
构造字符串对象:
// string constructor
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string s0 ("Initial string");
string s1;
string s2 (s0);
string s3 (s0, 8, 3);
string s4 ("A character sequence");
string s5 ("Another character sequence", 12);
string s6a (10, 'x');
string s6b (10, 42); // 42 is the ASCII code for '*'
string s7 (s0.begin(), s0.begin()+7);
cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;
cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a;
cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n';
return 0;
}
▌01. Iterators
Function | Explanation |
---|---|
begin | 函数返回一个迭代器,指向字符串的第一个元素 |
end | 函数返回一个迭代器,指向字符串的末尾(最后一个字符的下一个位置) |
rbegin | 函数返回一个逆向迭代器,指向字符串的最后一个字符 |
rend | 函数返回一个逆向迭代器,指向字符串的开头(第一个字符的前一个位置) |
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 ("Test string");
string str2 ("now step live...");
string::iterator it; //定义正向迭代器
string::reverse_iterator rit; //定义逆向迭代器
//用正向迭代器遍历容器
for(it=str1.begin(); it!=str1.end(); it++)
{
cout << *it; //*it 就是迭代器it指向的元素
}
cout << endl;
//用逆向迭代器遍历容器
for(rit=str2.rbegin(); rit!=str2.rend(); rit++)
{
cout << *rit; //*rit 就是迭代器rit指向的元素
}
cout << endl;
return 0;
}
输出结果:
Test string
...evil pets won
▌02. Capacity
Function | Explanation |
---|---|
size or length | 返回源字符串的长度大小 |
max_size | 返回string对象中可存放的最大字符串的长度 |
capacity | 返回string分配的存储容量 |
resize | 调整源字符串的长度 |
reserve | 重新给源字符串分配存储容量 |
clear | 删除字符串的内容,该字符串将变为空字符串(长度为0个字符) |
empty | 判断源字符串是否为空 |
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 ("Test string");
//1. 返回源字符串的长度大小
cout << "size: " << str1.size() << "\n";
cout << "length: " << str1.length() << "\n";
//2. 返回string对象中可存放的最大字符串的长度
cout << "max_size: " << str1.max_size() << "\n";
//3. 返回string分配的存储容量
cout << "capacity: " << str1.capacity() << "\n\n";
//4. 调整源字符串的长度
string str2 ("I like to code in C");
cout << str2 << "\n";
//4.1 void resize (size_t n, char c); 调整字符串长度为n,并用字符c填充不足的部分 。
unsigned sz = str2.size();
str2.resize (sz+2,'+');
cout << str2 << "\n";
//4.2 void resize (size_t n); 调整源字符串的长度为n。
str2.resize (14);
cout << str2 << "\n\n\n";
//5. 重新给源字符串分配存储容量
// void reserve (size_t n = 0);
string str ("Test string");
cout<<"调用str.reserve(size_t n=0);之前:"<<endl;
cout<<"capacity: "<<str.capacity()<<endl;
cout<<"max_size: "<<str.max_size()<<endl;
cout<<"size: "<<str.size()<<endl;
cout<<"length: "<<str.length()<<endl;
cout<<endl;
str.reserve(50);//string增加容量时,每次增加16的倍数,
cout<<"str.reserve(50);之后:str.capacity()=16*4-1"<<endl;
cout<<"capacity: "<<str.capacity()<<endl;//16*4-1
cout<<"max_size: "<<str.max_size()<<endl;
cout<<"size: "<<str.size()<<endl;
cout<<"length: "<<str.length()<<endl;
cout<<endl;
str.reserve(100);//string增加容量时,每次增加16的倍数
cout<<"str.reserve(100);之后:str.capacity()=16*7-1"<<endl;
cout<<"capacity: "<<str.capacity()<<endl;
cout<<"max_size: "<<str.max_size()<<endl;//16*7-1
cout<<"size: "<<str.size()<<endl;
cout<<"length: "<<str.length()<<endl;
cout<<endl;
return 0;
}
输出结果:
size: 11
length: 11
max_size: 1073741820
capacity: 11
I like to code in C
I like to code in C++
I like to code
调用str.reserve(size_t n=0);之前:
capacity: 11
max_size: 1073741820
size: 11
length: 11
str.reserve(50);之后:str.capacity()=16*4-1
capacity: 50
max_size: 1073741820
size: 11
length: 11
str.reserve(100);之后:str.capacity()=16*7-1
capacity: 100
max_size: 1073741820
size: 11
length: 11
▌03. Element access
Function | Explanation |
---|---|
operator[] | 返回对字符串中位置pos处的字符的引用 |
at | 返回对字符串中位置pos处的字符的引用 |
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str ("Test string");
for (int i=0; i<str.length(); i++)
{
cout << str[i];
}
cout << endl;
for (unsigned i=0; i<str.length(); ++i)
{
cout << str.at(i);
}
return 0;
}
输出结果:
Test string
Test string
▌04. Modifiers
Function | Explanation |
---|---|
operator+= | Append to string |
append | Append to string |
push_back | 字符串之后插入一个字符 |
assign | 可以理解为先将原字符串清空,然后赋予新的值作替换 |
insert | 插入操作 |
erase | 删除操作 |
replace | 替换操作 |
swap | 交换操作 |
4.1 append & push_back
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str;
string str2="Writing ";
string str3="print 10 and then 5 more";
// used in the same order as described above:
str.append(str2); // "Writing "
str.append(str3,6,3); // "10 "
str.append("dots are cool",5); // "dots "
str.append("here: "); // "here: "
str.append(10u,'.'); // ".........."
str.append(str3.begin()+8,str3.end()); // " and then 5 more"
str.append<int>(5,0x2E); // "....."
str.push_back('E') // 'E'
cout << str << '\n';
return 0;
}
Output:
Writing 10 dots here: .......... and then 5 more.....E
4.2 assign
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str;
string base="The quick brown fox jumps over a lazy dog.";
str.assign(base);
cout << str << '\n';
str.assign(base,10,9);
cout << str << '\n'; // "brown fox"
str.assign("pangrams are cool",7);
cout << str << '\n'; // "pangram"
str.assign("c-string");
cout << str << '\n'; // "c-string"
str.assign(10,'*');
cout << str << '\n'; // "**********"
str.assign<int>(10,0x2D);
cout << str << '\n'; // "----------"
str.assign(base.begin()+16,base.end()-12);
cout << str << '\n'; // "fox jumps over"
return 0;
}
Output:
The quick brown fox jumps over a lazy dog.
brown fox
pangram
c-string
**********
----------
fox jumps over
4.3 insert
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str="to be question";
string str2="the ";
string str3="or not to be";
string::iterator it;
str.insert(6,str2); // to be (the )question s.insert(pos,str) 在s的pos位置插入str
str.insert(6,str3,3,4); // to be (not )the question s.insert(pos,str,a,n) 在s的pos位置插入str中插入位置a到后面的n个字符
str.insert(10,"that is cool",8); // to be not (that is )the question s.insert(pos,cstr,n) 在pos位置插入cstr字符串从开始到后面的n个字符
str.insert(10,"to be "); // to be not (to be )that is the question s.insert(pos,cstr) 在s的pos位置插入cstr
str.insert(15,1,':'); // to be not to be(:) that is the question s.insert(pos,n,ch) 在s.pos位置上面插入n个ch
it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question s.insert(s.it,ch) 在s的it指向位置前面插入一个字符ch,返回新插入的位置的迭代器
str.insert (str.end(),3,'.'); // to be, not to be: that is the question(...) s.insert(s.it,n,ch) 在s的it所指向位置的前面插入n个ch
str.insert (it+2,str3.begin(),str3.begin()+3); // (or ) s.insert(it,str.ita,str.itb) 在it所指向的位置的前面插入[ita,itb)的字符串
cout << str << '\n';
return 0;
}
Output:
to be, or not to be: that is the question...
4.4 erase
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str ("This is an example sentence.");
cout << str << '\n';
// "This is an example sentence."
str.erase (10,8); // ^^^^^^^^ 直接指定删除的字符串位置第十个后面的8个字符
cout << str << '\n';
// "This is an sentence."
str.erase (str.begin()+9); // ^ 删除迭代器指向的字符
cout << str << '\n';
// "This is a sentence."
str.erase (str.begin()+5, str.end()-9); // ^^^^^ 删除迭代器范围的字符
cout << str << '\n';
// "This sentence."
return 0;
}
4.5 replace
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string base="this is a test string.";
string str2="n example";
string str3="sample phrase";
string str4="useful.";
// Using positions: 0123456789*123456789*12345
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)
cout << str << '\n';
return 0;
}
4.6 swap
#include <iostream>
#include <string>
using namespace std;
main ()
{
string buyer ("money");
string seller ("goods");
cout << "Before the swap, buyer has " << buyer;
cout << " and seller has " << seller << '\n';
seller.swap (buyer);
cout << " After the swap, buyer has " << buyer;
cout << " and seller has " << seller << '\n';
return 0;
}
Output:
Before the swap, buyer has money and seller has goods
After the swap, buyer has goods and seller has money
▌05. String operations
Function | Explanation |
---|---|
get_allocator | 返回本字符串的配置器 |
c_str or data | 返回一个指向正规C字符串的指针常量, 内容与本string串相同 |
copy | 将string对象的当前值的子字符串复制到s所指的数组中 |
find | 查找字符串中的内容 |
rfind | 查找字符串中最后出现的内容, 返回的位置仍然是从前往后数的 |
find_first_of | 在字符串中搜索与参数中指定的任何字符匹配的第一个字符 |
find_last_of | 从字符串末尾查找字符 |
find_first_not_of | 查找字符串中缺少字符 |
find_last_not_of | 从字符串末尾查找不匹配的字符 |
substr | 生成子字符串 |
compare | 比较字符串 |
5.1 c_str & data
const char* c_str() const;
const char* data() const;
c_str()
函数返回一个指向正规C字符串的指针常量, 内容与本string串相同。这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数c_str()
把 string 对象转换成c中的字符串样式。
注意: 一定要使用strcpy()
函数 等来操作方法c_str()
返回的指针
不要这样:
char* c;
string s="1234";
c = s.c_str();
这样操作:
char c[20];
string s="1234";
strcpy(c, s.c_str());
c_str()
和data()
的区别:
1. 从C++标准上的解释来看,只有一点区别:
c_str()
返回一个指向正规C字符串的指针常量,该指针保证指向一个size() + 1
长度的空间,而且最后一个字符肯定是\0
;
而data()
返回的指针则保证指向一个size()
长度的空间,不保证有没有null-terminate,可能有,可能没有,看库的实现了。
2. 有的STL的实现中,二者是完全一样的,如vs7.1,两个函数的源码中,data()
函数内部调用的是c_str()
。
5.2 copy
size_t copy (char* s, size_t len, size_t pos = 0) const;
将string对象的当前值的子字符串复制到s所指的数组中。此子字符串包含从位置pos开始的len字符。函数不会在复制内容的末尾附加空字符。
#include <iostream>
#include <string>
using namespace std;
int main ()
{
char buffer[20];
string str ("Test string...");
size_t length = str.copy(buffer,6,5);
buffer[length]='\0';
cout << "buffer contains: " << buffer << '\n';
return 0;
}
Output:
buffer contains: string
5.3 find & rfind
find
函数主要是查找一个字符串是否在调用的字符串中出现过,大小写敏感。rfind
函数就是找最后一个出现的匹配字符串,返回的位置仍然是从前往后数的。下面以find
为例:
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;
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;
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str ("There are two needles in this haystack with needles.");
string str2 ("needle");
//1. 在str当中查找第一个出现的needle,找到则返回出现的位置,否则返回结尾 size_t find (const string& str, size_t pos = 0) const;
size_t found = str.find(str2);
if (found != string::npos)
cout << "first 'needle' found at: " << found << '\n';
//2. 在str当中,从第found+1的位置开始查找参数字符串的前6个字符 size_t find (const char* s, size_t pos, size_t n) const;
found=str.find("needles are small",found+1,6);
if (found != string::npos)
cout << "second 'needle' found at: " << found << '\n';
//3. 在str当中查找参数中的字符串 size_t find (const char* s, size_t pos = 0) const;
found=str.find("haystack");
if (found != string::npos)
cout << "'haystack' also found at: " << found << '\n';
//4. 查找一个字符 size_t find (char c, size_t pos = 0) const;
found=str.find('.');
if (found != string::npos)
cout << "Period found at: " << found << '\n';
//5. 组合使用,把str2用参数表中的字符串代替, let's replace the first needle:
str.replace(str.find(str2),str2.length(),"preposition");
cout << str << '\n';
return 0;
}
Output:
first 'needle' found at: 14
second 'needle' found at: 44
'haystack' also found at: 30
Period found at: 51
There are two prepositions in this haystack with needles.
5.4 find_first_of find_last_of find_first_not_of find_last_not_of
在字符串中搜索与参数中指定的任何字符(不)匹配的第一个(或最后一个)字符。调用格式同find
or rfind
(四种调用格式)。
1) find_first_of
// string::find_first_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
using namespace std;
int main ()
{
string str ("Please, replace the vowels in this sentence by asterisks.");
size_t found = str.find_first_of("aeiou");
while (found != string::npos)
{
str[found]='*';
found=str.find_first_of("aeiou",found+1);
}
cout << str << '\n';
return 0;
}
//输出:Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.
2) find_last_of : 分离文件路径与文件名称
// string::find_last_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
using namespace std;
void SplitFilename (const string& str)
{
cout << "Splitting: " << str << '\n';
size_t found = str.find_last_of("/\\");
cout << " path: " << str.substr(0,found) << '\n';
cout << " file: " << str.substr(found+1) << '\n';
}
int main ()
{
string str1 ("/usr/bin/man");
string str2 ("c:\\windows\\winhelp.exe");
SplitFilename (str1);
SplitFilename (str2);
return 0;
}
/*output:
Splitting: /usr/bin/man
path: /usr/bin
file: man
Splitting: c:\windows\winhelp.exe
path: c:\windows
file: winhelp.exe
*/
3) find_first_not_of
// string::find_first_not_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
using namespace std;
int main ()
{
string str ("look for non-alphabetic characters...");
size_t found = str.find_first_not_of("abcdefghijklmnopqrstuvwxyz ");
if (found != string::npos)
{
cout << "The first non-alphabetic character is " << str[found];
cout << " at position " << found << '\n';
}
return 0;
}
//The first non-alphabetic character is - at position 12
4) find_first_not_of: 去除一段话末尾的回车、空格等字符。
// string::find_last_not_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
using namespace std;
int main ()
{
string str ("Please, erase trailing white-spaces \n");
string whitespaces (" \t\f\v\n\r");
size_t found = str.find_last_not_of(whitespaces);
if (found != string::npos)
str.erase(found+1);
else
str.clear(); // str is all whitespace
cout << '[' << str << "]\n";
return 0;
}
// [Please, erase trailing white-spaces]
5.5 substr
string substr (size_t pos = 0, size_t len = npos) const;
注意: substr
没有迭代器作为参数的操作,如果输入的位置超过字符的长度,会抛出一个out_of_range的异常。
// string::substr
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str="We think in generalities, but we live in details.";
string str2 = str.substr (3,5); // "think"
size_t pos = str.find("live"); // position of "live" in str
string str3 = str.substr (pos); // get from "live" to the end
cout << str2 << ' ' << str3 << '\n';
return 0;
}
// think live in details.
5.6 compare
和strcmp
函数一样,如果两个字符串相等,那么返回0
,调用对象大于参数返回>0
,小于返回<0
。在compare
当中还支持部分比较,里面有6个参数可以设置,6个参数的配置见cplusplus.com。
value | str1.compare(str2) |
---|---|
0 | 两个字符串相等 |
<0 | 在比较字符串中,str1 < str2 (第一个不匹配的字符的值较小,或者所有比较字符都匹配,但比较字符串较短) |
>0 | 在比较字符串中,str1 > str2 (第一个不匹配字符的值较较大,或者所有比较字符都匹配,但比较字符串较长) |
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 ("green apple");
string str2 ("red apple");
cout << str1.compare("green") << endl; //6, >0
cout << str1.compare("green apple 0") << endl; //-2, <0
cout << str1.compare("green apple") << endl; //0, =0
if (str1.compare(str2) != 0)
cout << str1 << " is not " << str2 << '\n';
if (str1.compare(6,5,"apple") == 0)
cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size()-5,5,"apple") == 0)
cout << "and " << str2 << " is also an apple\n";
if (str1.compare(6,5,str2,4,5) == 0)
cout << "therefore, both are apples\n";
return 0;
}
output:
6
-2
0
green apple is not red apple
still, green apple is an apple
and red apple is also an apple
therefore, both are apples
Member constants
▌01. npos
表示size_t的最大值(
Maximum value for size_t
)
static const size_t npos = -1;
- 如果作为一个返回值(return value)表示没有找到匹配项
- 但是string::npos作为string的成员函数的一个长度参数时,表示“直到字符串结束(until the end of the string)”。
Non-member function overloads
Function | Explanation |
---|---|
operator+ | Concatenate strings (function ) |
relational operators | Relational operators for string (function ) |
swap | Exchanges the values of two strings (function ) |
operator>> | Extract string from stream (function ) |
operator<< | Insert string into stream (function ) |
getline | Get line from stream into string (function ) |
▌01. operator+
// concatenating strings
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string firstlevel ("com");
string secondlevel ("cplusplus");
string scheme ("http://");
string hostname;
string url;
hostname = "www." + secondlevel + '.' + firstlevel;
url = scheme + hostname;
cout << url << '\n';
return 0;
}
// http://www.cplusplus.com
▌02. relational operators
// string comparisons
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string foo = "alpha";
string bar = "beta";
if (foo==bar) std::cout << "foo and bar are equal\n";
if (foo!=bar) std::cout << "foo and bar are not equal\n";
if (foo< bar) std::cout << "foo is less than bar\n";
if (foo> bar) std::cout << "foo is greater than bar\n";
if (foo<=bar) std::cout << "foo is less than or equal to bar\n";
if (foo>=bar) std::cout << "foo is greater than or equal to bar\n";
return 0;
}
/*output:
foo and bar are not equal
foo is less than bar
foo is less than or equal to bar
*/
▌03. swap
// swap strings
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string buyer ("money");
string seller ("goods");
cout << "Before the swap, buyer has " << buyer;
cout << " and seller has " << seller << '\n';
swap (buyer,seller);
cout << " After the swap, buyer has " << buyer;
cout << " and seller has " << seller << '\n';
return 0;
}
▌04. operator>> operator<<
// extract to string
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string name;
cout << "Please, enter your name: ";
cin >> name;
cout << "Hello, " << name << "!\n";
return 0;
}
▌05. getline
// extract to string
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string name;
cout << "Please, enter your full name: ";
getline (cin, name);
cout << "Hello, " << name << "!\n";
return 0;
}
参考资料: