- 1. 基本操作
- 2. 运算符重载
- 3. 字符串处理
- 3.1 使用下标访问元素 `[]`
- 3.2 使用 `at()` 方法访问
- 3.3 `size()` 获取字符串长度
- 3.4 `length()` 获取字符串长度
- 3.5 `capacity()` 获取字符串容量
- 3.6 `resize()` 更改字符串大小
- 3.7 `reserve()` 改变字符串容量大小
- 3.8 `empty()` 字符串是否为空
- 3.9 `clear()` 清除字符串
- 3.10 `substr()` 获取子串
- 3.11 `push_back()` 末尾追加一个字符
- 3.12 `pop_back()` 删除末尾一个字符
- 3.13 `append()` 末尾追加 字符 或 字符串
- 3.14 `insert()` 插入
- 3.15 `replace()` 替换
- 3.16 `assign()` 为字符串赋新值
- 3.17 `erase()` 删除
- 3.18 `compare()` 函数
- 3. string 转换为 const char* 、char * 或者 char[]
- 4. char * 、char []转换为 string
- 5. char* 与 char[] 互转
- 6. 查找
- 7. 实例
- 8. 数值转换:
- 9. Reference
说明:以下笔记大部分来自文末的Reference,并结合自己的理解整理成笔记
1. 基本操作
1.1 头文件
#include <string>
1.2 声明与初始化
string s0("Initial string");
// constructors used in the same order as described above:
string s1; // 默认初始化,s1为一个空字符串
string s2(s0); // s2是s0的副本
string s2 = s0; // 与上面是等价的
string s3(s0, 8, 3); // 将s0,从下标8开始,拷贝3个字符至s3
string s4("A character sequence"); // s4字符串的副本,处理字面值最后的那个空字符串外
string s4 = "A character sequence"; // 与上面是等价的
string s5("Another character sequence", 12);// 从字符串下标12开始,直到字符串结尾进行拷贝
string s6a(10, 'x'); // 把s6a初始化为10个字符'x'组成的串
string s6b(10, 42); // 把s6a初始化为10个'*'组成的串,42ASCII码为'*'
string s7(s0.begin(), s0.begin() + 7); // 从s0第一个个迭代器开始拷贝,直到s0.begin() + 7个迭代器
char cs[] = "12345";
string s8(cs, 3); // 复制字符串cs的前3个字符串到s当中
2. 运算符重载
+ 和 += | 连接字符串 |
---|---|
= | 字符串赋值 |
>、>=、< 和 <= | 字符串比大小(例如a < b, aa < ab) |
==、!= | 字符串是否相等 |
cin << s、cout >> s | 字符串输入输出,不能读入空格,以空格、制表符、回车符为结束标志 |
getline(cin, s) | 字符串输入输出,可以读入空格和制表符,以回车符作为结束标志 |
注意:使用重载的运算符 + 时,必须保证前两个操作数至少有一个为 string 类型。例如,下面的写法是不合法的:
#include <iostream>
#include <string>
int main() {
string str1 = "cat";
cout << "apple" + "boy" + str1; // 不合法
string str2 = str1 + "apple"; // 合法
return 0;
}
3. 字符串处理
3.1 使用下标访问元素 []
cout << str[0] << endl;
3.2 使用 at()
方法访问
cout << str.at(0) << endl; // (如果溢出会抛出异常)
3.3 size()
获取字符串长度
string str = "12345";
str.size(); // 长度为5
3.4 length()
获取字符串长度
string str = "12345";
str.length(); // 长度为5
3.5 capacity()
获取字符串容量
string str = "12345";
str.capacity(); // 字符串容量为5
3.6 resize()
更改字符串大小
这里改变的是 size()
大小,即string中字符数量。
(1)若新的大小n比原来的 size()
小,则多于n的部分直接删除。
(2)若新的大小n大于string中当前元素数量,则会在string当前的尾部掺入适量元素,是的vector的大小变为n。如果,为 resize()
方法指定了第二个参数,则会把后插入的原始值,初始化为该指定值,如果没有为 resize()
指定第二个参数,则会把新插入的元素初始化为默认的初始值。
string str = "12345";
str.resize(3); // 结果为 123
str.resize(str.size()+2, '+'); // 结果为 123++
3.7 reserve()
改变字符串容量大小
3.8 empty()
字符串是否为空
str.empty();
3.9 clear()
清除字符串
str.clear();
3.10 substr()
获取子串
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
3.11 push_back()
末尾追加一个字符
str.push_back('c'); // 末尾追加一个字符'c'
str += "c"; // 末尾追加一个字符串"c"
str.append("c") // 末尾追加一个字符串"c"
3.12 pop_back()
删除末尾一个字符
str.pop_back();
以上这两个方法在 string中不常用
因为字符串追加有+=
运算符,append()
、insert()
等
字符串删除有erase()
、substr()
等
3.13 append()
末尾追加 字符 或 字符串
#include <iostream>
#include <string>
int main () {
std::string str;
std::string str2="Writing ";
std::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, '.'); // ".........."
//添加str3迭代器范围的字符串
str.append(str3.begin()+8, str3.end()); // " and then 5 more"
//最后这个比较特殊,意思是添加5个'A',实际上参数里面的65对应的asc码就是65
str.append<int>(5, 65); // "....."
//字符串追加也可以用重载运算符实现
str += "lalala";
std::cout << str << '\n';
return 0;
}
3.14 insert()
插入
#include <iostream>
using namespace std;
int main(){
string str="to be question";
string str2="the ";
string str3="or not to be";
string::iterator it;
//s.insert(pos,str): 在s的pos位置插入str,下标从0开始
str.insert(6,str2); // to be the question
//s.insert(pos,str,a,n): 在s的pos位置插入str中插入位置a到后面的n个字符
str.insert(6,str3,3,4); // to be not the question
//s.insert(pos,cstr,n): 在pos位置插入cstr字符串从开始到后面的n个字符
str.insert(10,"that is cool",8); // to be not that is the question
//s.insert(pos,cstr): 在s的pos位置插入cstr
str.insert(10,"to be "); // to be not to be that is the question
//s.insert(pos,n,ch): 在s.pos位置上面插入n个ch
str.insert(15,1,':'); // to be not to be: that is the question
//s.insert(s.it,ch): 在s的it指向位置前面插入一个字符ch,返回新插入的位置的迭代器
it = str.insert(str.begin()+5,','); // to be, not to be: that is the question
//s.insert(s.it,n,ch): 在s的it所指向位置的前面插入n个ch
str.insert(str.end(),3,'.'); // to be, not to be: that is the question...
//s.insert(it,str.ita,str.itb): 在it所指向的位置的前面插入[ita,itb)的字符串
str.insert (it+2,str3.begin(),str3.begin()+3); // to be, or not to be: that is the question...
return 0;
}
3.15 replace()
替换
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.";
// 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个字符用str3的第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)
std::cout << str << '\n';
return 0;
}
以上的replace操作可以用insert和erase的操作组合替换,但是replace操作更加方便。
3.16 assign()
为字符串赋新值
#include <iostream>
#include <string>
using namespace std;
int main () {
string str;
string base = "The quick brown fox jumps over a lazy dog.";
// used in the same order as described above:
// 直接把base赋值给str
str.assign(base);
std::cout << str << '\n';
// 把base第10个字符以及后面的8个字符赋给str
str.assign(base, 10, 9);
std::cout << str << '\n'; // "brown fox"
// 把参数中的0到6个字符串赋给str
str.assign("pangrams are cool", 7);
std::cout << str << '\n'; // "pangram"
// 直接使用参数赋值
str.assign("c-string");
std::cout << str << '\n'; // "c-string"
// 给str赋值10个'*'字符
str.assign(10, '*');
std::cout << str << '\n'; // "**********"
// 赋值是10个'-'
str.assign<int>(10, 0x2D);
std::cout << str << '\n'; // "----------"
// 指定base迭代器范围的字符串
str.assign(base.begin()+16, base.end()-12);
std::cout << str << '\n'; // "fox jumps over"
return 0;
}
3.17 erase()
删除
删除操作有三种:
- 指定pos和len,其中pos为为起始位置,pos以及后面len-1个字符串都删除
- 迭代器,删除迭代器指向的字符
- 迭代器范围,删除这一范围的字符串,范围左闭右开
#include <iostream>
#include <string>
int main () {
std::string str ("This is an example sentence.");
std::cout << str << '\n'; // "This is an example sentence."
// 直接指定删除的字符串位置第十个后面的8个字符
str.erase(10, 8);
std::cout << str << '\n'; // "This is an sentence."
// 删除迭代器指向的一个字符
str.erase(str.begin()+9); // "This is a sentence."
std::cout << str << '\n';
// 删除迭代器范围的字符
str.erase (str.begin()+5, str.end()-9);
std::cout << str << '\n'; // "This sentence."
return 0;
}
3.18 compare()
函数
由于string重载了运算符,可以直接用>、<、>=、<=、==、!=来进行比较
或者使用 compare()
函数比较,其和strcmp函数一样,如果两个字符串相等,那么返回0,调用对象大于参数返回1,小于返回-1。 在compare当中还支持部分比较,里面有6个参数可以设置。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
string s1="123",s2="123";
cout<<s1.compare(s2)<<endl;//0
s1="123",s2="1234";
cout<<s1.compare(s2)<<endl;//-1
s1="1234",s2="123";
cout<<s1.compare(s2)<<endl;//1
std::string str1 ("green apple");
std::string str2 ("red apple");
if (str1.compare(str2) != 0)
std::cout << str1 << " is not " << str2 << '\n';
//str1的第6个字符以及后面的4个字符和参数比较
if (str1.compare(6,5,"apple") == 0)
std::cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size()-5,5,"apple") == 0)
std::cout << "and " << str2 << " is also an apple\n";
//str1的第6个字符以及后面的4个字符和str2的第4个字符以及后面的4个字符比较
if (str1.compare(6,5,str2,4,5) == 0)
std::cout << "therefore, both are apples\n";
return 0;
}
3. string 转换为 const char* 、char * 或者 char[]
1、如果要将 string
转换为 const char*
,可以使用string提供的函数 c_str()
,或是函数 data()
data()
除了返回字符串内容外,不附加结束符’\0’- 而
c_str()
返回一个以‘\0’结尾的字符数组
2、const char *c_str()
函数返回一个指向正规C字符串的指针,内容与本string串相同。这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数 c_str()
把string 对象转换成c中的字符串样式。注意:一定要使用 strcpy()
函数 等来操作方法 c_str()
返回的指针。
比如:最好不要这样:
string s = "1234";
const char* p = s.c_str(); // c最后指向的内容是垃圾,因为s对象被析构,其内容被处理
// 加const或者用char *p = (char*)str.c_str(); 强制转换
应该使用如下方式:
3.1 调用 string的 c_str()
函数 [返回的是const char *, 或者使用(char *) 强转成 char *]
#include <iostream>
#include <string>
#include <cstring>
int main() {
char p[20];
string str = "hello world";
// c_str()函数返回一个指向正规C字符串的指针cosnt char *, 内容与本string串相同,以'\0'结尾.
strcpy(p, str.c_str()); // 使用strcpy将返回的字符串拷贝至char p[] 数组
cout << p << endl;
}
3.2 调用 string 的 data()
函数 [返回的是const char *, 或者使用(char *) 强转成 char *]
和上面方法一致,只是返回字符串内容,不附加结束符’\0’
3.3 调用 string 的 copy()
函数 [返回的是 char *]
string str = "hello world";
char p[40];
str.copy(p, 5, 0); // 这里5,代表复制几个字符,0代表复制的位置
*(p+5)='\0'; // 要手动加上结束符!!!
cout << p << endl;
4. char * 、char []转换为 string
4.1 char * 转 string
可以直接赋值
string s;
char *p = "hello world";
s = p;
4.2 char [] 转 string
可以直接赋值
string s;
char ch[] = "hello world";
s = ch;
5. char* 与 char[] 互转
5.1 char[] 转 char*
可以直接赋值
char ch[] = "hello world";
char *p = ch;
5.2 char * 转 char[]
不能直接赋值,可以循环char*字符串逐个字符赋值,也可以使用strcpy()
或 strcpy_s()
等函数。
char *p = "hello world";
char ch[20];
strcpy(ch, p);
总结:char[] 数组转换为其他类型,可以直接赋值。
6. 查找
6.1 find()
函数
主要是查找一个字符串是否在调用的字符串中出现过,大小写敏感。
#include <iostream>
using namespace std;
int main(){
string str ("There are two needles in this haystack with needles.");
string str2 ("needle");
// different member versions of find in the same order as above:
//在str当中查找第一个出现的needle,找到则返回出现的位置,否则返回结尾
size_t found = str.find(str2);
if (found!=string::npos)
cout << "first 'needle' found at: " << found << '\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';
//在str当中查找参数中的字符串
found=str.find("haystack");
if (found!=string::npos)
cout << "'haystack' also found at: " << found << '\n';
//查找一个字符
found=str.find('.');
if (found!=string::npos)
cout << "Period found at: " << found << '\n';
//组合使用,把str2用参数表中的字符串代替
// let's replace the first needle:
str.replace(str.find(str2),str2.length(),"preposition");
cout << str << '\n';
return 0;
}
6.2 rfind()
函数
找最后一个出现的匹配字符串,返回的位置仍然是从前往后数的。
#include <iostream>
using namespace std;
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';
return 0;
}
6.3 find_….of
函数
find_first_of(args)
:查找args中任何一个字符第一次出现的位置find_last_of(args)
:最后一个出现的位置find_fist_not_of(args)
: 查找第一个不在args中的字符find_last_not_of(args)
: 查找最后一个不在args中出现的字符
#include <iostream>
using namespace std;
int main() {
string str1 ("Please, replace the vowels in this sentence by asterisks.");
size_t found1 = str1.find_first_of("aeiou");
//把所有元音找出来用*代替
while (found1!=string::npos) {
str1[found1]='*';
found1=str1.find_first_of("aeiou",found1+1);
}
cout << str1 << '\n';
//在str2中找到第一个不是消协英文字母和空格的字符
string str2 ("look for non-alphabetic characters...");
size_t found2 = str2.find_first_not_of("abcdefghijklmnopqrstuvwxyz ");
if (found2!=string::npos) {
cout << "The first non-alphabetic character is " << str2[found2];
cout << " at position " << found2 << '\n';
}
return 0;
}
find_last_of()
和 find_last_not_of()
与 first
基本相同,就不写例子代码了。
7. 实例
7.1 查找给定字符串并把相应子串替换为另一给定字符串
string 并没有提供这样的函数,所以我们自己来实现。由于给定字符串可能出现多次,所以需要用到 find()
成员函数的第二个参数,每次查找之后,从找到位置往后继续搜索。直接看代码(这个函数返回替换的次数,如果返回值是 0 说明没有替换):
int str_replace(string &str, const string &src, const string &dest) {
int counter = 0;
string::size_type pos = 0;
while ((pos = str.find(src, pos)) != string::npos) {
str.replace(pos, src.size(), dest);
++counter;
pos += dest.size();
}
return counter;
}
7.2 从给定字符串中删除一给定字串
方法和上面相似,内部使用 erase()
完成。代码:
int str_erase(string &str, const string src) {
int counter = 0;
string::size_type pos = 0;
while ((pos = str.find(src, pos)) != string::npos) {
str.erase(pos, src.size());
++counter;
}
return counter;
}
7.3 给定一字符串和一字符集,从字符串剔除字符集中的任意字符
int str_wash(string &str, const string src) {
int counter = 0;
string::size_type pos = 0;
while ((pos = str.find_first_of(src, pos)) != string::npos) {
str.erase(pos, 1);
++counter;
}
return counter;
}
7.4 分割字符串(以逗号分隔符为例,分割得到相应数字)
/*
输入一连串数字,数字之间逗号隔开,把数字存到数组或者向量里。
*/
#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
using namespace std;
int main() {
string str_input;
cout<<"输入一串以逗号为分隔符的数字字符串:"<<endl;
while(cin >> str_input) {
vector<int> nums;
// string->char *
char *s_input = (char *)str_input.c_str();
const char * split = ",";
// 以逗号为分隔符拆分字符串
char *p = strtok(s_input, split);
int a;
while(p != NULL) {
// char * -> int
sscanf(p, "%d", &a);
nums.push_back(a);
p=strtok(NULL, split);
}
cout<<"输出得到的数字:"<<endl;
for(a = 0; a < nums.size(); a++) {
cout<<nums[a]<<endl;
}
}
return 0;
}
8. 数值转换:
在io的部分有过数值和字符串相互转换的例子,使用的是stringstream函数,在c++11当中有定义好的现成的函数取调用,非常方便。
string和数值转换 | |
---|---|
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 |
//注意,下段代码在MinGw中会报错!即使使用c++11编译也一样,无法识别to_string!
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
string s1;
s1=to_string(100);
cout<<s1<<endl;
int a=stoi(s1,0,10)+1;
cout<<a<<endl;
return 0;
}
9. Reference
- https://blog.youkuaiyun.com/tengfei461807914/article/details/52203202
- https://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html
- https://www.cnblogs.com/devilmaycry812839668/p/6353807.html
- https://blog.youkuaiyun.com/hebbely/article/details/79577880
- https://blog.youkuaiyun.com/techfield/article/details/77855620
- http://www.cplusplus.com/reference/string/string/?kw=string