1.string 与getline
string会自动忽略开头的空白,从第一个真正的字符开始读起,直到遇到下一处空白为止。
getline从给定的输入流中读入内容,直到遇到换行符为止。 getline(cin,line)
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">int main(){
string line ;
while (getline(cin,line))
cout<<line<<endl;//每次读入一行直到文件末尾
}</span></span></span></span></span>
2.sting对象的相加string s1="hello",s2="world"
string s3=“hello”+","//错误,两个运算都不是string,每个加法运算符都有一个运算对象是string,
string s4=“hello”+","+s2;//错误字面值直接相加了
string s5=s2+“hello”+",";//正确
3.处理每个字符----用基于范围的for语句(处理string对象中的每一个字符有优势)
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">string s("helloworld");
for(auto c:s)//让编译器决定变量c的类型
cout<<c;</span></span></span></span></span>
使用for语句改变字符串中的字符
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">int main(){
string s("hello world!!!");
for(auto &c:s)<strong>//c为引用</strong>
c=toupper(c);//c为引用,所以赋值语句中将改变s中字符的值//实际上改变了c绑定的字符的值
cout<<s;</span></span></span></span></span>
4.访问string对象中单个字符的方式:1.使用下标(下标必须大于0,小于s.size())
2.使用迭代器
检查下标的合法性:总是设下标的类型为string::size_type,此类型是无符号,可以确保不会小于0,此时只要保证下标小于size()。
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">string s("helloworld");
if(!s.empty())
s[0]=toupper(s[0]);
cout<<s;</span></span></span></span>
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;">int main(){
string s("hello world");
for(decltype(s.size()) index=0;index!=s.size()&&!isspace(s[index]);++index)
s[index]=toupper(s[index]);
cout<<s;</span></span></span></span>
5.标准库类型vector(容器)表示对象的集合,其中所有对象的类型都相同。
使用vector,必须使用适当的头文件。
#include <vectorr>
using std::vector;
注意:vector是模板而非类型。由vector生成的类型必须包含vector中元素的类型,例如vector<int>
引用不是对象,所有不包含引用的vector。甚至组成vector的元素也可以是vector。
vector提供的是初始元素值的列表,只能把初始值都放在花括号里,进行列表初始化,而不能放在圆括号里。
<span style="font-size:14px;"><span style="font-size:14px;">vector<string> s1{"a","ac","ass"};
vector<string> s1("a","ac","ass");//错误</span></span>
可以用vector对象容纳的元素数量和所有元素的统一初始值来初始化vector对象。
<span style="font-size:14px;"><span style="font-size:14px;">vextor<int> s=(10,-1);//10个int类型元素,每个初始化为-1
vector<string> s=(10,"hi");//10个string类型元素,每个初始化为"hi"</span></span>
列表初始值还是元素数量:
花括号-列表初始化;圆括号-提供的值用来构造vector对象(容量)
<span style="font-size:14px;"><span style="font-size:14px;">vector<int> v1(10); //10个元素,每个值初始化为0
vector<int> v2{10}; //1个元素,值为10
vector<int> v3(10,1);//10个元素,值为1
vector<int> v1{10,1}; //2个元素,值为10,1</span></span>
另外想要列表初始化vector对象,花括号里面的值必须与元素类型相同。向vector中添加对象:
先创建一个空vector,在运行时,利用vector的成员函数push_back 向其中添加元素。push_back负责把一个值当成vector对象的尾元素压入(push)到vector对象的尾端(back)。
<span style="font-size:14px;"><span style="font-size:14px;">vector<int> v2;//空vector对象
for(int i=0;i!=100;i++)
v2.push_back(i);//依次把整数值放到v2尾端</span></span>
如果循环体内部包含有向vector对象添加元素的语句,不能使用for循环。使用size_type:
需要首先指定它是由哪种类型定义的,vector对象的类型总是包含着元素的类型。
<span style="font-size:14px;">vector<int> size_type;//正确
vector::size_type;//错误</span>
下标运算符:
vector对象(以及string对象)的下标运算符可以用于访问已经存在的元素,而不能用于添加元素。
只能对确实已经存在的元素进行下标操作。因此确保下标合法的一种有效手段就是尽可能使用范围for语句。
练习题:
从cin中输入一组词,并把它们全部存入一个vector对象,然后设法把所有词都改成大写形式。输出改变后的结果,每个词占一行。
for(auto s:v1)
for(auto c:s)//从vector v1中取出每个字符串再在字符串中遍历,改变值
<span style="font-size:14px;">#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
vector<string> v1; //空的vector对象
string word;
while(cin>>word) //输入字符
v1.push_back(word); //添加字符
for(auto s:v1){ //依字符串遍历
for(auto &c:s) //
c=toupper(c); //大写改变值,用&
cout<<s<<endl;
}
return 0;
}</span>
读入一组整数并把他们存入到一个vector对象,将每对相邻整数的和输出输出。
<span style="font-size:14px;">#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
vector<int> v1; //空的vector对象
int word;
while(cin>>word) //输入字符
v1.push_back(word); //添加字符
for(decltype(v1.size()) index=0;index!=v1.size()-1;index+=2)
{v1[index]+=v1[index+1];
cout<<v1[index]<<endl;
}
if(v1.size()%2!=0)
cout<<"最后一个数没有求和"<<endl;
return 0;
}</span>
更改程序,使得第一个数和最后一个元素的和相加,接着输出第二个和倒数第二个元素的和,以此类推。
<span style="font-size:14px;">#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(){
vector<int> v1; //空的vector对象
int word;
while(cin>>word) //输入字符
v1.push_back(word); //添加字符
for(decltype(v1.size()) index=0;index!=v1.size()/2;++index)//此处更改一下就行
{v1[index]+=v1[v1.size()-1-index]; //此处更改,其余不变
cout<<v1[index]<<endl;
}
if(v1.size()%2!=0)
cout<<"中间一个数没有求和"<<endl;
return 0;
}</span>
使用迭代器可以访问某个元素,也可以从一个元素移动到另外一个元素。分为有效和无效之分。有效的迭代器或者指向某个元素,或者指向容器的尾元素的下一位置,其他情况都属于无效。
有效的迭代器同时具有返回迭代器的成员,比如拥有begin和end成员。
auto b=v.begin();
auto c=v.end();//end负责返回指向容器或者(string对象)的尾元素的下一位置。
//依次处理s的字符直至我们处理完成全部字符或者遇到空白。
string s("some string");
for(auto it=s.begin();it!=s.end();++it)
*it=toupper(*it);
cout<<s;
//
养成使用迭代器和!=的习惯。
vector<int>::itertaor it;it能读写vector<int>的元素
string::iterator it2;//it2能读写string对象中的字符
begin 和and返回的具体对象由对象是否是常量来决定,如果对象是常量,,begin和and则返回const_iterator,否则返回iterator;
解引用和成员访问操作:
解引用迭代器可以获得迭代器所指的对象。
(*it).empty();//*it的括号必不可少.运算优先级高于*
it->men与(*it).men表达意思相同
某些对vector对象的操作会使迭代器失效:(使用了迭代器的循环体,都不要向迭代器所属的容器中添加元素)
1.不能在范围for循环中向vector对象中添加元素
2.任何一种可能改变vector对象容量的操作,比如push_back都会使vector对象的迭代器失效。
迭代器运算:
iter+n:迭代器新指的位置比原来相比向前移动了若干个元素。-就相当于往后移动了n个元素
iter1-iter2:表示两个迭代器之间的距离。参与运算的两个迭代器必须指向同一个容器的元素,或者尾元素的下一位置。
使用迭代器,把text的第一段全部改写成大写形式:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
using namespace std;
int main(){
vector<string> text;
string i;
while(cin>>i)
text.push_back (i);
auto it=text.begin();{ //保证进入toupper里面的是单个字符
for(auto itr=it->begin();itr!=it->end();++itr)
*itr=toupper(*itr);
}
for(auto it=text.begin();it!=text.end();++it)
cout<<*it;
return 0;}