STL详解(十) 字符串string

使用场合:

因为C风格字符串(以空字符结尾的字符数组)太过复杂难于掌握,不适合大程序的开发,所以C++标准库定义了一种string类,它不必担心内存是否足够及字符串长度,可以使用输入输出流方式直接进行操作,也可以通过文件等手段进行操作,同时C++的算法库对string也有着很好的支持 ,而且string还和c语言的字符串之间有着良好的接口,因此现在编程中涉及到字符串的处理,就可以直接使用string类了。

string类是由模板而实例化的一个标准类,本质上不是一个标准数据类型,我们尽可以把它看成是C++的基本数据类型。

string 函数列表

函数名 描述
begin 得到指向字符串开头的Iterator
end 得到指向字符串结尾的Iterator
rbegin 得到指向反向字符串开头的Iterator
rend 得到指向反向字符串结尾的Iterator
size 得到字符串的大小
length 和size函数功能相同
max_size 字符串可能的最大大小
capacity 在不重新分配内存的情况下,字符串可能的大小
empty 判断是否为空
[  ]、at 下标访问,取第几个元素,相当于数组
c_str 取得C风格的const char* 字符串
data 取得字符串内容地址
operator= 赋值操作符
reserve 预留空间
swap 交换函数
insert 插入字符
append 追加字符
push_back 追加字符
+= += 操作符
erase 删除字符串
clear 清空字符容器中所有内容
resize 重新分配空间
assign 和赋值操作符一样
replace 替代
copy 字符串到空间
find 查找
rfind 反向查找
find_first_of 查找包含子串中的任何字符,返回第一个位置
find_first_not_of 查找不包含子串中的任何字符,返回第一个位置
find_last_of 查找包含子串中的任何字符,返回最后一个位置
find_last_not_of 查找不包含子串中的任何字符,返回最后一个位置
substr 得到字串
compare 比较字符串
+ 字符串链接
== 判断是否相等
!= 判断是否不等于
< 、 <= 、 >=  、> 判断是否小于、小于等于、大于等于、大于
>> 从输入流中读入字符串
<< 字符串写入输出流
getline 从输入流中读入一行

一、string的初始化

    首先,为了在我们的程序中使用string类型,我们必须包含头文件

    #include<string>                   //注意这里不是string.h ,    string.h是C字符串头文件,   当然也可以用万能头文件<bits/stdc++.h>

    using    namespace   std;     //此语句必不可少,否则有的编译器无法识别。

二、C++字符串声明与初始化赋值

声明一个字符串变量:

string s;//声明一个string 对象

string ss[10];//声明一个string对象的数组

 

 

 

这样我们就声明了一个字符串变量s 和一个字符串对象数组。

string是C++中一个类,就有构造函数和析构函数。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把Str初始化为一个空字符串。String类的构造函数和析构函数如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{ freopen("a.in","r",stdin);
  freopen("a.out","w",stdout);
  string str;             //定义了一个空字符串str
  str = "Hello world";    // 给str赋值为"Hello world",也可以上面定义时直接赋值。
  char cstr[] = "abcde";  //定义了一个C字符串
  
  string s1(str);         //调用复制构造函数生成s1,s1为str的复制品
  string s4(cstr);        //将C字符串作为s4的初值
  string str1("1234");    //生成"1234"的复制品
  cout<<s1<<endl;
  cout<<s4<<endl;
  cout<<str1<<endl;
  
  string s2(str,6);       //将str内,开始于位置6的部分当作s2的初值
  string s5(cstr,3);      //将C字符串前3个字符作为字符串s5的初值。
  string str4("123456",5);//结果为"12345"
  cout<<s2<<endl; 
  cout<<s5<<endl;
  cout<<str4<<endl;

  string s3(str,6,3);     //将str内,开始于6且长度顶多为3的部分作为s3的初值
  string str3("12345",1,3);//结果为"234"
  cout<<s3<<endl;
  cout<<str3<<endl;
  
  string s6(5,'A');       //生成一个字符串,包含5个'A'字符
  cout<<s6<<endl;
  string s7(str.begin(),str.begin()+5); //区间str.begin()和str.begin()+5内的字符作为初值
  cout<<s7<<endl;
  str.~string();           //销毁str字串所有字符,释放内存
}

程序执行结果为:

Hello world
abcde
1234
world
abc
12345
wor
234
AAAAA
Hello

三、string特性描述

可用下列函数来获得string的一些特性:

返回值类型 函数 描述
int capacity() 返回当前容量(即string中不必增加内存即可存放的元素个数
int max_size() 返回string对象中可存放的最大字符串的长度
int size() 返回当前字符串的大小
int length() 返回当前字符串的长度
bool empty() 当前字符串是否为空
void resize(int len,char c) 把字符串当前大小置为len,多去少补,多出的字符c填充不足的部分

大小和容量:

1. size()和length():返回string对象的字符个数,他们执行效果相同。C++的话,倾向于用 size();
2.empty()用来检查字符串是否为空。
3. max_size():返回string对象最多包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。我们一般情况下不用关心他,应该大小足够我们用的。但是不够用的话,会抛出length_error异常。
4. capacity()函数返回在重新申请更多的空间前字符串可以容纳的字符数.就是string当前能够容纳的最大字符数;即capacity()>=length()。
5.resize()函数,为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

 

#include<bits/stdc++.h>
using namespace std;
int main()
{   string str;
    if (str.empty())  cout<<"str is NULL."<<endl;
       else   cout<<"str is not NULL."<<endl;
    str = str + "abcdefg";
    cout<<"str is "<<str<<endl;
    cout<<"str's size is "<<str.size()<<endl;
    cout<<"str's capacity is "<<str.capacity()<<endl;
    cout<<"str's max size is "<<str.max_size()<<endl;
    cout<<"str's length is "<<str.length()<<endl;
    str.resize(20,'c');
    cout<<"str is "<<str<<endl;
    str.resize(5);
    cout<<"str is "<<str<<endl;
    return 0;
}

程序执行结果为:

str is NULL.
str is abcdefg
str's size is 7
str's capacity is 7
str's max size is 1073741820
str's length is 7
str is abcdefgccccccccccccc
str is abcde

 

四、string的比较操作(==、>、<、>=、<=、!=、compare()

1、用运算符 ==、>、<、>=、<=、和!=比较字符串,这些操作符是按从左向右顺序逐一比较,遇到不相等的字符就按这个位置上的两个字符的ASC码大小比较,ASC码大的字串大。

2、compare()比较两个字符串。

compare()为区分大小写比较字符串,比如,利用compare比较字串“str”与字串“lpsz”,等同于区分大小写比较“str”与“lpsz”的第一个相异字符,如果“str”该处的字符比“lpsz”大,则字符串“str”大于“lpsz”,返回1;如果“str”该处的字符比“lpsz”小,则字符串“str”小于“lpsz”,返回-1;“str”与“lpsz”内容完全一致则返回0。

返回值类型 函数 描述
int str.compare(const string &s) 比较字符串str和s的大小
int str.compare(int pos, int n,const string &s) 比较字符串str从pos开始的n个字符组成的字符串与s的大小
int str.compare(int pos, int n,const string &s,int pos2,int n2)

比较字符串str从pos开始的n个字符组成的字符串与s中pos2开始的n2个字符组成的字符串的大小

int str.compare(const char *s) ; 比较字符串str和c字符串s的大小
int  str.compare(int pos, int n,const char *s) ; 比较字符串str从pos开始的n个字符组成的字符串与c字符串s的大小
int str.compare(int pos, int n,const char *s, int pos2,int n2) ; 比较字符串str从pos开始的n个字符组成的字符串与c字符串s中pos2开始的n2个字符组成的字符串的大小

例一、

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string str;
    cout << "Please input your name:"<<endl;
    cin >> str;
    if( str == "Li" )   // 字符串相等比较
        cout << "you are Li!"<<endl;
    else if( str != "Wang" )  // 字符串不等比较
        cout << "you are not Wang!"<<endl;
    else if( str < "Li")     // 字符串小于比较,>、>=、<=类似
        cout << "your name should be ahead of Li"<<endl;
    else
        cout << "your name should be after of Li"<<endl;
    str += ", Welcome!";  // 字符串+=
    cout << str<<endl;
    for(int i = 0 ; i < str.size(); i ++)
        cout<<str[i];  // 类似数组,通过[]获取特定的字符,可换为: cout<<str.at(i);
    return 0;
}

程序执行结果为:

Please input your name:
Zhang↙

you are not Wang!
Zhang, Welcome!
Zhang, Welcome!

例二:

#include<bits/stdc++.h>
using namespace std;
int main()
{ 	string str1="hi,test,hello";
	string str2="hi,test";
	//字符串比较
	if(str1.compare(str2)>0) printf("str1>str2\n");
	else if(str1.compare(str2)<0)	printf("str1<str2\n");
	     else	printf("str1==str2\n");
	
	//str1的子串(从索引3开始,包含4个字符)与str2进行比较
	if(str1.compare(3,4,str2)==0)	printf("str1的指定子串等于str2\n");
	else	printf("str1的指定子串不等于str2\n");
	
	//str1指定子串与str2的指定子串进行比较
	if(str1.compare(3,4,str2,3,4)==0) printf("str1的指定子串等于str2的指定子串\n");
	else printf("str1的指定子串不等于str2的指定子串\n");
	
	//str1指定子串与字符串的前n个字符进行比较
	if(str1.compare(0,2,"hi,hello",2)==0) printf("str1的指定子串等于指定字符串的前2个字符组成的子串\n");
	else	printf("str1的指定子串不等于指定字符串的前2个字符组成的子串\n");
	return 0;	
}

程序执行结果为:

str1>str2
str1的指定子串不等于str2
str1的指定子串等于str2的指定子串
str1的指定子串等于指定字符串的前2个字符组成的子串

例三:

#include<bits/stdc++.h>
using namespace std;
int main()
{  	string A("aBcdef");	string B("AbcdEf");	string C("123456");	string D("123dfg");
	int m = A.compare(B);
	int n = A.compare(1, 5, B);
	int p = A.compare(1, 5, B, 4, 2);
	int q = A.compare(0, 3, D, 0, 3);
	cout << "m=" << m << endl;
	cout << "n=" << n << endl;
	cout << "p=" << p << endl;
	cout << "q=" << q << endl;
}

程序执行结果为:

m=1
n=1
p=-1
q=1

 

五、字符串内容修改

(5.1)string类的赋值函数:给字符串赋值assign()函数。

返回值类型 函数 描述
string str=(const string &s); 把字符串s,赋值给字符串str
string str.assign(const char *s); 用c类型字符串s赋值给字符串str
string str.assign(const char *s,int n); 用c字符串s前n个字符,赋值给字符串str
string str.assign(const string &s); 把字符串s,赋值给字符串str
string str.assign(int n,char c); 用n个字符c,赋值给字符串str
string str.assign(const string &s,int start,int n); 把字符串s中从start开始的n个字符,赋值给字符串str
string str.assign(const_iterator first,const_itertor last); 把first和last迭代器之间的部分,赋值给字符串str
#include<bits/stdc++.h>
using namespace std;
int main()
{   string str;
    string base="The quick brown fox jumps over a lazy dog.";
        
    str.assign(base);       //直接把base赋值给str
                            //str(base)是错误的,只有在赋初值时可以用str(base)。
    cout<<str<<'\n';
    
    str.assign(base,10,9);  //把base第10个字符以及后面的8个字符赋给str
    cout<<str<<'\n';        // "brown fox"
    
    str.assign("pangrams are cool",7);//把参数中的0到6个字符串赋给str
    cout<<str<<'\n';        // "pangram"
    
    str.assign("c-string"); //直接使用参数赋值
    cout << str << '\n';    // "c-string"
    
    str.assign(10,'*');     //给str赋值10个'*'字符
    cout<<str<<'\n';        // "**********"
    
    str.assign<int>(10,0x2D);//赋值是10个'-'
    cout << str << '\n';     // "----------"
   
    str.assign(base.begin()+16,base.end()-12); //指定base迭代器范围的字符串
    cout<<str<<'\n';         // "fox jumps over"
}

程序执行结果为:

The quick brown fox jumps over a lazy dog.
brown fox
pangram
c-string
**********
----------
fox jumps over

(5.2)字符的连接(在尾巴上增加)

        1、append()函数可以用来在字符串的末尾追加字符和字符串,

        2、也可以用 + 和 += 来实现,

        3、push_back()在字符串的末尾追加一个字符,不能追加字符串。

返回值类型 函数 描述
string str+=(const string &s); 把字符串s,连接到字符串str的结尾 
string str.append(const char *s);  把c类型字符串s,连接到字符串str的结尾 
string str.append(const char *s,int n); 把c类型字符串s的前n个字符,连接到字符串str的结尾 
string str.append(const string &s);  把字符串s,连接到字符串str的结尾 ,同+=相同。
string str.append(const string &s,int pos,int n); 把字符串s中从pos开始的n个字符,连接到字符串str的结尾 
string str.append(int n,char c);   在字符串str结尾添加n个字符c
string str.append(const_iterator first,const_iterator last); 把迭代器first和last之间的部分,连接到字符串str的结尾 
string str.push_back(char c) 在字符串str的末尾追加一个字符
#include<bits/stdc++.h>
using namespace std;
int main()
{string str;
 string str2="Writing ";
 string str3="print 10 and then 5 more";

 str.append(str2);        //直接追加一个str2的字符串,追加"Writing "
 str.append(str3,6,3);    //后面追加str3第6个字符开始的3个字符串 ,追加"10 "
 str.append("dots are cool",5); //追加字符串形参的前5个字符,追加"dots "
 str.append("here: ");    //直接追加 "here: "
 str.append(10,'.');     //追加 10个'.' ,追加 ".........."
 str.append(str3.begin()+8,str3.end()); //从str3的第8个字符开始追加" and then 5 more"
 str.append<int>(5,65);   //这个比较特殊,意思是添加5个'A',65对应的asc码就是65
 
 str+="lalala";           //字符串追加也可以用重载运算符实现
 
 str.push_back('X');    //括号内不能用双引号如:“X”,不能用多个字符如:“AFF”。 

 cout<<str<<'\n';
}

程序执行结果为:

Writing 10 dots here: .......... and then 5 moreAAAAAlalalaX

    (5.3)string类的插入函数:插入字符串insert()。

返回值类型 函数 描述
string str.insert(int p0, const char *s); 在p0位置插入C语言字符串s
string str.insert(int p0, const char *s, int n); 在p0位置插入C语言字符串s的前n个字符
string str.insert(int p0,const string &s); 在p0位置插入C++字符串s
string str.insert(int p0,const string &s, int pos, int n); 在p0位置插入C++字符串s从pos开始的连续n个字符
string str.insert(int p0, int n, char c); 在p0处插入n个字符c
iterator str.insert(iterator it, char c); 在it处插入字符c,返回插入后迭代器的位置
void str.insert(iterator it, const_iterator first, const_iteratorlast); 在it处插入从first开始至last-1的所有字符
void str.insert(iterator it, int n, char c); 在it处插入n个字符c

例一、

#include <bits/stdc++.h>
using namespace std;
int main()
{   ios::sync_with_stdio(false);    
    string str="to be question";
    string str2="the ";
    string str3="or not to be";
    string::iterator it;

    //s.insert(pos,str)//在s的pos位置插入str
    str.insert(6,str2);                 // to be the question
    cout<<str<<endl;
    //s.insert(pos,str,a,n)在s的pos位置插入str中插入位置a到后面的n个字符
    str.insert(6,str3,3,4);             // to be not the question
    cout<<str<<endl;
    //s.insert(pos,cstr,n)//在pos位置插入cstr字符串从开始到后面的n个字符
    str.insert(10,"that is cool",8);    // to be not that is the question
    cout<<str<<endl;
    //s.insert(pos,cstr)在s的pos位置插入cstr
    str.insert(10,"to be ");            // to be not to be that is the question
    cout<<str<<endl;
    //s.insert(pos,n,ch)在s.pos位置上面插入n个ch
    str.insert(15,1,':');               // to be not to be: that is the question
    cout<<str<<endl;
    //s.insert(s.it,ch)在s的it指向位置前面插入一个字符ch,返回新插入的位置的迭代器
    it = str.insert(str.begin()+5,','); // to be, not to be: that is the question
    cout<<*it<<endl;
    cout<<str<<endl;
    //s.insert(s.it,n,ch)//在s的it所指向位置的前面插入n个ch
    str.insert (str.end(),3,'.');       // to be, not to be: that is the question...
    cout<<str<<endl;
    //s.insert(it,str.ita,str.itb)在it所指向的位置的前面插入[ita,itb)的字符串
    str.insert (it+2,str3.begin(),str3.begin()+3); // to be, or not to be: that is the question...
    cout<<str<<endl;
}

程序执行结果为:

to be the question
to be not the question
to be not that is the question
to be not to be that is the question
to be not to be: that is the question
,
to be, not to be: that is the question
to be, not to be: that is the question...
to be, or not to be: that is the question...

在竞赛中遇到大数据时,往往读文件成了程序运行速度的瓶颈,需要更快的读取方式。cin读入速度缓慢原因一般cin与stdin总是保持同步的,正因为这个的特性,导致cin有许多额外的开销,禁用这个特性只需一个语句std::ios::sync_with_stdio(false);,这样就可以取消cin于stdin的同步了,效率可以提高几乎10倍。

(5.4)string类的删除函数 :删除字符串erase()。

返回值类型 函数 描述
iterator str.erase(iterator first, iterator last); 删除[first,last)之间的所有字符,返回删除后迭代器的位置
iterator str.erase(iterator it); 删除it指向的字符,返回删除后迭代器的位置
string str.erase(int pos = 0, int n = npos); 删除pos开始的n个字符,返回修改后的字符串
#include <bits/stdc++.h>
using namespace std;
int main()
{ string str("This is an example sentence.");
  cout << str << '\n';  
                          // "This is an example sentence."
  str.erase (10,8);       //            ^^^^^^^^
  //直接指定删除的字符串位置第十个后面的8个字符
  cout << str << '\n';
                            // "This is an sentence."
  str.erase (str.begin()+9);//           ^
  //删除迭代器指向的字符
  cout << str << '\n';
                            // "This is a sentence."
                            //       ^^^^^
  str.erase (str.begin()+5, str.end()-9);
  //删除迭代器范围的字符
  cout << str << '\n';
                            // "This sentence."
}

 程序执行结果为:

This is an example sentence.
This is an sentence.
This is a sentence.
This sentence.

(5.5)string类的替换函数(replace):​​​​​替换字符串。

返回值类型 函数 描述
string str.replace(int p0, int n,const char *s); 删除从p0开始的n0个字符,然后在p0处插入串s
string str.replace(int p0, int n0,const char *s, int n); 删除p0开始的n0个字符,然后在p0处插入字符串s的前n个字符
string str.replace(int p0, int n0,const string &s); 删除从p0开始的n0个字符,然后在p0处插入串s
string str.replace(int p0, int n0,const string &s, int pos, int n); 删除p0开始的n0个字符,然后在p0处插入串s中从pos开始的n个字符
string str.replace(int p0, int n0,int n, char c); 删除p0开始的n0个字符,然后在p0处插入n个字符c
string str.replace(iterator first0, iterator last0,const char *s); 把[first0,last0)之间的部分替换为字符串s
string str.replace(iterator first0, iterator last0,const char *s, int n); 把[first0,last0)之间的部分替换为s的前n个字符
string str.replace(iterator first0, iterator last0,const string &s); 把[first0,last0)之间的部分替换为串s
string replace(iterator first0, iterator last0,int n, char c); 把[first0,last0)之间的部分替换为n个字符c
string replace(iterator first0, iterator last0,const_iterator first, const_iterator last); 把[first0,last0)之间的部分替换成[first,last)之间的字符串

例一:

#include <bits/stdc++.h>
using namespace std;
int main ()
{   string base="this is a test string.";
    string str2="n example";
    string str3="sample phrase";
    string str4="useful.";

string str=base;   // "this is a test string."
cout<<str<<endl; 
	
	//str第9个字符以及后面的5个字符被str2代替
str.replace(9,5,str2);  // "this is an example string." (1)
cout<<str<<endl;
	
	//第19个字符串以及后面的6个字符用str的第7个字符以及后面的6个字符代替
str.replace(19,6,str3,7,6);   // "this is an example phrase." (2)
cout<<str<<endl;
   
    //第8个字符以及后面的9个字符用字符串参数代替
str.replace(8,10,"just a");   // "this is just a phrase."     (3)
cout<<str<<endl;
   
    //第8个字符以及后面的5个字符用字符串参数的前7个字符替换
str.replace(8,6,"a shorty",7); // "this is a short phrase."    (4)
cout<<str<<endl;
	
	//第22以及后面的0个字符用3个叹号替换
str.replace(22,1,3,'!');       // "this is a short phrase!!!"  (5)
cout<<str<<endl;
	
	//迭代器的原理同上
    // Using iterators:    0123456789*123456789*
str.replace(str.begin(),str.end()-3,str3);      // "sample phrase!!!"      (1)
cout<<str<<endl;
str.replace(str.begin(),str.begin()+6,"replace");  // "replace phrase!!!"  (3)
cout<<str<<endl;
str.replace(str.begin()+8,str.begin()+14,"is coolness",7);//"replace is cool!!!" (4)
cout<<str<<endl;
str.replace(str.begin()+12,str.end()-4,4,'o');  // "replace is cooool!!!"  (5)
cout<<str<<endl;
str.replace(str.begin()+11,str.end(),str4.begin(),str4.end()); // "replace is useful." (6)
cout<<str<<endl;
}

程序执行结果为:

this is a test string.
this is an example string.
this is an example phrase.
this is just a phrase.
this is a short phrase.
this is a short phrase!!!
sample phrase!!!
replace phrase!!!
replace is cool!!!
replace is cooool!!!
replace is useful.

(5.6)sawp()函数:相互交换字符串

#include <bits/stdc++.h>
using namespace std;
int main()
{string str="give me";
 string str1="a cup'";
 str.swap(str1);
 cout<<str<<endl;    //输出:a cup
 cout<<str1<<endl;   //输出:give me
}

(5.7)把字符串清空

把字符串清空的方法有三个:

1、s=””;

2、s.clear();

3、s.erase();

(5.8)string和数值转换  :

在c++11当中有定义好的现成的函数取调用,非常方便。

返回值类型 函数 描述
string to_string(val) 把val转换成string
int stoi(s,p,b) 把字符串s从p开始转换成b进制的int
long stol(s,p,b)  把字符串s从p开始转换成b进制的long
unsigned long stoul(s,p,b)  把字符串s从p开始转换成b进制的unsigned long
long long stoll(s,p,b) 把字符串s从p开始转换成b进制的long long
unsigned long long stoull(s,p,b) 把字符串s从p开始转换成b进制的unsigned long long
float stof(s,p) 把字符串s从p开始转换成float
double stod(s,p)  把字符串s从p开始转换成double
long double stold(s,p)  把字符串s从p开始转换成long double

以上函数是C++11中的库函数,让Dev C++支持C++11还要在软件中进行设置。

1.先在dev的【工具】里找到【编译选项】


2.一开始普遍的dev应该都是以下这个界面,在【编译时加入以下命令】栏是空白的且没有打钩。


3.奇迹就在此刻改变.在这个【编译时加入以下命令】处打钩,然后在空白栏输入【-std=c++11】(c是小写的),确定.然后就能支持c++1

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string s1;
    s1=to_string(100);
    cout<<s1<<endl;
    int a=stoi(s1,0,10)+1;
    cout<<a<<endl;
}

以上程序在Dev C++编译环境中设置好【-std=c++11】后才可以运行。

(5.9)String字符串与字符(char类型)数组互相转换 :

1、字符数组转化成string类型

#include<bits/stdc++.h>
using namespace std;
int main()
{char ch[] = "ABCDEFG";
 string str(ch);//也可string str = ch;
 cout<<str;
}

或者

#include<bits/stdc++.h>
using namespace std;
int main()
{char ch[]="ABCDEFG";
 string str;
 str=ch;//在原有基础上添加可以用str+=ch;
 cout<<str;
}


2、将string类型转换为字符数组
char buf[10];
string str("ABCDEFG");
length = str.copy(buf, 9);
buf[length] = '\0';
或者
char buf[10];
string str("ABCDEFG");
strcpy(buf, str.c_str());//strncpy(buf, str.c_str(), 10);

标准库的string类提供了3个成员函数来从一个string得到c类型的字符数组:c_str()、data()、copy(p,n)。

1. c_str():生成一个const char*指针,指向以空字符终止的数组。

注:

①这个数组的数据是临时的,当有一个改变这些数据的成员函数被调用后,其中的数据就会失效。因此要么现用先转换,要么把它的数据复制到用户自己可以管理的内存中。注意。看下例:

const char* c;

string s="1234";

c = s.c_str();

cout<<c<<endl; //输出:1234

s="abcd";

cout<<c<<endl; //输出:abcd

 

上面如果继续用c指针的话,导致的错误将是不可想象的。就如:1234变为abcd

其实上面的c = s.c_str(); 不是一个好习惯。既然c指针指向的内容容易失效,我们就应该按照上面的方法,那怎么把数据复制出来呢?这就要用到strcpy等函数(推荐)。

//const char* c; //①

//char* c;       //②

//char c[20];

char* c=new char[20];

string s="1234";

//c = s.c_str();

strcpy(c,s.c_str());

cout<<c<<endl; //输出:1234

s="abcd";

cout<<c<<endl; //输出:1234

注意:不能再像上面一样①所示了,const还怎么向里面写入值啊;也不能②所示,使用了未初始化的局部变量“c”,运行会出错的 。

② c_str()返回一个客户程序可读不可改的指向字符数组的指针,不需要手动释放或删除这个指针。

2. data():与c_str()类似,但是返回的数组不以空字符终止。

3. copy(p,n,size_type _Off = 0):从string类型对象中至多复制n个字符到字符指针p指向的空间中。默认从首字符开始,但是也可以指定,开始的位置(记住从0开始)。返回真正从对象中复制的字符。------用户要确保p指向的空间足够保存n个字符。

#include <bits/stdc++.h>

using namespace std;

int main( )

{   string str1 ( "1234567890" );

    basic_string <char>::iterator str_Iter;

    char array1 [ 20 ] = { 0 };

    char array2 [ 10 ] = { 0 };

    basic_string <char>:: pointer array1Ptr = array1;

    basic_string <char>:: value_type *array2Ptr = array2;



    cout << "The original string str1 is: ";

    for ( str_Iter = str1.begin( ); str_Iter != str1.end( ); str_Iter++ )

        cout << *str_Iter;

    cout << endl;



    basic_string <char>:: size_type nArray1;

    // Note: string::copy is potentially unsafe, consider

    // using string::_Copy_s instead.

    nArray1 = str1.copy ( array1Ptr , 12 );  // C4996

    cout << "The number of copied characters in array1 is: "

        << nArray1 << endl;

    cout << "The copied characters array1 is: " << array1Ptr << endl;



    basic_string <char>:: size_type nArray2;

    // Note: string::copy is potentially unsafe, consider

    // using string::_Copy_s instead.

    nArray2 = str1.copy ( array2Ptr , 5 , 6  );  // C4996

    cout << "The number of copied characters in array2 is: "

        << nArray2 << endl;

    cout << "The copied characters array2 is: " << array2Ptr << endl;

六、访问单个字符。可以通过[ ]下标,函数at()及迭代器三种方法来访问单个字符。

#include <bits/stdc++.h>
using namespace std;
int main()
{   string s1 = "abcdefg";

    //1、数组方式
    cout << "数组方式:" << endl;
    for (int i = 0; i < s1.length(); i++)
        cout <<s1[i] <<endl;
        
    //2、函数方式
    cout << "数组方式:" << endl;
    for (int i = 0; i < s1.length(); i++)
        cout <<s1.at(i) <<endl;    

    //3、迭代方式
    cout << "迭代方式:" << endl;
    for (string::iterator it = s1.begin(); it != s1.end(); it++)
        cout<<*it<< endl;
}

注意:运算符[  ]和at()均返回当前字符串中第n个字符的位置,但at函数提供范围检查,当越界时会抛出out_of_range异常,下标运算符[  ]不提供检查访问。

 

七、字符串的输入输出。>>、 << 、getline()

1、string类重载运算符operator>>用于输入,同样重载运算符operator<<用于输出操作。

2、getline()的原型: getline ( istream &is , string &str , char delim );

其中:

istream &is 表示一个输入流,譬如cin;

string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);

char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为'\n',也就是回车换行符(遇到回车停止读入)。

例如:

string line;
cout<<"please cin a line:";
getline(cin,line,'#');
cout<<"The line you give is:"<<line<<endl;

输入"You are the #best!" 的时候,输入流实际上只读入了"You are the ",#后面的并没有存放到line中。

程序运行结果应该是这样的: 

please cin a line:You are the #best!
The line you give is:You are the 

while(getline(cin,line))语句

注意这里默认回车符停止读入,按Ctrl+Z或键入回车即可退出循环。

在这个语句中,首先getline从标准输入设备上读入字符,然后返回给输入流cin,注意了,是cin,所以while判断语句的真实判断对象是cin,也就是判断当前是否存在有效的输入流。在这种情况下,我想只要你的电脑不中毒不发神经你的输入流怎么会没有效?所以这种情况下不管你怎么输入都跳不出循环,因为你的输入流有效,跳不出循环。

然而有些同学误以为while判断语句的判断对象是line(也就是line是否为空),然后想通过直接回车(即输入一个空的line)跳出循环,却发现怎么也跳不出循环。这是因为你的回车只会终止getline()函数的读入操作。getline()函数终止后又进行while()判断(即判断输入流是否有效,你的输入流当然有效,满足条件),所以又运行getline()函数。

所以,以下的写法根本不可能让你推出while()循环的:

while(getline(cin,line))    cout<<line<<endl;

二、cin.getline()

此函数会一次读取多个字符(包括空白字符)。它以指定的地址为存放第一个读取的字符的位置,依次向后存放读取的字符,直到读满N-1个,或者遇到指定的结束符为止。若不指定结束符,则默认结束符为'\n'。其语法为:

cin.getline(字符指针(char*),字符个数N(int),结束符(char));

#include <bits/stdc++.h>
using namespace std;
int main()
{char a[30];
 cout << "请输入一个字符串:" << endl;
 cin.getline(a, 10);//第10位存放字符串结束符'\0'
 for (int i = 0; i<10; i++)
 cout << "第"<<i+1<<"个值为:"<<a[i] << endl;
 return 0;
}

输入:1234567890123

输出:

请输入一个字符串:
第1个值为:1
第2个值为:2
第3个值为:3
第4个值为:4
第5个值为:5
第6个值为:6
第7个值为:7
第8个值为:8
第9个值为:9
第10个值为:

 

八、string的搜索操作: 

1、 find()  和  rfind() 函数:  find函数主要是查找一个字符串是否在调用的字符串中出现过,大小写敏感。

str.find(str2),当str2是str的子串时,返回其在str中第一次出现的位置,否则返回string::npos。

str.find(str2,pos),是从str的pos号位开始查找匹配str2,找到返回其位置;否则返回string::npos。

string::npos是一个常数,其本身的值等于-1,但由于是unsigned int类型,因此,也可以认为是unsigned int类型的最大值(4294967295)。

rfind()与find()很相似,差别在于查找顺序不一样,find()是从指定位置起向后查找,直到串尾。rfind()是从指定位置起向前查找,直到串首,相当于逆向查找,返回的位置仍然是从前往后数的。

返回值类型 函数 描述
int str.find(char c, int pos = 0); 从pos开始查找字符c在C++字符串str中的位置
int str.find(const char *s, int pos = 0);  从pos开始查找c语言字符串s在C++字符串str中的位置
int str.find(const char *s, int pos, int n); 从pos开始查找c语言字符串s中前n个字符在C++字符串str中的位置
int str.find(const string &s, int pos = 0);  从pos开始查找c++字符串s在C++字符串str中的位置。
int str.rfind(char c, int pos = npos); 从pos开始从后向前查找字符c在C++字符串str中的位置
int str.rfind(const char *s, int pos = npos);   从pos开始从后向前查找c语言字符串s在C++字符串str中的位置
int str.rfind(const char *s, int pos, int n = npos); 从pos开始从后向前查找c语言字符串s中前n个字符在C++字符串str中的位置
int str.rfind(const string &s,int pos = npos); 从pos开始从后向前查找c++字符串s在C++字符串str中的位置。

例一、

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string str ("There are two needles in this haystack with needles.");
    string str2 ("needle");

    //在str当中查找第一个出现的needle,找到则返回出现的位置,否则返回结尾
    size_t found = str.find(str2);
    if (found!=string::npos)
    cout << "first 'needle' found at: " << found << '\n';
    //在str当中,从第found+1的位置开始查找参数字符串的前6个字符
    found=str.find("needles are small",found+1,6);
    if (found!=string::npos)
    cout << "second 'needle' found at: " << found << '\n';
    //在str当中查找参数中的字符串
    found=str.find("haystack");
    if (found!=string::npos)
    cout << "'haystack' also found at: " << found << '\n';
    //查找一个字符
    found=str.find('.');
    if (found!=string::npos)
    cout << "Period found at: " << found << '\n';
    //组合使用,把str2用参数表中的字符串代替
    // let's replace the first needle:
    str.replace(str.find(str2),str2.length(),"preposition");
    cout << str << '\n';
    return 0;
}

程序结果:

first 'needle' found at: 14
second 'needle' found at: 44
'haystack' also found at: 30
Period found at: 51
There are two prepositions in this haystack with needles.

例二、

#include <bits/stdc++.h>
using namespace std;
int main()
{//测试find (charT c, size_type pos = 0) const noexcept;
 string st1("babbabab");
 cout <<st1.find('a')<<endl;//1 由原型知,若省略第2个参数,则默认从位置0(即第1个字符)起开始查找
 cout<<st1.find('a',0)<<endl;//1
 cout<<st1.find('a',1)<<endl;//1   
 cout<<st1.find('a',2)<<endl;//4  在st1中,从位置2(包括位置2)开始查找字符a,返回首次匹配的位置,匹配失败,返回npos
 cout<<st1.rfind('a',7)<<endl;//6  
 cout<<st1.find('c',0)<<endl;//4294967295
 cout<<(st1.find('c',0) == -1)<<endl;//1
 cout<<(st1.find('c',0)==4294967295)<<endl;//1 两句均输出1,原因是计算机中-1和4294967295都表示为32个1(二进制)
 cout<<st1.find('a',100)<<endl;//4294967295  当查找的起始位置超出字符串长度时,按查找失败处理,返回npos
 
//测试find (const basic_string& str, size_type pos = 0);
 string st2("aabcbcabcbabcc");
 string str1("abc");
 cout<<st2.find(str1,2)<<endl;//6  从st2的位置2开始匹配,返回第一次成功匹配时匹配的串(abc)的首字符在st2中的位置,失败返回npos

//测试size_type find (const charT* s, size_type pos = 0) ;
 cout << st2.find("abc",2)<<endl; //6   同上,只不过参数不是string而是char*

//测试size_type find (const charT* s, size_type pos, size_type n) ;
 cout<<st2.find("abcdefg",2,3)<<endl;//6   取abcdefg得前3个字符(abc)参与匹配,相当于st2.find("abc",2)
 cout<<st2.find("abcbc",0,5)<<endl;//1  相当于st2.find("abcbc", 0)
 cout<<st2.find("abcbc",0,6)<<endl;//4294967295  第3个参数超出第1个参数的长度时,返回npos
}

例三、

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string str ("The sixth sick sheik's sixth sheep's sick.");
    string key ("sixth");//                    ^
    //rfind是找最后一个出现的匹配字符串
    size_t found = str.rfind(key);
    if (found!=string::npos)
    {
        cout<<found<<endl;//输出23
        str.replace (found,key.length(),"seventh");//找到的sixth替换成seventh
    }
    cout << str << '\n';
    return 0;
}

程序结果:

23
The sixth sick sheik's seventh sheep's sick.

2、find_first_of()和 find_first_not_of()和 函数: 
        在源串中从位置pos起往后查找,只要在源串中遇到一个字符,该字符与目标串中任意一个字符相同,就停止查找,返回该字符在源串中的位置;若匹配失败,返回npos。

        注意find_first_of函数和find函数的区别,如果是str.find(“abc”)的话,则必须找到完全匹配abc的才算查找成功,而find_first_of只需要abc中任何一个出现即可。

返回值类型 函数 描述
int str.find_first_of(char c, int pos = 0); 从pos开始查找字符c在C++字符串str中的位置
int str.find_first_of(const char *s, int pos = 0);  从pos开始查找c语言字符串s中任何一个字符首次在C++字符串str中的位置
int str.find_first_of(const char *s, int pos, int n); 从pos开始查找c语言字符串s中前n个字符中任何一个字符首次在C++字符串str中的位置
int str.find_first_of(const string &s,int pos = 0);  从pos开始查找c++字符串s中任何一个字符首次在C++字符串str中的位置。
int str.find_first_not_of(char c, int pos = 0); 从pos开始查找字符c以外的任何一个字符在C++字符串str中的位置
int str.find_first_not_of(const char *s, int pos = 0);   从pos开始c语言字符串s以外的任何一个字符在C++字符串str中的位置
int str.find_first_not_of(const char *s, int pos,int n); 从pos开始查找c语言字符串s中前n个字符以外的任何一个字符在C++字符串str中的位置
int str.find_first_not_of(const string &s,int pos = 0); 从pos开始查找c++字符串s以外的任何一个字符在C++字符串str中的位置。

3、find_last_of()和 find_last_not_of()和 函数: 

在源串中从位置pos起往前查找,只要在源串中遇到一个字符,该字符与目标串中任意一个字符相同,就停止查找,返回该字符在源串中的位置;若匹配失败,返回npos。find_last_of和find_last_not_of与find_first_of和find_first_not_of相似,只不过是从后向前查找

返回值类型 函数 描述
int str.find_last_of(char c, pos = npos); 从pos开始由后向前查找字符c在C++字符串str中的位置
int str.find_last_of(const char *s, int pos = npos);  从pos开始由后向前查找c语言字符串s中任何一个字符首次在C++字符串str中的位置
int str.find_last_of(const char *s, int pos, int n=npos); 从pos开始由后向前查找c语言字符串s中前n个字符中任何一个字符首次在C++字符串str中的位置
int str.find_last_of(const string &s,int pos = npos);  从pos开始由后向前查找c++字符串s中任何一个字符首次在C++字符串str中的位置。
int str.find_last_not_of(char c, int pos = npos); 从pos开始由后向前从后向前查找字符c以外的任何一个字符在C++字符串str中的位置
int str.find_last_not_of(const char *s, int pos = npos);   从pos开始由后向前从后向前查找c语言字符串s以外的任何一个字符在C++字符串str中的位置
int str.find_last_not_of(const char *s, int pos,int n); 从pos开始由后向前从后向前查找c语言字符串s中前n个字符以外的任何一个字符在C++字符串str中的位置
int str.find_last_not_of(const string &s,int pos = npos); 从pos开始由后向前从后向前查找c++字符串s以外的任何一个字符在C++字符串str中的位置。

九、string的子串substr():

这个函数的作用是取字符串str中位置为pos开始的len个字符,返回一个字符串。

如果pos开始后len个字符长度超出了字符串的长度,则取到最后一个字符。

返回值类型 函数 描述
string str.substr(int pos = 0,int n = npos) ; 返回pos开始的n个字符组成的字符串给str字符串

假设:string s = “0123456789”;

string sub1 = s.substr(5); //只有一个参数5,  则表示从下标为5开始一直到结尾:sub1 = “56789”

string sub2 = s.substr(5, 3); //有二个参数(5,3),表示从下标为5开始截取长度为3位:sub2 = “567”

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章