文章目录
标准库类型string表示可变长的字符序列,使用string类型的时候建议先加上string的头文件,string的定义也在命名空间std当中。
定义和初始化string对象
如何初始化类的对象是由类本身决定的,一个类可以定义很多种初始化对象的方式,只不过这些方式之间必须有所区别,或者是初始值不同,或者是初始值的类型不同。下面是初始化string的最常用的一些方式:
string s1; //1
string s2=s1;//2
string s3=“hi”;//3
string s4(10,‘c’);//4
string s5(“hi”);//5
- 默认初始化,s1是一个空字符串
- s2是s1的副本
- s3是指向该字符串字面值的副本
- s4的内容是cccccccccc
- s5与s3相同,是指向该字符串字面值的副本
直接初始化和拷贝初始化
由之前的学习中,我们明白了如果使用=初始化一个变量,实际上就是执行拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去。与之相反,如果不适用等号,则执行的是直接初始化
对于初始值只有一个的时候,使用直接 初始化或者拷贝初始化没有什么区别:
string s3=“hi”;//直接初始化
string s5(“hi”);//拷贝初始化
string s4(10,‘c’);//直接初始化
而对于多个值进行初始化的时候,可以使用直接初始化,也可以使用拷贝初始化,但是需要一个暂时的类进行储存,之后也会经常用到。
string s6 = string(10,‘c’);//拷贝初始化,
里面的内容是cccccccccc
string对象上的操作
一个类除了要规定初始化其对象的方式以外,还要定义对象上所能执行的操作。其中,类既能定义通过函数名调用的操作,也能定义<<,+等各种运算符在该类对象上的新含义。以下是string上的大多数操作。
os<<s;//1
is>>s;//2
getline(is,s);//3
s.empty()//4
s.size();//5
s{n};//6
s1+s2;//7
s1=s2;//8
s1==s2//9
s1!=s2//10
<、<=、>、>=//11
- 将s写道输出流os当中,返回os
- 从is中读取字符串赋值给s,字符串以空白分割,返回is
- 从is中读取一行赋值给s,返回is
- s为空返回true,否则返回false
- 返回s中字符的个数,不包括’\0’
- 返回s中第n个字符的引用,位置n从0开始计起
- 返回s1和s2连接的结果
- 用s2的副本代替s1中原来的字符
- 如果s1和s2中所含的字符全都一致,则他们相等
- 不一致则不相等
- 利用字符在字典中的顺序进行比较,且对字母的大小写敏感
读写string对象
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s; //空字符串
cin >> s; //将string对象读入s,遇到空白(回车和空格)停止
cout << s << endl;//输出s
return 0;
}
这段程序首先定义了一个名为s的空string,然后将标准输入的内容读取到s中,在执行读取操作的时候,string对象会自动忽略开头的空白(即空格符,换行符,制表符)并从第一个真正的字符开始读起,直至遇见下一个空白为止。
而如果我们向输入流输入" Hello World “的时候,输出将是"Hello”,输出结果中将没有任何空格。
读取未知量的string对象
这里仅给出代码部分,相信大家也可以轻松看懂。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;
while (cin >> str)
cout << str << endl;
return 0;
}
使用getline读取一整行
有时候我们希望可以在最终得到的字符串中保留输入时的空白符,这时候应该使用getline函数替代原本的>>运算符。getline函数的参数是一个输入流和一个string对象,函数从给定义的输入流中读取内容,直至换行符为止,然后把所读的所有内容存入那个string函数当中去。getline只要一遇到换行符就结束读取操作并返回结果,哪怕输出的一开始就只是一个换行符(空)。
如我们也可以使用getline让上面的代码一次性输出一整行
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;
while (getline(cin, str))
cout << str << endl;
return 0;
}
PS:触发getline函数返回的那个换行符实际上被丢弃掉了,得到的string对象中并不包含换行符
string的empty和size操作
empty作为string内部的一个函数,顾名思义,它就是判断string类型变量内部的数值是否为空,若为空返回true否则返回false的一个函数下面给出相关使用的代码:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;
while (getline(cin, str))
if(!str.empty())
cout << str << endl;
return 0;
}
size函数则是返回string对象的长度,见代码,不赘述
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str;
while (getline(cin, str))
if(str.size()>0)
cout << str << endl;
return 0;
}
string::size_type类型
string::size_type也就是常说的size_t类型,这里找到size函数的定义size_t size() const;以下是对于size_t的介绍
size_t是一个无符号类型的整数值,这是毋庸置疑的,因为没有字符串是-1个的是吧
所以我们在使用这个数据进行比较的时候,切记如果将其和负数的int进行比较,将会出错,具体原因可见之前的文章,这里不赘述。
比较string对象
string类定义了几种用于比较字符串的运算符。这些比较运算符逐一比较string对象中的字符,并且对大小写敏感。这里的比较一般是以字典的顺序来进行比较的。
举个例子进行理解
string str1 = “Hello”;
string str2 = “Hello World”
string str3 = “Hiya”
比较的顺序是按照字母的顺序来进行比较的,比较不相同的第一位,故str1和str2进行比较的话,str2大于str1,str3大于str1,str2;
为string对象赋值
允许用=号进行赋值,故:
string str1(10,‘c’),str2;
str2=str1;
两个string对象相加
两个string对象相加得到一个新的string对象,其内容是把左侧的运算对象与右侧的运算对象串联而成。
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str1="hello ", str2="world\n", str3;
str3 = str1 + str2;
str1 += str2;
cout << str3 << str1;
return 0;
}
应该也可以很简单的看懂吧,自行判断一下各自的值。
字面值和string对象相加
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1 = "hello", s2 = "world";//1
string s3 = s1 + "," + s2 + '\n';//2
string s4 = s1 + ",";//3
string s5 = "hello" + ",";//4
string s6 = s1 + "," + "world";//5
string s7 = "hello" + "," + s2;//6
return 0;
}
- 定义成string类型
- 正确用法
- 正确,把一个string对象和一个字面值进行相加
- 错误,两个对象都是字面值,相加的结果也还是字面值,不为string类型,类型不匹配。
- 正确,每个加法运算符都由一个运算对象是string。
- 错误,根据运算顺序可得,中间又一步骤是将两个字面值进行相加。
处理string对象的字符
我们经常要单独处理string对象中的字符,这在一头文件中由定义许多相关的函数
#include<cctype>
下面列出常用的函数:
isalnum( c );//1
isalpha( c );//2
iscntrl( c );//3
isdigit( c );//4
isgraph( c );//5
islower( c );//6
isprint( c );//7
ispunct( c );//8
ispace( c );//9
isupper( c );//10
isxdigit( c );//11
tolower( c );//12
toupper( c );//13
- 当c是字母或者数字的时候为真
- 当c是字母的时候为真
- 当c是控制字符是为真
- 当c是数字的时候为真
- 当c不是空格但可以打印的时候为真
- 当c是小写字母的时候为真
- 当c是可打印字符是为真
- 当c是空白时为真
- 当c是大写字母的时候为真
- 当c是十六进制时为真
- 如果c是大写字母,则输出对应的小写字母,否则原样输出c
- 如果c是小写字母,则输出对应的大写字母,否则原样输出c
处理每一个字符,使用基于范围的for语句
范围for语句的表达式
for(declaration:expression)
statement
其中expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,declaration部分的变量就会被初始化为expression部分的下一个元素值。
例如:
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string str("some string");
for (char c: str)
{
cout << c << endl;
}
return 0;
}
这个例子相信大家也可以更好的理解范围for的用法了。举个稍微复杂的例子。
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string str("Hello,World!!");
decltype(str.size()) punct_num = 0;
for (char c : str)
if (ispunct(c))
punct_num++;
cout << punct_num;
return 0;
}
这是统计标点符号的个数的函数,大家可以理解一下,也很好理解。
使用范围for语句改变字符串中的字符
这里写一个把字符串改编成其大写类型的具体函数
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string str("Hello,World!!");
for (auto c : str)
c = toupper(c);
cout << str;
return 0;
}
这里有一个切记的就是一定要记住auto c后面是==:==而非=。
只处理一部分字符
如果要处理string内部的所有字符,范围for语句确实是一个好主意,但是我们有时候要访问的是部分,则不太好用了。
一般是有两种方法进行处理:
第一种:下标运算符,要注意的是string类型是从第0位开始的,所以最后一位是str[str.size()-1]
PS:string对象的下标必须大于等于0,而小于str.size()如果超出这个范围将造成不可预知的错误,以此判断,用下标法访问空string类型也将产生不可预知的后果。
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string str("hello,World!!");
if (!str.empty())
str[0] = toupper(str[0]);
cout << str;
return 0;
}
第二种方法是使用迭代器,后续再进行介绍。
使用下标执行迭代
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
string str("hello World!!");
for (decltype(str.size()) index = 0; index != str.size() && !isspace(str[index]); index++)
{
str[index] = toupper(str[index]);
}
cout << str;
return 0;
}
这里可以停顿调试理解一下。也就是之前综合的知识。
使用下标执行随机访问
这里也是一段函数仅供理解,题目是将0-15的数据转换为16进制数。
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int main()
{
const string hex = "0123456789ABCDEF";
string str;
int num;
while (cin >> num)
if (num < hex.size() && num >= 0)
str += hex[num];
cout << str;
return 0;
}
如果是读者复制了代码准备调试时,切记要输入一个crtl+z原因就在于cin>>num放于while内,此符号声明读取结束。