NOIP学习小站
西安交通大学附属中学航天学校

C++中的string类型字符串

使用字符数组来存储字符串,其实是C的做法,C++除了沿用这样的做法外,还引入了专门的数据类型string来处理字符串。string本质是类,所以有很多字符串处理方法。

因为string是C++中的类,而类是C++的高级用法,所以本节的内容有一定的难度,如果不能较好地理解,可以尝试先记忆介绍的使用方法。

一、C++中的string类型

C++中有专门的string类型来处理字符串,所以可以像int、double这些基本数据类型一样很简单地使用string类型存储字符串,使用string最好引入string头文件:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s;
    cin>>s;
    cout<<s<<endl;
    return 0; 
}

需要特别注意的是,通过 cin 输入 string,与 cin 输入数字相同,默认的分割符号是空格、回车、制表符,所以上面的程序如果输入Hello World,字符串 s 的结果是Hello,只会把空格前的内容输入到字符串 s 中。如果想将有空格的内容全部输入到字符串中,可以使用 getline(cin,s);,这样可以将一整行的内容输入到字符串中 。

二、使用string中的某个字符

可以像使用数组下标访问数组元素那样通过下标来使用string中的某个字符,不仅仅是取出来使用,甚至可以修改:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s = "Hello";
	cout<<s<<endl;

	cout<<s[0]<<s[1]<<s[2]<<s[3]<<s[4]<<endl;

	s[0] = 'X'; 
	cout<<s<<endl;    
    return 0; 
}

三、string与字符数组字符串的相互转换

C使用字符数组来存储字符串,C++除沿用这样的方法外,还有专门的string类型来处理字符串。可以通过代码来相互转换:

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int main()
{
    char str[15] = "Hello World";
	string s(str);  //使用字符数组初始化string 
	cout<<s<<endl;
	
	s = "Hi";
	//s.c_str()方法返回string变量s的字符数组存储形式
	//再通过strcpy函数拷贝到str数组中 
	strcpy(str,s.c_str());
	cout<<str<<endl;
    return 0; 
}

四、string常用方法

1.string相比较char数组存储字符串的优势

string可以认为是一种数据类型,支持string变量直接赋值成另一个变量:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s = "Hello";
	string ss = s;
	cout<<ss;    
    return 0; 
}

string类型支持+运算,表示字符串拼接:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s = "Hello";
	cout<<s+" World"<<endl;
	s += " World";
	cout<<s<<endl;
    return 0; 
}

string类型支持>、>=、<、<=、==、!=这些比较运算,string字符串比较时规则和char数组存储的字符串规则一致:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s;
    cin>>s;
    if(s=="yes") cout<<"you inputed YES";
    return 0; 
}

2.string的初始化

string本质是类,有丰富的构造函数(后面会有所介绍),所以初始化string变量的方式很多:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string s1 = "Hello";    //通过赋值语句初始化
    cout<<s1<<endl;
    
    string s2("Hello");     //用字符串常量初始化
    cout<<s2<<endl;
    
    string s3(s2);          //用其它字符串变量初始化
    cout<<s3<<endl;
    
    char str[6] = "Hello";
    string s4(str);         //用存储在字符数组的字符串初始化
    cout<<s4<<endl;
    return 0; 
}

3.string字符串长度

使用string的length方法或者size方法都能获取字符串的长度。使用方法参见下面的程序:

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s;
	cin>>s;
	cout<<s.length()<<endl;		//使用length方法获取字符串长度 
	cout<<s.size()<<endl;		  //使用size方法获取字符串长度
	
	//与string长度相关的变量可以使用int类型,但推荐使用size_t或者string::size_type
	size_t n = s.length();		 //使用size_t类型变量存储获取到的字符串长度
	//使用size_t类型控制变量遍历string的每个字符 
	for(size_t i = 0;i<n;i++){
		cout<<s[i];
	}
    return 0; 
}

4.遍历string所有元素

可以使用for循环来依次枚举string元素的下标,实现正向以及逆向遍历string的元素:

#include<iostream>
#include<string>
using namespace std;
int main(){
	string s;
	cin>>s;
	//size_t 在标准Linux环境下本质上是 unsigned long long(无符号长整型)
	//正向遍历
	for(size_t i = 0;i<s.length();i++)
		cout<<s[i];
	cout<<endl;
	
	//反向遍历:控制变量是size_t类型,这里循环条件不能用 i>=0
	//原因是当size_t类型变量i值为0时,执行i--后,i值会变成很大的一个整数(string::npos)
	//所以这里条件用 i!=string::npos
	for(size_t i = s.length()-1;i!=string::npos;i--)
		cout<<s[i]; 
	cout<<endl;
	return 0;
} 

还可以使用STL(标准模版库)中的迭代器实现string元素的遍历(后续进阶学习内容):

#include<iostream>
#include<string>
using namespace std;
int main(){
	string s;
	cin>>s;
	
	//正向遍历 
	string::iterator it = s.begin(); 
	for(;it != s.end();it++)
		cout<<*it;
	cout<<endl;
	
	//反向遍历 
	string::reverse_iterator rit = s.rbegin(); 
	for(;rit != s.rend();rit++)
		cout<<*rit;
	cout<<endl;
	return 0;
} 

*5.修改string内容

可以通过多种语句或者调用方法修改string的内容:

#include<iostream>
#include<string>
using namespace std;
int main ()
{
    string s = "Hello World";
    cout<<1<<":"<<s<<endl;
    
    //通过下标方式修改字符串某个字符,字符串也会变化 
    s[5] = '+'; 
    cout<<2<<":"<<s<<endl; 
    
    //assign方法重新赋值,效果与 s="Nice to meet you";一致,但执行方式不同 
    s.assign("Nice to meet you");
	cout<<3<<":"<<s<<endl; 
	
	string st="Hello";
	//swap方法交换s与st的值
	s.swap(st); 
	cout<<4<<":"<<s<<" "<<st<<endl; 
	
	//append方法末尾追加字符串
	//效果与 s = s+" World";或者 s+=" World";一致,但执行方式不同 
	s.append(" World");
	cout<<5<<":"<<s<<endl;
	
	//push_back方法在字符串末尾追加字符 
	s.push_back('!');
	cout<<6<<":"<<s<<endl;
	
	//insert方法在字符串中插入字符串 
	//在第0个字符前插入字符串 
	s.insert(0,"Say ");
	cout<<7<<":"<<s<<endl;
	
	//replace方法替换字符串指定区间的内容
	//s从第4个开始的一共5个字符被替换成"Hi"
	s.replace(4,5,"Hi"); 
	cout<<8<<":"<<s<<endl;
	//s从第0个开始的一共4个字符被替换成"",实现的是删除的效果 
	s.replace(0,4,""); 
	cout<<9<<":"<<s<<endl;
	
	//erase方法删除字符串指定区间的所有字符
	//从第2个字符开始总共删除6个字符
	s.erase(2,6); 
	cout<<10<<":"<<s<<endl;
	
	//clear方法清空字符串,变成空字符串"" 
	s.clear();
	cout<<11<<":"<<s<<endl;
	cout<<12<<":"<<s.size()<<endl;

    return 0;
}

程序运行结果如下:

1:Hello World
2:Hello+World
3:Nice to meet you
4:Hello Nice to meet you
5:Hello World
6:Hello World!
7:Say Hello World!
8:Say Hi World!
9:Hi World!
10:Hi!
11:
12:0

*6.字符串查找方法

string有丰富的字符串查找方法,包括find、rfind、find_first_of、find_last_of、find_first_not_of、find_last_not_of等方法可以实现丰富的查找:

#include<iostream>
#include<string>
using namespace std;
int main ()
{
    string s = "Hello World";
    
    //在s中查找字符'o'的位置
    cout<<1<<":"<<s.find('o')<<endl;
    
    //在s中从第5个字符开始查找字符'o'的位置
	cout<<2<<":"<<s.find('o',5)<<endl;
	
	//在s中查找字符串"or"出现的位置
	cout<<3<<":"<<s.find("or")<<endl;
	
	//在s中从第8个字符查找字符串"or"出现的位置,查不到返回string::npos
	cout<<4<<":"<<s.find("or",8)<<endl;
	if(s.find("or",8)==string::npos)
		cout<<5<<":"<<"Not found"<<endl;
	
	//在s中逆向查找字符'o'的位置
	cout<<6<<":"<<s.rfind('o')<<endl;
	
	//在s中从第5个字符开始,逆向查找字符'o'的位置
	cout<<7<<":"<<s.rfind('o',5)<<endl;
	
	//在s中逆向查找字符串"or"出现的位置
	cout<<8<<":"<<s.rfind("or")<<endl;
    return 0;
}

程序运行结果如下:

1:4
2:7
3:7
4:4294967295
5:Not found
6:7
7:4
8:7
#include<iostream>
#include<string>
using namespace std;
int main ()
{	
	string str("This is one string for example");
	
	//str中第一个字符'i'出现的位置
	cout<<1<<":"<<str.find_first_of('i')<<endl;
	
	//str中从第3个字符开始,第一个'i'出现的位置
	cout<<2<<":"<<str.find_first_of('i',3)<<endl;
	
	//字符串"oiehtT"任意一个字符在str中第一次出现的位置
	cout<<3<<":"<<str.find_first_of("oiehtT")<<endl;
	
	//从第3个字符开始,字符串"oiehtT"任意一个字符在str中第一次出现的位置
	cout<<4<<":"<<str.find_first_of("oiehtT",3)<<endl;
	
	//逆向查找:str中第一个字符'e'出现的位置
	cout<<5<<":"<<str.find_last_of('e')<<endl;
	
	//逆向查找:字符串"le"中任意一个字符在str中第一次出现的位置 
	cout<<6<<":"<<str.find_last_of("le")<<endl;
    return 0;
}

程序运行结果如下:

1:2
2:5
3:0
4:5
5:29
6:29
#include<iostream>
#include<string>
using namespace std;
int main ()
{	
	string str = "iiiiekpkiiieylmnqqqqq";
	
	//str中第一个不是'i'的字符的位置
	cout<<1<<":"<<str.find_first_not_of('i')<<endl;
	
	//str中第一个不是"eik"字符串中任意字符的位置
	cout<<2<<":"<<str.find_first_not_of("eik")<<endl;
	
	//str中从第7个字符开始查找第一个不是"eik"字符串中任意字符的位置 
	cout<<3<<":"<<str.find_first_not_of("eik",7)<<endl;
	
	//逆向查找:str中第一个不是字符'q'的字符出现的位置
	cout<<4<<":"<<str.find_last_not_of('q')<<endl;
	
	//逆向查找:str中第一个不是字符串"nqm"的任意字符出现的位置
	cout<<5<<":"<<str.find_last_not_of("nqm")<<endl;
    return 0;
}

程序运行结果如下:

1:4
2:6
3:12
4:15
5:13

*7.获取字符串子串

可以通过string的substr方法获取字符串的子串(连续的一部分)

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s = "Hello World";
	cout<<s<<endl;
	
	//从s下标2开始直到结尾的子串 
	string s1 = s.substr(2);	//结果是:llo World
	cout<<s1<<endl;
	
	//从s下标2开始,长度为5的子串 
	string s2 = s.substr(2,5);	//结果是:llo W 
	cout<<s2<<endl; 
	
	//从s下标0开始直到结尾的子串 
	string s3 = s.substr(0);	//结果是:Hello World
	cout<<s3<<endl;
	return 0;
}