string

scorlw 发布于

string

c++

string类本不是STL的容器,但是它与STL容器有着很多相似的操作,之所以抛弃char的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,*不必担心内存是否足够、字符串长度**等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下的需要。

一、声明:

使用字符串,要先包含头文件 : #include

1
2
3
4
5
6
7
8
9
10
string s;  // 生成一个空字符串s 
string s(str) ; // 拷贝构造函数生成str的复制品
string s(str, stridx); // 将字符串str内"始于位置stridx"的部分当作字符串的初值
string s(str, stridx, strlen) ; // 将字符串str内"始于stridx且长度顶多strlen"的部分作为字符串的初值
string s(cstr) ; // 将C字符串(以NULL结束)作为s的初值
string s(chars, chars_len) ; // 将C字符串前chars_len个字符作为字符串s的初值。
string s(num, ‘c’) ; // 生成一个字符串,包含num个c字符
string s(“value”); string s=“value”; // 将s初始化为一个字符串字面值副本
string s(begin, end); // 以区间begin/end(不包含end)内的字符作为字符串s的初值
s.~string(); //销毁所有字符,释放内存

二、string对象的操作

1
2
3
4
5
6
7
8
9
10
11
string s;
s.empty(); // s为空串 返回true
s.size(); // 返回s中字符个数 类型应为:string::size_type
s[n]; // 从0开始相当于下标访问
s1+s2; // 把s1和s2连接成新串 返回新串
s1=s2; // 把s1替换为s2的副本
s1==s2; // 比较,相等返回true
`!=, <, <=, >, >=` //惯有操作 任何一个大写字母都小于任意的小写字母
string s1("hello");
string s3=s1+"world"; //合法操作
string s4="hello"+"world"; //非法操作:两个字符串字面值相加or报错

三、字符串操作函数

1、 string类函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
=, s.assign() // 赋以新值 
swap() // 交换两个字符串的内容
+=, s.append(), s.push_back() // 在尾部添加字符
s.insert() // 插入字符
s.erase() // 删除字符
s.clear() // 删除全部字符
s.replace() // 替换字符
+ // 串联字符串
==,!=,<,<=,>,>=,compare() // 比较字符串
size(),length() // 返回字符数量
max_size() // 返回字符的可能最大个数
s.empty() // 判断字符串是否为空
s.capacity() // 返回重新分配之前的字符容量
reserve() // 保留一定量内存以容纳一定数量的字符
[ ], at() // 存取单一字符
>>,getline() // 从stream读取某值
<< // 将谋值写入stream
copy() // 将某值赋值为一个C_string
c_str() // 返回一个指向正规C字符串(C_string)的指针 内容与本string串相同 有’\0’
data() // 将内容以字符数组形式返回 无’\0’
s.substr() // 返回某个子字符串
begin() end() // 提供类似STL的迭代器支持
rbegin() rend() // 逆向迭代器
get_allocator() // 返回配置器

2、 函数说明

1) s.assign();

1
2
3
4
5
6
s.assign(str);
s.assign(str,1,3); // 如果str是"iamangel" 就是把"ama"赋给字符串
s.assign(str,2,string::npos); // 把字符串str从索引值2开始到结尾赋给s
s.assign("gaint");
s.assign("nico",5); // 把’n’ ‘I’ ‘c’ ‘o’ ‘\0’赋给字符串
s.assign(5,'x'); // 把五个x赋给字符串

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
string str = "hello";
string s;
s.assign(str); // 不说
cout << s << endl;
s.assign(str,1,3); // 如果str是"iamangel" 就是把"ama"赋给字符串
cout << s << endl;
s.assign(str,2,string::npos); // 把字符串str从索引值2开始到结尾赋给s
cout << s << endl;
s.assign("gaint"); // 不说
cout << s << endl;
s.assign("nico",5); // 把’n’ ‘I’ ‘c’ ‘o’ ‘\0’赋给字符串
cout << s << endl;
s.assign(5,'x'); // 把五个x赋给字符串
cout << s << endl;

I/O:

1
2
3
4
5
6
hello
ell
llo
gaint
nico
xxxxx

2) 大小和容量函数

一个C++字符串存在三种大小:

  1. 现有的字符数,函数是s.size()和s.length(),他们等效。s.empty()用来检查字符串是否为空。
  2. max_size(); 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。
  3. capacity()重新分配内存之前string所能包含的最大字符数。

这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

3) 元素存取

我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。

但是应该注意的是操作符[]并不检查索引是否有效(有效索引0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用at()的时候索引无效,会抛出out_of_range异常。

有一个例外不得不说,const string a;的操作符[]对索引值是a.length()仍然有效,其返回值是’\0’。其他的各种情况,a.length()索引都是无效的。

4) 比较函数

C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<”hello”)。在使用>,>=,<,<=这些操作符的时候是根据”当前字符特性”将字符按字典顺序进行逐一的比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。

另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等 、>0-大于、<0-小于。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int main ()
{
string s1="123",s2="123";
cout<<s1.compare(s2)<<endl;//0,相等

s1="123",s2="1234";
cout<<s1.compare(s2)<<endl;//-1,小于

s1="1230",s2="123";
cout<<s1.compare(s2)<<endl;//1,大于,0也大于空

s1="1234",s2="223";
cout<<s1.compare(s2)<<endl;//-1,小于,因为是从s[0]开始一位一位比较的

std::string str1 ("green apple");
std::string str2 ("red apple");

cout<<str1.compare(str2)<<endl;//-1,小于g在r前面

if (str1.compare(str2) != 0)
std::cout << str1 << " is not " << str2 << '\n';//green apple is not red apple
//str1的第6个字符以及后面的4个字符和参数比较
if (str1.compare(6,5,"apple") == 0)
std::cout << "still, " << str1 << " is an apple\n";//still, green apple is an apple

if (str2.compare(str2.size()-5,5,"apple") == 0)
std::cout << "and " << str2 << " is also an apple\n";//and red apple is also an apple
//str1的第6个字符以及后面的4个字符和str2的第4个字符以及后面的4个字符比较
if (str1.compare(6,5,str2,4,5) == 0)
std::cout << "therefore, both are apples\n";//therefore, both are apples
system("pause");
return 0;
}

5) 插入字符

也许你需要在string中间的某个位置插入字符串,这时候你可以用insert()函数,这个函数需要你指定一个安插位置的索引,被插入的字符串将放在这个索引的后面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);//关闭缓存
string str2 = "abcdefghijklmn";
string str = "0123456789";
string str3 = "ABCDEFGHIJKLMN";
string::iterator it;

//s.insert(pos,str)//在s的pos位置插入str
str.insert(6,str2); //012345abcdefghijklmn6789
cout << str << endl;
str = "0123456789";
//s.insert(pos,str,a,n)在s的pos位置插入str中插入位置a到后面的n个字符
str.insert(6,str3,3,4); //012345DEFG6789
cout << str << endl;
str = "0123456789";
//s.insert(pos,cstr,n)//在pos位置插入cstr字符串从开始到后面的n个字符
str.insert(3,"that is cool",8); //012that is 3456789
cout << str << endl;
str = "0123456789";
//s.insert(pos,cstr)在s的pos位置插入cstr
str.insert(3,"to be "); //012to be 3456789
cout << str << endl;
str = "0123456789";
//s.insert(pos,n,ch)在s.pos位置上面插入n个ch
str.insert(3,1,':'); //012:3456789
cout << str << endl;
str = "0123456789";
//s.insert(s.it,ch)在s的it指向位置前面插入一个字符ch,返回新插入的位置的迭代器
it = str.insert(str.begin()+5,','); //01234,56789
cout << *it << endl;//,
str = "0123456789";
//s.insert(s.it,n,ch)//在s的it所指向位置的前面插入n个ch
str.insert (str.end(),3,'.'); //0123456789...
cout << str << endl;
str = "0123456789";
//s.insert(it,str.ita,str.itb)在it所指向的位置的前面插入[ita,itb)的字符串
cout << *it << endl;//5
str.insert (it+2,str3.begin(),str3.begin()+3); //0123456ABC789
cout << str << endl;
system("pause");
return 0;
}

这种形式的insert()函数不支持传入单个字符,这时的单个字符必须写成字符串形式。为了插入单个字符,insert()函数提供了两个对插入单个字符操作的重载函数:

1
2
insert(size_type index, size_type num, chart c);
insert(iterator pos, size_type num, chart c);

其中size_type是无符号整数,iterator是char*,

所以,你这么调用insert函数是不行的:

insert(0, 1, ‘j’);这时候第一个参数将转换成哪一个呢?

所以你必须这么写:insert((string::size_type)0, 1, ‘j’)

第二种形式指出了使用迭代器安插字符的形式。

6) 提取子串s.substr()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
s.substr(); // 返回s的全部内容 
s.substr(11); // 从索引11往后的子串
s.substr(5,6); // 从索引5开始6个字符

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
string s="abcdefg";

//s.substr(pos1,n)返回字符串位置为pos1后面的n个字符组成的串
string s2=s.substr(1,5);//bcdef

//s.substr(pos)//得到一个pos到结尾的串
string s3=s.substr(4);//efg

return 0;
}

7) 删除函数erase

用来执行删除操作

删除操作有三种

  • 指定pos和len,其中pos为为起始位置,pos以及后面len-1个字符串都删除
  • 迭代器,删除迭代器指向的字符
  • 迭代器范围,删除这一范围的字符串,范围左闭右开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>

int main()
{
string str("0123456789");
//直接指定删除的字符串位置第3个后面的4个字符
str.erase(3,4);//012789
cout << str << endl;
str = "0123456789";
//删除迭代器指向的字符
str.erase(str.begin() + 2);//013456789
cout << str << endl;
str = "0123456789";
//删除迭代器范围的字符
str.erase(str.begin() + 2, str.end() - 2);//0189
cout << str << endl;
system("pause");
return 0;
}

8) 追加与替换:append和replace操作

append函数可以用来在字符串的末尾追加字符和字符串。由于string重载了运算符,也可以用+=操作实现 。

repalce顾名思义,就是替换的意思,先删除,后增加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int main ()
{
string str;
string str2="Writing ";
string str3="print 10 and then 5 more";

//直接追加一个str2的字符串
str.append(str2); // "Writing "
//后面追加str3第6个字符开始的3个字符串
str.append(str3,6,3); // "10 "
//追加字符串形参的前5个字符
str.append("dots are cool",5); // "dots "
//直接添加
str.append("here: "); // "here: "
//添加10个'.'
str.append(10u,'.'); // ".........."
//10u是unsigned int,直接写10也是可以的
//添加str3迭代器范围的字符串
str.append(str3.begin()+8,str3.end()); // " and then 5 more"
//最后这个比较特殊,意思是添加5个'A',实际上参数里面的65对应的asc码就是65
//str.append<int>(5,65); // "....."
//本地没有成功
//字符串追加也可以用重载运算符实现
str+="lalala";
cout << str << '\n';
system("pause");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int main ()
{
string base="this is a test string.";
string str2="n example";
string str3="sample phrase";
string str4="useful.";

// replace signatures used in the same order as described above:

// Using positions: 0123456789*123456789*12345
string str=base; // "this is a test string."
//第9个字符以及后面的4个字符被str2代替
str.replace(9,5,str2); // "this is an example string." (1)
//第19个字符串以及后面的5个字符用str的第7个字符以及后面的5个字符代替
str.replace(19,6,str3,7,6); // "this is an example phrase." (2)
//第8个字符以及后面的9个字符用字符串参数代替
str.replace(8,10,"just a"); // "this is just a phrase." (3)
//第8个字符以及后面的5个字符用字符串参数的前7个字符替换
str.replace(8,6,"a shorty",7); // "this is a short phrase." (4)
//第22以及后面的0个字符用3个叹号替换
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';
system("pause");
return 0;
}

9) 搜索操作

find和rfind函数:

find函数主要是查找一个字符串是否在调用的字符串中出现过,大小写敏感。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int main ()
{
string str ("There are two needles in this haystack with needles.");
string str2 ("needle");

//在str当中查找第一个出现的needle,找到则返回出现的位置,否则返回结尾
size_t found = str.find(str2);//size_t = unsigned long long
if (found != string::npos)
cout << "first 'needle' found at: " << found << '\n';//first 'needle' found at: 14(n的下角标)
//在str当中,从第found+1的位置开始查找参数字符串的前6个字符
found = str.find("needles are small",found+1,6);
if (found != string::npos)
cout << "second 'needle' found at: " << found << '\n';//second 'needle' found at: 44
//在str当中查找参数中的字符串
found = str.find("haystack");
if (found != string::npos)
cout << "'haystack' also found at: " << found << '\n';//'haystack' also found at: 30
//查找一个字符
found = str.find('.');
if (found != string::npos)
cout << "Period found at: " << found << '\n';//Period found at: 51
//组合使用,把str2用参数表中的字符串代替
// let's replace the first needle:
str.replace(str.find(str2),str2.length(),"preposition");
cout << str << '\n';//There are two prepositions in this haystack with needles.
system("pause");
return 0;
}

注意:

rfind函数就是找最后一个出现的匹配字符串,返回的位置仍然是从前往后数的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main ()
{
string str ("The sixth sick sheik's sixth sheep's sick.");
string key ("sixth");// ^
//rfind是找最后一个出现的匹配字符串
size_t found = str.rfind(key);
if (found != string::npos)
{
cout<< found <<endl;//输出23
str.replace (found,key.length(),"seventh");//找到的sixth替换成seventh
}
cout << str << '\n';//The sixth sick sheik's seventh sheep's sick.
system("pause");
return 0;
}

find_….of函数:

1
2
3
4
find_first_of(args) 查找args中任何一个字符第一次出现的位置
find_last_of(args) 最后一个出现的位置
find_fist_not_of(args) 查找第一个不在args中的字符
find_last_not_of 查找最后一个不在args中出现的字符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main ()
{
std::string str1 ("Please, replace the vowels in this sentence by asterisks.");
std::size_t found1 = str1.find_first_of("aeiou");
//把所有元音找出来用*代替
while (found1 != std::string::npos)
{
str1[found1] = '*';
found1 = str1.find_first_of("aeiou",found1+1);
}
std::cout << str1 << '\n';//Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.

//在str2中找到第一个不是消协英文字母和空格的字符
std::string str2 ("look for non-alphabetic characters...");
std::size_t found2 = str2.find_first_not_of("abcdefghijklmnopqrstuvwxyz ");
if (found2 != std::string::npos)
{
std::cout << "The first non-alphabetic character is " << str2[found2];
std::cout << " at position " << found2 << '\n';
//The first non-alphabetic character is - at position 12
}
system("pause");
return 0;
}

find_last_of和find_last_not_of与first基本相同。

10) 数值转换

函数 含义
to_string(val) 把val转换成string
stoi(s,p,b) 把字符串s从p开始转换成b进制的int
stol(s,p,b) long
stoul(s,p,b) unsigned long
stoll(s,p,b) long long
stoull(s,p,b) unsigned long long
stof(s,p) float
stod(s,p) double
stold(s,p) long double

四、字符串流stringstream操作

iostream标准库支持内存中的输入输出,只要将流与存储在程序内存中的string对象捆绑起来即可。此时,可使用iostream输入和输出操作符读写这个stream对象。使用stringstream,我们必须包含头文件#include <sstream>

1、 stringstream特定的操作

1
2
3
4
1)  stringstream strm; // 创建自由的stringstream对象
2) stringstream strm(s); // 创建存储s的副本的stringstream对象,s是stringstream类型
3) strm.str(); // 返回strm中存储的string类型对象
4) strm.str(s); // 将string类型的s复制给strm 返回void

转换格式等参见原文。

原文地址:https://blog.csdn.net/livecoldsun/article/details/25011413 https://blog.csdn.net/tengfei461807914/article/details/52203202