目录
3.2 string(size_type n, char c)
3.5 string(const char *s, size_type n)
3.7 string(const string &str, string size_type pos = 0, size_type n = npos)
3.8 string(string && str) noexcept
3.9 string(initializer_list it)
前言
由于工作需要,要补一下C++的知识,主要是string类、vector模板类和map模板类,以前在学校里学C++只学了类、对象、继承、多态等一些面向对象的基本思想,并没有接触到标准模板库(STL)的内容。本篇文章记录下自己对STL中,string类的学习笔记。以后应该还会继续学习vector(矢量)模板类、map模板类。
初学的同学我们可以交流、补充我的不足,大佬光临还希望能提出建议。无论如何,您的建言我都将感激不尽~。
本文参考书籍:《C++ Primer Plus》。
一、string类 头文件
#include <string>
注意,<string>头文件不同于<string.h>!前者提供了string类,后者提供了C-风格的字符串操作函数。
<string>头文件提供了大量的方法,其中包括了若干构造函数,字符串赋值、合并、比较、查找、字串、重载运算符等。
二、string和字符数组简单对比
string声明的是简单变量;字符数组声明的是数组。
string类能让程序自动处理string大小;字符数组定长。
2.1 定义
字符数组:char a[20]; 或 char a[20] ="abc cba"; 或 char a[] = "abc cba";
string类 :string a; 或 string a = "abc cba";
2.2 赋值
字符数组:char b[10]; strcpy(b, a); //数组b必须大于等于数组a的长度。
string类 :string b; b = a; //没有限制,string类可自动调节string长度
使用getline输入时:
字符数组:char a[20]; cin.getline(a,20); cout << strlen(a); //需要指定最大长度,避免超越数组边界
string类 :string a; getline(cin, a); cout << strlen(a);
2.3 附加
字符数组:char c[20] = "#: "; strcat(c, a); //数组c的长度定义时,必须大于strlen(a)+strlen(c)
string类 :string c = "#: "; c += a; //string对象c的长度定义时,没有限制
2.4 长度
字符数组:int len1 = strlen(c);
string类 :int len2 = c.size();
//都去掉'\0'后的长度。
只定义,不初始化时的长度
字符数组:char a[20]; cout << strlen(a); //等于27(一种可能),未初始化时的字符数组长度是”未定义“的,没有意义。
string类 :string a; cout << a.size(); //等于0,定义的,有意义。
三、string类的构造函数
缩写NBTS(null-terminated string)表示以空字符结束的字符串--这是传统的C-字符串
3.1 string(const char *s)
解释:将string对象初始化,s指向NBTS
实例: string one("Hank!");
cout << one << endl;
结果:Hank
3.2 string(size_type n, char c)
解释:创建一个包含n个元素的string对象,其中每个元素都被初始化为字符c。
实例: string two(4, '$');
cout << two << endl;
结果:$$$$
3.3 string(const string &str)
解释:将一个string对象,初始化为string对象str(复制构造函数)
实例: string three(one);
cout << three << endl;
结果:Hank (复制了one)
3.4 string()
解释:创建一个默认的string对象,长度为0.
实例: string four;
cout << four << endl;
结果:(空)
3.5 string(const char *s, size_type n)
解释:将string对象初始化为s指向的NBTS的前n个字符,即使超过了NBTS结尾。
实例: char alls[] = "Leiney is my gril-friend!";
string five(alls, 6);
cout << five << endl;
结果:Leiney
3.6 template<class Iter>
string(Iter begin, Iter end)
解释:将string对象初始化为区间[begin, end)内的字符,其中begin和end用于指定位置。Iter看作指针,比如(char *)。所以需要传入指针或地址。注意:第一个字符位置为0。
实例: char alls[] = "Leiney is my gril-friend!";
string six(alls+0, alls+3); //方法1,指针方式调用(char *)。范围:[9,11)-->9,10
string six_2(&alls[0], &alls[3]); //方法2,地址方式调用。范围:[9,11)-->9,10
cout << six << six_2 << endl;
结果:LeiLei
3.7 string(const string &str, string size_type pos = 0, size_type n = npos)
解释:将一个string对象初始化为对象str中,从pos位开始到结尾的字符,或从pos位开始之后的n个字符。注意:第一个字符位置为0。
实例: char alls[] = "Leiney is my gril-friend!";
string seven(alls, 0, 6);
cout << seven << endl;
结果:Leiney
3.8 string(string && str) noexcept
解释:c++11新增,将一个string对象初始化为string对象str,并可能修改str。这是移动构造函数:新建的string为str的副本,与复制构造不同的是,它不保证将str视为const。
实例:
string test(const string & x)
{
return x;
}
main()
{
char alls[] = "Leiney is my gril-friend!"
...
string eithg(test(alls));
cout << eight << endl;
...
}
结果:Leiney is my gril-friend!
3.9 string(initializer_list<char> it)
解释:C++11新增,将一个string对象初始化为初始化列表il中的字符。(一般来说,用处不大)
实例: string nine = {'H', 'a', 'n', 'k'};
cout << nine;
结果:Hank
3.10 一个简单的测试
/*************************************************************************
> File Name: string_1.cpp
> Author: hank
> Mail: 34392195@qq.com
> Created Time: 2020年07月27日 星期一 19时18分27秒
************************************************************************/
#include<iostream>
#include<string>
using namespace std;
string test(const string& x)
{
return x;
}
int main()
{
char alls[] = "Leiney is my gril-friend!";
cout << endl << "***1 string(const char *s)"<< "***" << endl;
string one("Hank!");
cout << one << endl;
//Hank!
cout << endl << "***2 string(size_type n, char c)" << "***" << endl;
string two(4,'$');
cout << two << endl;
//$$$$
cout << endl << "***3 string(const string &str)" << "***" << endl;
string three(one);
cout << three << endl;
//Hank!
cout << endl << "***4 string()" << "***" << endl;
string four();
cout << four << endl;
//
cout << endl << "***5 string(const char *s, size_type n)" << "***" << endl;
string five(alls, 6);
cout << five << endl;
//Leiney
cout << endl << "***6 template<class Iter> string(Iter begin, Iter end)" << "***" << endl;
string six(alls + 0, alls + 3);
string six_2(&alls[0], &alls[3]);
cout << six << six_2 << endl;
//LeiLei
cout << endl << "***7 string(const string &str, string size_type pos = 0, size_type n = npos)" << "***" << endl;
string seven(alls, 0, 6);
cout << seven << endl;
//Leiney
cout << endl << "***8 string(string && str) noexcept" << "***" << endl;
string eight(test(alls));
cout << eight << endl;
//Leiney is my gril-friend!
cout << endl << "***9 string(initializer_list<char> it)" << "***" << endl;
string nine = {'H','a','n','k'};
cout << nine << endl;
//Hank
}
【新手提示】
g++ string_1.cpp -std=c++11 //编译时不要忘了参数
当然,为了方便,可以使用alias 取别名的方式,重新指定g++的编译方式
alias g++ ‘g++ -std=c++11’
以后,直接g++ string_1.cpp就可以了。
四、string类输入方式
4.1 对于C-风格字符串有三种方式
char info[100];
(1)cin >> info; //输入一个词,从第一个非空白符(如空格/换行符/制表符)到最后一个非空白符。
(2)cin.getline(info, 100); //输入一行
(3)cin.get(info, 100); //输入一行
对于cin.getline:读取所有字符,遇到'\n'时止,'\n'从输入缓冲区中删除掉,不影响下一个读操作。
对于cin.get:读取所有字符,遇到'\n'时止,'\n'留在输入缓冲区中。'\n'将影响下一个读操作。
另外,cin.getline可指定输入边界,如指定‘:’代替\n成为输入边界:cin.getline(info, 100, ':');
4.2 对于string对象,有两种方式
string stuff;
(1)cin >> stuff; //输入一个词,从第一个非空白符(如空格/换行符/制表符)到最后一个非空白符。
(2)geline(cin, stuff); //输入一行
同样的,getline可指定输入边界,如指定‘:’代替\n成为输入边界:getline(cin, ':');
4.3 cin.getline和getline的区别
用于C-风格字符串的cin.geline,不能自动调整字符串的大小。
用于string对象的getline可以自动调整字符串的大小,使其刚好存储一个字符串。
char f1[10];
string f2;
cin.getline(f1, 10); //可能超出10的限制,造成问题
getline(cin, f2); //自动调整字符串长度
五、string类运算符
string s1, s2;
string s2;
s1 = "hello,"; // ”=“ 赋值
s2 = "Leiney!";
s1 += s2;
s2 += "I am Hank." // ”+=“ 追加
s3 = s1 + s2 // ”+“ 拼接
s3 = s1 + "Long time no see!" + " " + s2 + "\n";
六、string类关系运算符
字符串比较:从前向后,对比每一个字符,按照ASCII值小的,字符串小。
string类对6种关系运算符都进行了重载:!= < <= == >= >
除了6中关系运算符,在关系运算中,常用的还有两个对象:s.empty()、s.size()
s.empty()判断string是否空,空返回true,否则返回false。
s.size()和length()用于获取string的字符个数。length()来自较早版本的string类;size()为STL提供兼容性而添加。
简例:
int main()
{
string str1;
getline(cin, str1); //input relationship
if(s.size() < 7) //字节数
{
if(s.empty()) //判空
{
cout << "string empty" <<endl;
}
else if(s == "love") //关系符
{
cout << "they are fall in love" << endl;
}
else
{
cout << "relation is not clear" << endl;
}
}
else
{
cout << "string input too long" << endl;
}
return 0;
}
七、重载的find()方法及其簇(查找子串)
string::npos是字符串可存储的最大字符数,通常是无符号int和无符号long的最大取值
方法原型:
(1)size_type find(const string &str, size_type_pos = 0)const
(2)size_type find(const char *s, size_type pos = 0)const
(3)size_type find(const char *s, size_tpye pos = 0, size_type n)
(4)size_type find(const ch, size_type pos = 0)const
对于(1):从字符串pos位置开始,查找子串str。成功则返回首次出现时首字符索引,失败返回string::npos。
对于(2):同(1)
对于(3):从字符串pos位置开始,查找子串s前n个字符组成的字符串。成功则返回首次出现时首字符索引,失败返回string::npos。
对于(4):从字符串pos位置开始,查找字符s。成功则返回首次出现时字符的索引,失败返回string::npos。
find相关的其它方法,它们的重载特征都和find相同:
rfind():查找子字符串或字符最后一次出现的位置。
find_first_of():在字符串中,查找字符串参数中任何一个字符,首次出现的位置。
find_last_of():在字符串中,查找字符串参数中任何一个字符,末次出现的位置。
find_first_not_of():在字符串中,查找不是字符串参数中任何一个字符,首次出现的位置。
find_last_not_of():在字符串中,查找不是字符串参数中任何一个字符,末次出现的位置。
八、string库实际上基于一个模板类
template<class charT, class traits = char _traits<charT>,
class Allocator = allocator<charT>>
basic_string{...};
模板basic_string有4个具体化,每个具体化都有一个typedef名称:
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
typedef basic_string<char16_t> u16string;
typedef basic_string<char32_t> u32string;
Allocator是一个管理内存分配的类,他们使用new和delete,申请和注销的过程是自动的。所以数据在堆区。
好文章参考
http://c.biancheng.net/view/400.html
https://blog.youkuaiyun.com/weixin_33939380/article/details/94093365