标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件,此外,string定义在命名空间std中。
#include <string>
using std::string;
定义和初始化
如果使用 =
初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去。如果不使用等号,则执行的是直接初始化。
当初始值只有一个时,使用直接初始化或拷贝初始化都行;如果初始化要用到的值有多个,一般来说只能使用直接初始化的方式,也可通过显示创建一个(临时)对象用于拷贝:
string s1 = "hi"; //拷贝初始化
string s2("hi"); //直接初始化
string s3(10, 'c'); //直接初始化,s7的内容是cccccccccc
string s4 = string(10, 'c'); //拷贝初始化。相当于使用参数‘10’和‘c’创建了一个string对象,然后又拷贝给了s3
string上的操作
常用操作:
os << s //将s写到输出流os中,返回os
is >> s //从is中读取字符串赋给s,字符串以空白分隔,返回is
getline(is, s) //从is中读取一行赋给s,返回is
s.empty()
s.size()
s[n]
s1 + s2 //返回s1和s2连接后的结果
s1 = s2; //用s2的副本代替s1中原来的字符
s1 == s2; //判断是否相等,对字母的大小写敏感
s1 != s2;
<, <=, >, >= //利用字符在字典中的顺序进行比较,对字母的大小写敏感
读写 string 对象:
可以使用IO操作符读写string对象:
int main(){
string s;
cin >> s;
cout << s << endl;
return 0;
}
在执行读取操作时,string对象会从第一个真正的字符开始读起,知道遇见下一出空白为止。如在上面的程序中输入“ hello world ”,则输出将是“hello”,输出结果中没有任何空格。
多个输入或者多个输出也可以连写在一起:
string s1, s2;
cin >> s1 >> s2;
cout << s1 << s2 << endl;
//此时若给这段程序输入与之前一样的内容,输出将是“helloworld”
读取未知数量的 string 对象
int main(){
string word;
while(cin >> word) //如果流有效,即没有遇到文件结束符或非法输入
cout << word << endl;
return 0;
}
使用 getline() 读取一整行
getline
函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(换行符也被读进来),将所读内容存入string对象中(不存换行符)。
getline
也会返回它的流参数,因此也能用其结果作为条件,因其只要一遇到换行符就结束读取操作并返回结果,所以可使用getline让它一次输出一整行而不是一个词( ‘>>’ 每次遇到空白就结束):
int main(){
string line;
while(getline(cin, line))
cout << line << endl;
return 0;
}
string 的 empty 和 size 操作
string line;
while(getline(cin, line))
if(!line.empty()) //empty返回一个bool值,当line为空时返回true
cout << line.size() << endl; //size返回string对象中字符的个数
string 对象的比较
string 对象的比较包括他们长度的比较以及所包含字符的比较,且字符的比较都依照字典顺序:
- 如果两个 string 对象的长度不同,而且较短对象的每个字符都与较长的对象对应位置上的字符相同,就认为较短 对象小于较长对象
- 如果两个 string 对象在某些对应的位置上不一致,则比较结果其实是 string 对象中第一对相异字符比较的结果
string str = "hello";
string phrase = "hello world";
string slang = "hi";
// str对象小于phrase
// slang对象大于str,也大于phrase
字面值和 string 对象相加
标准库允许把字符字面值和字符串字面值转换成 string 对象,当把 string 对象和字符字面值以及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是 string:
string s1 = "hello", s2 = "world";
string s3 = s1 + "," + s2 + '\n'; //将字符字面值和字符串字面值混在一起
string s4 = "hello" + ","; //错误:两个运算对象都不是string
string s5 = s1 + "," + "world"; //正确:根据其语义加上括号等价于 string s5 = (s1 + ",") + "world"
string s6 = "hello" + "," + s2; //错误
string 对象中字符的处理
在 cctype 头文件中定义了一组标准库函数:
isalnum(c); //c为字母或数字时为真
isalpha(c); //c为字母时为真
iscntrl(c); //c为控制字符时为真
isdigit(c); //c为数字时为真
isgraph(c); //c不是空格但可打印时为真
islower(c); //c为小写字母时为真
isupper(c); //c为大写字母时为真
isprint(c); //c是可打印字符时为真
ispunct(c); //c是标点符号时为真
isspace(c); //c为空白时为真
isxdigit(c); //c为十六进制数字时为真
tolower(c); //若c为大写字母,则输出对应小写字母;否则原样输出
toupper(c); //若c为小写字母,则输出对应大写字母;否则原样输出
使用 for 语句处理每个字符
string str("some thing");
for(auto c : str) //auto 关键字让编译器来决定变量c的类型。这里c的类型是char,每次迭代,str的下一个字符被拷贝给c
cout << c << end;
改变字符串中的字符
string s("hello world");
for(auto &c : s) //使用引用来实现字符串中字符的修改
c = toupper(c);
cout << s << endl;
//代码将输出 HELLO WORLD
只处理一部分字符
访问 string 对象中的单个字符有两种方式:使用下标和使用迭代器
下标运算符 接受的输入参数是 string::size_type (size_type)类型的值,参数表示要访问的字符的位置,返回值是该位置上字符的引用。
string s("some string");
if(!s.empty())
s[0] = toupper(s[0]);
//输出Some string
for(decltype(s.size()) index = 0; index != s.size() && !isspace(s[index]); index++) //decltype会根据s.size()的值确定index的类型
s[index] = toupper(s[index]); //在使用下标访问时必须保证该位置的合法性
//输出SOME string
一个例子:
const string hexdigits = "0123456789ABCDEF";
string result;
string::size_type n;
while(cin >> n)
if(n < hexdigits.size())
result += hexdigits[n];
cout << result << endl;
//输入:12 0 5 15 8 15
//输出:C05F8F