字符串,vector,queue,stack

字符串:

C风格字符串:

C风格字符串是指以 ‘\0’(null)空字符结束的字符数组。

字符和字符串字面值:

由单引号括起来的一个字符称为char型字面值。双引号括起来的零个或多个字符则构成字符串型字面值,也同样属于C风格字符串。因为某些历史原因,也为了与C兼容,所以C++语言中的字符串字面值并不是标准库类型string的对象。切记,字符串字面值与string是不同的类型但标准库允许把字符字面值和字符串字面值转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。

'a'	//字符字面值
"Hello World!"	//字符串字面值

字符串字面值的类型实际上是由常量字符构成的数组。编译器在每个字符串的结尾处添加一个 ‘\0’ ,因此,字符串字面值的实际长度要比它的内容多1。例如:字面值’A’表示的就是单独的字符A,而字符串"A"则代表了一个字符的数组,该数组包含两个字符:一个是字母A,另一个是空字符。

标准库类型string:

使用string类型必须首先包含string头文件。

#include<string>

string类型属于模板类,所以我们使用的都是string类的对象,因此有:定义和初始化string对象:
可以通过默认的方式初始化一个string对象,这样就会得到一个空的string,也就是说,该string对象中没有任何字符。如果提供了一个字符串字面值,该字面值中除了最后那个空字符外其他所有的字符都被拷贝到新创建的string对象中去。如果提供的是一个数字和一个字符,则string对象的内容是给定字符连续重复若干次后得到的。

string s1;//默认初始化,s1是一个空字符串
string s2="China";//s2是字面值"China"的副本,除了字面值最后的那个空字符外
string s3(n,'c');//把s4初始化为由连续n个字符c组春的串
string s4=s3;//拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去,s4
//是s3的一个副本
string s5(s3);//直接初始化
string s6("China");//等同于s2

为string对象赋值: 对于string类而言,允许把一个对象的值赋给另外一个对象。


string s1="China";
string s2=s1;

***********string对象上的操作;

os<<s	//将s写到输出流os当中,返回os
is>>s	//从is中读取字符串赋给s,字符串以空白分隔,返回is
getline(is,s)//从is中读取一行赋给s,返回is
s.empty()//s为空返回true,否则返回false
s.size()//返回s中字符的个数
s[n]//返回s中第n个字符的**引用**,位置n从0计起
s1+s2//返回s1和s2连接后的结果
s1=s2//对于string类而言,允许把一个对象的值赋给另外一个对象,用s2的副本代替
//s1中原来的字符
s1==s2//如果s1和s2中所包含的字符完全一样,则它们相等返回true,否则返回false
s1!=s2
<,<=,>,>=

使用cin>>读写string对象:

string s;
cin>>s;
cout<<s;

在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等),并从第一个真正的字符开始读起,直到遇到下一处空白为止。

string word;
while(cin>>word)//cin>>word返回cin流
	cout<<word<<endl;
//当遇到文件结束标记或非法输入循环才结束。

使用getline读取一整行:
有时我们希望能在最终得到的字符串中保留输入时的空白,这时应该用getline函数代替原来的>>运算符。getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)。getline只要一遇到换行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此。如果输入真的一开始就是换行符,那么得到的结果是个空string。

string line;
while(getline(cin,line)//返回它的流参数
	cout<<line<<endl;
//每次读入一整行,直至到达文件末尾

s.size()操作:
返回string对象的长度(即string对象中字符的个数)。
返回一个无符号的整型数。 因此切记,如果在表达式中混用了带符号数和无符号数将可能产生意想不到的结果。 例如,假设n是一个具有负值的int,则表达式s.size()<n的判断结果几乎肯定是true,这是因为负值n会自动地转换成一个比较大的无符号值。

字符串的比较==,!=,<,<=,>,>= :
上述运算符都依照(大小写敏感的)字典顺序:
1、如果两个string对象的长度不同,而且较短的string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2、如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。

+运算符:
1、对string对象使用加法运算符(+)的结果是一个新的string对象,它所包含的字符由两部分组成:前半部分是加号左侧string对象所含的字符、后半部分是加号右侧string对象所含的字符。另外,复合赋值运算符(+=)负责把右侧string对象的内容追加到左侧string对象的后面。

string s1="Hello";
string s2="World\n";
string s3=s1+s2;//s3:HelloWorld\n
s1+=s2;//s1等价于s3

2、字面值和string对象相加:
标准库允许把字符字面值和字符串字面值转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。
当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须保证每个加法运算符+两侧的运算对象至少有一个是string。

string s1="Hello";
string s2="World";
string s3=s1+","+s2+'\n';
string s4="hello"+",";//错误
string s5=s1+","+"world";//其中子表达式s1+","结果是一个string对象,它同时
//作为第二个加法运算符的左侧运算对象。
string s6="hello"+"world"+s2;//错误

处理string对象中的字符:

isalpha(c)//当c是字母是为真
isdigit(c)//当c是数字时为真
islower(c)//当c是小写字母时为真
isupper(c)//当c是大写字母时为真
isspace(c)//当c是空白时为真(即c是空格、横向制表符、纵向制表符、回车符、
//换行符、进纸符中的一种)
ispunct(c)//当c是标点符号时为真

string的其他重要方法(都为下标版本,不涉及迭代器):
1、find操作
find函数完成最简单的搜索,它查找参数指定的字符串或字符,若找到,则返回第一个匹配位置的下标,否则,返回npos。npos是一个无符号类型并被初始化为-1,这意味着npos等于任何string最大的可能大小。
s.find(args)查找s中args第一次出现的位置
args:
[c,pos] 从s中位置pos开始查找字符c。pos默认为0
[s2,pos] 从s中位置pos开始查找字符串s2。pos默认为0
[cp,pos] 从s中位置pos开始查找指针cp指向的以空字符结尾的C风格字符串。pos默认为0

2、substr操作:
返回一个string,它是原始string的一部分或全部的拷贝。可以传递给substr一个可选的开始位置和计数值。
s.substr(pos,n)
返回一个string,包含s中从pos开始的n个字符的拷贝。pos默认值为0。n默认值为s.size()-pos,即拷贝从pos开始的所有字符。

string s("Hello Wordl");
string s1=s.substr(6);//World
string s2=s.substr(0,5);//Hello
strin s3=s.substr(12);//抛出out_of_range异常

3、insert操作
s.insert(pos,args)
在pos之前插入args指定的字符串或字符,返回一个一个指向s的引用。

4、erase操作
s.erase(pos,len)
删除从位置pos开始的len个字符,如果len被省略,则删除从pos开始直至s末尾的所有字符。返回一个指向s的引用。

5、replace操作
s.repalce(pos,len,args)
删除s中pos位置开始的n个字符,替换为args指定的字符。

args:
[str] 字符串str
[str,pos,len] str中从pos开始最多len个字符
[cp] cp指向以空字符结尾的字符数组,insert不支持
[cp,len]
[n,c] n个字符c

标准库类型vector:

初始化vector对象的方法:
要使用vector,必须包含适当的头文件

#include<vector>

vector是一个类模板,对于类模板来说,我们通过提供一些额外信息来指定模板到底实例化什么样的类,需要提供哪些信息由模板决定。**提供信息的方式总是这样:即在模板名字后面跟一对尖括号,在括号内放上信息。**如:

vector<int> ivec;
vector<Student> Stu;

vector能容纳绝大多数类型的对象作为其元素,但因为引用不是对象,所以不存在包含引用的vector。除此之外,其他大多数(非引用)内置类型和类类型都可以构成vector对象,甚至组成vector的元素也可以是vector。

定义和初始化vector对象:

vector<T> v1;//v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1);//v2包含v1中所有元素的副本
vector<T> v3=v1;//等价于v2(v1)
vector<T> v4(n);//v4中包含了n个重复执行值初始化的对象
vector<T> v5(n,val);//v5中包含了n个重复的元素,每个元素的值都是val
vector<T> v6={a,b,c...};//v6中包含了初始值个数的元素,每个元素被赋予相应的
//初始值
vector<T> v7{a,b,c...};//等价于上式,两式都属于C++11新标准

事实上,最常见的方式就说先定义一个空vector,然后当运行时获取到元素的值后再逐一添加。

为vector对象赋值: 允许把一个vector对象的元素拷贝给另外一个vector对象。此时,新vector对象的元素就是原vector对象对应元素的副本。注意两个vector对象的类型必须相同

vector<int> ivec;
vector<int> ivec2;
ivec2=ivec;

容器中元素的值初始化:

通常情况下,可以只提供容器容纳的元素数量而略去初始值。此时库会创建一个值初始化的元素初值,并把它赋给容器中的所有元素。这个初值由容器中的元素的类型决定。如果只提供了元素的数量而没有设定初始值,只能使用直接初始化。

vector<int> v1(10);
vector<int> v2=10.//错误

如果容器对象的元素是内置类型,比如int,则元素初始值自动设为0。如果是某种类类型,比如string,则元素由类默认初始化(执行类的默认构造函数)。

vector对象的操作:

v.push_back(val);//把val的拷贝加到vector对象的尾端
v.pop_back();//删除c中尾元素
v.empty();
v.size();
v[n];//返回v中第n个位置上元素的**引用**
v1=v2;//用v2中元素的拷贝替换v1中的元素
v1={a,b,c...}
v1{a,b,c...}用列表中元素的拷贝替换v1中的元素,适用于C++11标准
v1==v2;
v1!=v2;v1和v2相等当且仅当它们的元素数量且对应位置的元素都相同
<,<=,>,>=//以字典序进行比较

字典序:如果两个vector对象的容量不同,但是再相同位置上的元素值都一样,则元素较少的vector对象小于元素多的vector对象;若元素的值有区别,则vector对象的大小关系由第一对相异的元素值的大小关系决定。

不能使用下标形式添加元素 ! 只能使用push_back()

列表初始化容器只能用于C++11标准。

使用迭代器:

所有容器都拥有名为begin和end的成员,其中begin成员返回指向第一个元素的迭代器;end成员返回指向容器“尾元素的下一位置”的迭代器,也就是说,该迭代器指示的是容器的一个本不存在的“尾后”元素,称为“尾后迭代器”。如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回的是const_iterator;如果对象不是常量,返回iterator。
const_iterator和常量指针类似,能读取但不能修改它所指的元素,相反,iterator的对象可读可写。如果vector对象或string对象是一个常量,只能使用const_iterator,如果容器不是常量,那么既能使用iterator也能使用const_iterator。

vector<int> v1;
vector<int>::iterator it;//it能读写vector<int>的元素
it=v1.begin();
vector<string>::const_iterator it2;//it2只能读元素,不能写元素

cbegin和cend专门用于得到const_iterator的迭代器,但只能用于C++11标准。

迭代器的操作:

*iter;//解引用迭代器可获得迭代器所指的对象,返回迭代器iter所指元素的引用
(*iter).empty();//如果该对象的类型恰好是类,就有可能希望进一步访问它的成员
//第一个圆括号必不可少,此时访问对象的empty()函数
iter->empty();//上式的简化
++iter;//iter前移
--iter;//iter后移
iter1==iter2;//判断两个迭代器是否相等,如果两个迭代器指示的是同一个元素,
iter1!=iter2;//或者它们是同一个容器的尾后迭代器,则相等;反之,不相等。


iter+n;//迭代器加上一个整数仍得一个迭代器,新迭代器指示的位置比原理相比向前
//移动了n个元素
iter-n;//迭代器减去一个整数仍得一个迭代器,新迭代器指示的位置比原理相比向后
//移动了n个元素

iter+=n;
iter-=n;

iter1-iter2;//两个迭代器相减的结果是它们之间的距离。
//不支持两个迭代器相加
>,>=,<,<=//迭代器的关系运算符,但与比较的两个迭代器必须合法而且指向同一个
//容器的元素(或者尾元素的下一位置),如果某迭代器指向的容器位置在另一个迭代
//器所指位置之前,则说明前者小于后者

与旧代码的接口:

混用string对象和C风格字符串:
1、允许使用以空字符结束的字符数组来初始化string对象或为string对象赋值。
2、在string对象的加法运算中允许使用以空字符结束的字符数组作为其中一个运算对象(不能两个运算对象都是)
上述性质反过来就不成立了:如果程序的某处需要一个C风格字符串,无法直接用string对象代替它。例如,不能用string对象直接初始化指向字符的指针。为了完成改功能,string专门提供了一个名为c_str的成员函数:

string s("Hello World");
char *str=s;//错误,不能用string对象初始化char *
const char *str=s.c_str();//正确

c_str返回值是一个C风格的字符串。也就是说,函数的返回结果是一个指向以空字符结尾的字符数组,返回类型是const char *,从而确保我们不会改变字符数组的内容。但是如果后续的操作改变了s的值就可能让之前返回的数组失去效用。

使用数组初始化vector对象:
不允许使用一个数组为另一个内置类型的数组赋初值,也不允许使用vector对象初始化数组。相反的,允许使用数组来初始化vector对象。要实现这一目的,只需要指明拷贝区域的首元素地址和尾后地址就可以了:

int int_arr[]={0,1,2,3,4};//数组可用列表初始化但容器只有在C++11标准下才行
vector<int> ivec=(begin(int_arr),end(int_arr));//begin,end负责返回数组
//的首迭代器和尾后迭代器,但只适用于C++11标准
vector<int>ivec2=(int_arr+1,int_arr+4);//初始化vector对象的值也可能仅是
//数组的一部分

三种容器适配器:

1、栈stack

#include<stack>

stack<T> s;

s.pop();//删除栈顶元素,但不返回该元素值
s.push(item);
s.top();//返回栈顶元素,但不将该元素弹出栈

2、队列queue和优先队列priority_queue

#include<queue>

queue<T> q;

q.push(item);//在queue末尾或priority_queue中恰当位置创建一个元素
q.pop();//弹出queue的首元素或priority_queue的最高优先级的元素,但不返回此元素
q.front();//返回首元素,但不删除此元素
q.back();//只适用于queue
q.top();//返回最高优先级元素,但不删除此元素,只适用于priority_queue

所有容器适配器都支持的操作:

A a;//创建一个名为a的空适配器
A a(c);//创建一个名为a的适配器,带有容器c的一个拷贝
==,!=,<,<=,>,>=;//所有适配器都支持所有的关系运算符,这些运算符返回底层容器
//的比较结果
a.empty();
a.size();

所有容器都支持的操作:

//迭代器:
iterator
const_iterator
begin();
end();

//构造函数:
C c;
C c1(c2);
C c(b,e);//[b,e)是一对迭代器

//大小
c.size();
c.empty();

所有迭代器都支持的操作:

*it;
it->empty();
it++;
it1==it2;
it1!=it2;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

且放白鹿青涯间

你的打赏将是我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值