标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件。
#include3.2.1 定义和初始化string对象using std::string;
初始化类的方式是由类本身决定的(源代码),下面是初始化对象的常用方式:
string s1; // 默认构造,s1是一个空字符串 string s2 = s1; // s2是s1的副本(s2中的值和s1相同) string s3 = "hello"; // s3是字面值"hello"的副本 (1) string s3("hello"); // 和上一行代码等价 string s4(10, 'c'); // 有参构造函数,s4的内容是cccccccccc
需要提一下的是,对于代码行(1)的字面值除了最后的空字符‘ ’其他所有的字符都被拷贝到新创建的string对象中。
直接初始化和拷贝初始化如果直接使用等号(=)初始化一个对象,实际上执行的是拷贝初始化,例如上面代码段中的
string s2 = s1;
如果不使用等号,那么执行的是直接初始化,比如:
string s3("hello");
建议:当初始值只有一个时,使用直接初始化和靠被初始化都行;如果想s4那样初始化需要用到的值有多个时,一般来说只能使用直接初始化的当时:
string s5 = "hello"; // 拷贝初始化 string s6("hello"); // 直接初始化 上面的两者等价 string s7(10, 'c'); // 直接初始化3.2.2 string 对象上的操作 读写string对象
可以使用IO操作符读写string对象:
// 首先要导入iostream库文件,以及合适的using申明 int main(){ string s; // 空字符串 cin >> s; // 读入s,遇到空白(空格符、换行符、制表符等)停止 cout << s << endl; // 输出s return 0; }
当然也可以输入输出多个对象。如果想读入未知数量的string对象可以使用以下代码:
int main(){ string s; while(cin >> s){ cout << s << endl; return 0; } }使用getline读取一整行
getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容直至遇到换行符位置(注意换行符也被读进来了),然后将所读的内容存入那个string对象(注意不存放换行符)。
getline只要一遇到换行符(‘n’)就结束读取操作并返回结果。
举个例子,下面的代码时一次读入一整行:
int main(){ string line; while(getline(cin, line)) cout << line << endl; //由于line中不包含换行符,所以我们手动的加上换行操作符 return 0; }string的一些操作
string的empty和size操作
empty函数根据string是否为空返回一个bool值;
size()函数返回string对象的长度(即string对象中字符的个数,不包含空字符);
对于size()函数来说,返回的是一个string::size_type类型的值,它是一个无符号整型的值,而且足够存放下任何string对象的大小,多有用于存放string类的size函数返回值的变量应该都哦是string::size_type类型的。
注:如果一个表达式中已经有了size()函数就不要再使用int,这样可以避免混用int和unsigned可能带来的问题。
比较string对象
string类定义了几种用于比较字符串的运算符:
1,相等性运算符(==和!=):两个字符串只有长度,对应字符(包括大小写)相等时才想等;
2,关系运算符<,<=、>,>=:依照字典顺序进行比大小。
string对象之间相加以及字面值与string对象相加
两个string对象相加得到的是一个新的string对象,对象内容是将加号左侧的运算对象的内容和加号右侧的运算对象的内容串接起来,同理也可以使用+=。
string s1 = "hello, ", s2 = "worldn"; string s3 = s1 + s2; // s3结果是 hello, worldn s1 += s2; // 等价于 s1 = s1 + s2
下面介绍字面值和string对象相加,标准库允许字符字面值和字符串字面值转换成string对象,从而在需要string对象的地方就可以使用这两种来代替,下面举出一个例子:
string s1 = "hello", s2 = "world"; string s3 = s1 + ", " + s2 + 'n'; // 得到的结果是 hello, worldn
选要注意的是,当string对象和字符字面值及字符串字面值混在一条语句使用时,必须确保每个加法运算(+)的两侧的运算对象至少有一个是string:
string s4 = s1 + " "; // 正确 string s5 = "hello" + ", "; // 错误,两个运算对象都不是string string s6 = s1 + ", " + "world"; // 正确,s1 + ", "得到的结果是一个string对象,然后这个对象再加上 "world" string s7 = "hello" + ", " + s2; // 错误,"hello" + ", "没有定义字面值相加
注意:由于某些历史原因,C++语言中的字符串字面值并不是标准库类型string的对象,所以切记,字符串字面值和string是不同的类型。
3.2.3 处理string对象中的字符我们经常需要单独处理string对象中的字符,这种处理的一个关键问题是如何获取字符本身,另外的一个问题是需要知道字符串中某些字符的特性(这个问题的解决可以通过导入库来进行处理)。
建议:使用C++版本的C标准头文件。
使用基于范围的for语句来处理每个字符 处理单个字符若目的是对string对象中的每个字符进行操作,建议使用C++11新标准的范围for语句:
for(declaration : expression) statement
其中,expression部分是一个对象,用于表示一个序列;declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。举个例子(将string对象中的每个字符输出来):
string str("some string"); for(auto c : str) // 对于str中的每个字符 cout << c << endl; // 输出当前字符
如果我们想统计某个string对象中标点符号的个数,可以使用for语句和ispunct函数:
string s("Hello World!!!!!"); decltype(s.size()) punt_cnt = 0; // punt_cnt 的类型为string::size_type for(auto c : s) if(ispunct(c)) ++punt_cnt; cout << punct cnt << " punctuation chatacters in " << s << endl;
同样的,我们也可以通过这种方法改变字符串中的字符(只不过是应用及格处理字符的函数)。下面的例子是将整个string对象转换成大写(用到的函数是toupper):
string s("hello world!!!"); for(auto &c : s) // 改变s中字符,需要用到引用 c = toupper(c); cout << s << endl;处理部分字符
上边所说的for循环适合于处理string对象中的每一个字符,如果想要访问string对象中的单个字符有两种方式:其一使用下标,其二是迭代器,本节后半段主要讨使用下标来访问某些字符。
下标运算符(’[]’)接受的输入参数是string::size_type类型的值,这个指标是要访问的字符的位置,返回值是该位置上字符的引用。string对象的下标从0计起。
注:string对象的下标必须大于等于0而小于s.size().
举几个例子
1,目标是将字符串的首字符改造写成大写形式:
string s("some string"); if(!s.empty()) s[0] = toupper(s[0]);
2,将s的第一个词改写成大写形式
for(decltype(s.size()) index = 0; index != s.size() && !isspace(s[index]); ++index) s[index] = toupper(s[index]);
条件部分的意思是,只有index到达s.size()之前并且当前字符不为空字符才为真。
3,编写一个程序,将0~15之间的数转换成相应的十六进制:
const string hexdigits = "0123456789ABCDEF"; cout << "Enter a series of numbers between 0 and 15" << endl; string result; string::size_type n; while(cin >> n) if(n < hexdigits.size()) result += hexidigits[n]; cout << "Your hex number is : " << result << endl;
在强调下,特别需要注意的是无论何时用到字符串的下标,都应该注意检查其合法性。
参考书籍:《C++ Primer》