续接模板
当函数模板和函数同时存在的时候,优先调用函数,除非是类型优先匹配的情况
他们套用相同的模板但不是相同的类型
string
string 是一个类模板的重命名,套用的是typedef basic_string string;
iterator 迭代器
String 的一些常用的知识
表示无符号整数的最大值,是静态变量所有类都有
reverse 字符串翻转
范围是左闭右开
, last 提前减去1,reverse的参数是迭代器,str.begin()是当前字符的下标,str.end(),是最后一个字符的下个位置的下标
rbegin() 以最后的位置为起始位置,rend()以起始的位置为结束的位置
string str = "hehe";
reverse(str.begin(),str.end());
string s = "123456";
auto it = s.rbegin();
while (it != s.rend())
{
cout << *it;
++it;
}
对符号[ ] 的重载
使得string 也可以像数组一样使用
string s1 = “123123”;
s1[0] = ‘2’;
但是如果前面加了const 表示只读,
string 的扩容机制
capacity 大于size(),多开几个预留的空间,当字符串等于capacity的时候会扩容.
vs 下还是会多开,linux下不会
int main()
{
string str("Hello Bit.");
str.reserve(111);
str.resize(5);
str.reserve(50);
cout<<str.size()<<":"<<str.capacity()<<endl;
return 0;
}
分析:
str.reserve(111); //调整容量为 111
str.resize(5); //调整元素个数为 5
str.reserve(50); //调整容量为 50,由于调整的容量小于已有空间容量,故容量不会减小
所以size=5 capacity=111
会缩容,但也只会缩小到size
append
不用const char* s,效率低,使用+=
insert 和 erase
//insert 常用于头插
string s = "5678";
s.insert(0, 1, '1');//在0的位置插入一个字符
cout << s << endl;
s.insert(s.begin(), 'p');//也可以这样头插
cout << s;
// erase
cout << s << endl;
s.erase(0,1);//从下标为0的位置开始删除1个字符
cout << s;
replace 和 find
string s1("hello world hello caixukun");
//所有的空格替换为20%
// find 正向查找 , 找到了就返回当前的下标,未找到,就返回 npos
size_t pos = s1.find(' ', 0);//从下标为零的位置往后找第一个出现的
while (pos!= string::npos)
{
s1.replace(pos,1,"20%");//将下标为pos 的替换为20%,替换一个
pos += 3;//从新的位置开找,越过20%
pos = s1.find(' ', pos);
}
cout << s1;
但是这里replace不建议使用,因为每次的替换,都需要后面的字符串往后移动,时间复杂度太高
方法二
string s1("hello world hello caixukun");
//所有的空格替换为20%
// find 正向查找 , 找到了就返回当前的下标,未找到,就返回 npos
string str;
for (auto ch : s1)
{
if (ch == ' ')
{
str += "20%";
}
else {
str += ch;
}
}
cout << str;
rfind
string s1("hello world d");
// rfind 找到最后一次元素出现的下标
size_t it =s1.rfind('d');
cout << it;
fopen和c_str
- c_str()函数返回一个指向正规C字符串的指针常量, 内容与本string串相同。
- 这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。
- 注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针。
比如:最好不要这样:
1 char* c;
2 string s="1234";
3 c = s.c_str();
//error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
c最后指向的内容是垃圾,因为s对象被析构,其内容被处理,同时,编译器也将报错——将一个const char *赋与一个char *。
c_str函数的返回值是const char*的,不能直接赋值给char*,所以就需要我们进行相应的操作转化「通过strcpy函数」。
应该这样用:
1 char c[20];
2 string s="1234";
3 strcpy(c,s.c_str());
这样才不会出错,c_str()返回的是一个临时指针,不能对其进行操作。
c++ 的打开文件方式和c有些差别
string filename("源.cpp");
FILE* fout = fopen(filename.c_str(), "r");
char ch = fgetc(fout);
while (ch != EOF)
{
cout << ch;
ch = fgetc(fout);
}
substr
(size_type _Off = 0,size_type _Count = npos)
注意这里的缺省参数无符号整型
一种构造string的方法
形式 : s.substr(pos, len)
返回值: string,包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
异常 :若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾
string str("https://legacy.cplusplus.com/reference/string/string/substr/");//取域名
string sub1;
int pos1 = str.find(':');
int pos2 = str.find('/',pos1+3);
sub1 = str.substr(pos1 + 3, pos2-pos1-3);
cout << sub1;
find_first_of 和find_last_of
find_first_of ()正向查找在原字符串中第一个与指定字符串(或字符)中的某个字符匹配的字符,返回它的位置。若查找失败,则返回npos。(npos定义为保证大于任何有效下标的值。)
find_first_not_of()正向查找与与其某个字符不匹配的第一个字符,并返回第一个的下标
find_last_of逆向查找在原字符串中最后一个与指定字符串(或字符)中的某个字符匹配的字符,返回它的位置。若查找失败,则返回npos。(npos定义为保证大于任何有效下标的值。)`
string str("rab0dec");
size_t found = str.find_last_of("abc");
cout << found;//6
find_last_not_of()函数
正向查找在原字符串中最后一个与指定字符串(或字符)中的任一字符都不匹配的字符,返回它的位置。若查找失败,则返回npos。(npos定义为保证大于任何有效下标的值。)
- string str=“abcdefab”;
- cout<<str.find_last_not_of(‘h’)<<endl;//第二个参数为0,默认从npos逆向查。原串倒数第一个字符b和h就不同,故输出b的小标7。
- cout<<str.find_last_not_of(“ab”,6)<<endl;//从原串下标为6开始逆向查询,第一个a和待查串中的字符a相同,不符合,故继续逆向比较。f和待查子串任一字符不同,故输出f的下标5。
getline
string a;
cin>>a;//默认输入结束的时候用空格和换行分割,但是string
getline 默认规定换行才是分割
getline(cin,a);