字符类型和字符数组( 字符值知识点)要提前了解一下,能更好的了解string
string类型支持长度可变的字符串 在头文件 #include<string>中
一:string对象的定义和初始化
string s1; | 默认构造函数,s1位空串 |
string s2(s1); | 将s2初始化为s1的一个副本 |
string s3("value"); | 将s3初始化为一个字符串字面值副本 |
string s4(n,'c') | 将s4初始化为字符'c'的n个副本 |
当没有明确指定对象初始华式时,系统使用默认构造函数
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1;
s1="chenchen";
cout<<s1<<endl;
string s2(s1);
cout<<s2<<endl;
string s3("value");
cout<<s3<<endl;
string s4(10,'c');
cout<<s4<<endl;
return 0;
}
二:string对象的读写
对:cin>>s;//和scanf()类似
从标准输入读取string,并将读入的串存储在s中。
a.读取并忽略开头所有的空白字符(如空格,换行符,制表符,进纸符)
b.读取字符直至再次遇到空白符,读取终止
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
int T;
cin>>T;
//如果没有这个getchar()那么s首先会把我们按空格给s,这里我们要注意下
//cin是不会这样的
//同样的是gets()也会和getline()出现一样的情况
/*
比如输入:
1 adfs
输出:adfs有个空格
输入
1
adfs
输出:那么string参数被置为空string
*/
getchar();
while(T--)
{
string s;
getline(cin,s);
cout<<s<<endl;
}
return 0;
}
getline()了解一下,在字符串知识里有,上面有链接//换行符是丢弃的
三:string对象的操作
s.empty() | 如果s为空串,则返回true,否则返回false |
s.size() | 返回s 中字符的字符个数 |
s[n] | 返回s中位置为n的字符,位置从0开始计数 |
s1+s2 | 把s1和s2链接成一个新的字符串,返回新生成的字符串 |
s1=s2 | 把s1内容替换为s2的副本 |
v1==v2 | 判断v1与v2的内容,相等则返回true,否则返回false |
!=, <, <=, >, >= | 保持这些操作的惯有含义 |
a. string::size_type 类型
注意s.size()返回的类型是string::size_type()类型,而不是int形,string::size_type 的类型长度是int的俩倍所以尽量让s.size()的返 回值给string::size_type 类型
因为string 的字符会很长,所以有了string::size_type 类型
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
string s("value");
string::size_type it;
it=s.size();
cout<<it<<endl;//5
return 0;
}
b.和字符串字面值的连接问题
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
string s1="hello";
string s2=("world");
string s3=s1+", ";//正确的
cout<<s3<<endl;
// string s4="hello"+", ";//错误的
string s5=s1+", "+", "+"world";//错误的
// string s6="hello"+", "+s2;//错误的
cout<<s5<<endl;
return 0;
}
s5的理解为:string t=s1+", "; s5=t+"world";
注意俩个字符串字面值相加,是非法的
c.下标操作可以作左值
如:s[x]='*';
四:string对象中字符的处理
这些函数都在cctype头文件中定义
isalnum(c) | 如果c是字母或数字,则为true |
isalpha(c) | 如果c是字母,则为true |
isdigit(c) | 如果c是数字,则为true |
islower(c) | 如果c是小写字母,则为ture |
isupper(c) | 如果c是大写字母,则为true |
isspace(c) | 如果c是空白字符,则为true |
ispunct(c) | 如果c是标点符号,则为true |
iscntrl(c) | 如果c是控制字符,则为true |
isgraph(c) | 如果c不是空格,但是可打印,则为true |
isprint(c) | 如果c是可打印的字符,则为true |
isxdigit(c) | 如果c是十六进制数,则为true |
tolower(c) | 如果c是大写字母,则返回其小写字母形式,否则直接返回c |
toupper(c) | 如果c是小写字母,则返回其大写字母形式,否则直接返回c |
表中大部分函数是测试一个给定的字符是否符合条件,并返回一个int值作为真值。如果失败,则函数返回0,否则返回一个(无意义的)非0值,表示被测字符符合条件
注意:除了一些特殊操作,string类型提供与vector容器相同的操作。string类型和vector容器不同的是,它不支持以栈方式操纵容器:在string类型中不能使用front,back,pop_back操作
string 是支持push_back()的,因为string也是顺序容器
五:string 的遍历
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
string s("Hiya");
string::iterator it;
for(it=s.begin();it!=s.end();++it)
cout<<*it<<endl;
for(int i=0;s[i];i++)
cout<<s[i]<<endl;
cout<<s<<endl;
return 0;
}
六:构造string对象的其他方法
写这个之前学个知识点:
char s[]="abcd"; 这个是字符串,以'\0'结束的,用strlen(s)是4,'\0'不计,但是它是有五个字符的
char s1[]={'a','b','c','d'}; 这个是字符数组,没有'\0',用strlen(s1)是不确定的,它有四个字符
a.使用只有一个指针参数的构造函数,该指针指向空字符结束的字符数组中的第一个元素。//前面已经介绍了
b.构造函数需要一个指向字符数组元素的指针和一个标记要复制多少字符的计数器做参数,由于该构造函数有一个计数器,因此 数组不必以空字符结束
string s(cp,n) | 创建一个string对象,它被初始化为cp所指向数组的前n个元素副本 |
string s(s2,pos2) | 创建一个string对象,它被初始化为一个已存在的string对象s2中从下标pos2开始的字符的副本 如果pos2>s.size(),则该操作未定义 |
string s(s2,pos2,len2) | 创建一个string对象,它被初始化为s2中从下标pos2开始的len2个字符的副本 如果pos2>s2.size(),则该操作未定义 无论len2的值是多少,最多只能复制s2.size()-pos2个字符 |
注意:n,len2和pos2都是unsinged值
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
char *cp="Hiya";
char c_array[]="world!!!!";
char no_null[] = {'H','i'};
string s1(cp);
cout<<"s1="<<s1<<endl;
string s2(c_array,5);
cout<<"s2="<<s2<<endl;
string s3(c_array+5,4);
cout<<"s3="<<s3<<endl;
//string s4(no_null);//s4是错误的
//cout<<s4<<endl;
string s5(no_null,2);
cout<<"s5="<<s5<<endl;
string s6(s1,2);
cout<<"s6="<<s6<<endl;
string s7(s1,0,2);
cout<<"s7="<<s7<<endl;
string s8(s1,0,8);
cout<<"s8="<<s8<<endl;
return 0;
}
七:修改string对象的其他方法
s.insert(p,t) | 在迭代器p指向的元素之前插入一个值为t的新元素。返回指向新插入元素的迭代器 |
s.insert(p,n,t) | 在迭代器p指向的元素之前插入n个值为t的新元素。返回void |
s.insert(p,b,e) | 在迭代器p指向的元素之前插入b和e标记范围内所有的元素,返回void |
s.assign(b,e) | 用迭代器b和e标记范围内的元素替换s。对于string类型,该操作返回s,对于容器类型,则返回void |
s.assign(n,t) | 用值为t的n个副本替换s。对于string类型,该操作返回s,对于容器类型,返回void |
s.erase(p) | 删除迭代器p指向的元素,返回一个迭代器,指向被删除元素后面的元素 |
s.erase(b,e) | 删除迭代器b和e标记范围内所有的元素,返回一个迭代器,指向被删除元素段后面的第一个元素 |
reverse(b,e) | 把迭代器b和e标记范围内的所有元素反转 |
#include<iostream>
#include<string>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s="12345abcde";
string::iterator it;
it=s.begin();
s.insert(it+2,'s');
cout<<"s="<<s<<endl;
it=s.begin();
s.insert(it+2,2,'t');
cout<<s<<endl;
it= s.begin();
s.assign(it,it+3);
cout<<s<<endl;
s.assign(10,'c');
cout<<s<<endl;
string s1="sfdfsaf";
s1.erase(s1.begin());
cout<<s1<<endl;
s1.erase(s1.begin(),s1.begin()+3);
cout<<s1<<endl;
reverse(s1.begin(),s1.end());
cout<<s1<<endl;
return 0;
}
s.insert(pos,n,c) | 在下表pos的元素之前插入n个字符c |
s.insert(pos,s2) | 在下标为pos的元素之前插入string对象s2的副本 |
s.insert(pos,s2,pos2,len) | 在下标为pos的元素之前插入s2中从下标pos2开始len个字符 |
s.insert(pos,cp,len) | 在下标为pos的元素之前插入s2中从下标pos2开始的len个字符 |
s.insert(pos,cp) | 在下标为pos的元素之前插入cp所指向的以空字符结束的字符串副本 |
s.assign(s2) | 用s2的副本替换s |
s.assign(s2,pos2,len) | 用s2中从下标pos2开始的len个字符副本替换s |
s.assign(cp,len) | 用cp所指向数组的前len个字符副本替换s |
s.assign(cp) | 用cp所指向的以空字符结束的字符串副本替换s |
s.erase(pos,len) | 删除从下标pos开始的len个字符 |
#include<iostream>
#include<string>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s="12345abcde";
s.insert(2,2,'s');
cout<<s<<endl;
string s2="zyz";
s.insert(1,s2);
cout<<s<<endl;
s.insert(0,s2,0,2);
cout<<s<<endl;
char *cp="Statelu pou";
s.insert(0,cp);
cout<<s<<endl;
s.insert(0,cp,2);
cout<<s<<endl;
string s3="123456abc";
s.assign(s3);
cout<<s<<endl;
string s4="987";
s.assign(s4,0,3);
cout<<s<<endl;
s.erase(1,6);
cout<<s<<endl;
return 0;
}
除非特殊声明,上述所有操作都返回s的引用
其实string 的特有版本,就是多了pos下标的使用还有就是控制了一下,比较方便了
八:只适用于string类型的操作
a.substr函数,返回当前string对象的子串
b.append和replace函数,用于修改string对象
c.一系列find函数,用于查找string对象
s.substr(pos,n) | 返回一个string类型的字符串,它包含s中从下标pos开始的n个字符 |
s.substr(pos) | 返回一个string类型的字符串,它包含从下标pos开始到s末为的所有字符 |
s.substr() | 返回s的副本 |
#include<iostream>
#include<string>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s("hello world");
string s2=s.substr(6,5);
cout<<s2<<endl;
string s3=s.substr(6);
cout<<s3<<endl;
return 0;
}
s.append(args) | 将args串接在s后面。返回s的引用 |
s.replace(pos,len,args) | 删除s中从下标pos开始的len个字符,用args指定的字符替换之,返回s的引用 这个版本中,args不能为b2,e2 |
s.replace(b,e,args) | 删除迭代器b和e标记的范围内所有的字符,用args代替之。返回s的引用 这个版本中,args不能为 s1,pos2,len2
|
s2 | string类型的字符串s2 |
s2,pos1,pos2 | 字符串s2中从下标pos2开始的len2个字符 |
cp | 指针cp指向的以空字符结束的数组 |
cp,len2 | cp指向的以空字符结束的数组中前len2个字符 |
n,c | 字符c的n个副本 |
b2,e2 | 迭代器b2和e2标记的范围内所有字符 |
#include<iostream>
#include<string>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s("C++ Prime");
s.append(" 3rd Ed");
cout<<s<<endl;
s.insert(s.size(),"w");
cout<<s<<endl;
s.replace(10,3,"4th");
cout<<s<<endl;
s.erase(10,3);
cout<<s<<endl;
s.insert(10,"4th");
cout<<s<<endl;
return 0;
}
string类型的查找操作
string类提供了6中查找函数,每种函数以不同形式的find命名。这些操作全都返回string::size_type类型的值,以下标形式标记查找所发生的位置;或者返回一个名为string::npos 的特殊值,说明没有找到匹配。string类将npos定义为保证大于任何有效下标的值
s.find(args) | 在s中查找args的第一次出现 |
s.rfind(args) | 在s中查找args的最后一次出现 |
s.find_first_of(args) | 在s中查args的任意字符的第一次出现 |
s.find_last_of(args) | 在s中查找args的任意字符的最后一次出现 |
s.find_first_not_of(args) | 在s中查找第一个不属于args的字符 |
s.find_last_not_of(args) | 在s中查找最后一个不属于args的字符 |
c,pos | 在s中,从下标pos标记的位置开始,查找字符c、pos的默认值是0 |
s2,pos | 在s中,从下标pos标记的位置开始,查找string对象s2,pos的默认值为0 |
cp,pos | 在s中从下标pos标记的位置开始,查找cp所指向的c风格的以空格结束的字符串。pos默认值为0 |
cp,pos,n | 在s中,从下标pos标记的位置开始,查找指针cp所指向数组的前n个字符,pos和n都没有默认值 |
#include<iostream>
#include<string>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
int main()
{
//查找单个单词
string ss="abcdefg";
string::size_type pos=ss.find('c',0);
cout<<pos<<endl;
cout<<ss[pos]<<endl;
//如果找不到就是npos
//精确匹配的查找
string name("AnnaBelle");
string::size_type pos1=name.find("Anna");
cout<<pos1<<endl;//子串Anna在name中的下标是0
string s("annaBelle");
pos1=s.find("Anna");//pos1=npos
//cout<<pos1<<endl;
//查找任意字符
string s2("0123456789");
string s3("r2d2");
// string::size_type pos=s3.find_first_of(s2);
// cout<<s3[pos]<<endl;//2
// cout<<pos<<endl;//1
//指定查找的起点
string::size_type pos2=0;
while((pos2=s3.find_first_of(s2,pos2))!=string::npos)
{
cout<<"pos2="<<pos2<<endl;
cout<<s3[pos2]<<endl;
pos2++;//pos2值必须加1,以确保下一次循环从刚找到的数字后面开始查找下一个数字
}
//寻找不匹配点
string nums("0123456789");
string depet("03714p3");
string::size_type pos3=depet.find_first_not_of(nums);
cout<<"pos3="<<pos3<<endl;
cout<<depet[pos3]<<endl;
//反向查找
string river("Mississippi");
string::size_type first=river.find("is");
string::size_type last=river.rfind("is");
cout<<first<<" "<<river[first]<<endl;
cout<<last<<" "<<river[last]<<endl;
return 0;
}
九:string对象的比较
s.compare(s2) | 比较s和s2 |
s.compare(pos1,n1,s2) | 让s中从pos下标位置开始的n1个字符与s2做比较 |
s.compare(pos1,n1,s2,pos2,n2) | 让s中从pos1下标位置开始的n1个字符与s2中从pos2下标位置开始的n2个字符做比较 |
s.compare(cp) | 比较s和cp所指向的以空字符结束的字符串 |
s.compare(pos1,n1,cp) | 让s从pos1下标位置开始的n1个字符与cp所指向的字符串做比较 |
s.compare(pos1,n1,cp,n2) | 让s中从pos1下标位置开始的n1个字符与cp所指向字符串的前n2个字符做比较 |
比如:s1.compare(args);
a.正数,此时s1大于args所代表的string对象
b.负数,此时s1小于args所代表的string对象
c.0,此时s1恰好等于args所代表的string对象
这次举个例子以前做的题
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,q;
scanf ("%d%d", &n,&q);
string s;
cin>>s;
for ( int i=0; i<q;i++ )
{
int a,b,c,d;
scanf ( "%d%d%d%d" ,&a,&b ,&c , &d );
if ( s.compare( a-1,b-a+1,s,c-1,d-c+1)==0 )
printf ( "YES\n" );
else
printf ( "NO\n" );
}
return 0;
}