今天的主要内容是字符串。学过C的同学知道,C中的字符串是一个以'\0'为结尾的字符型数组。但是到了C++中传统的C风格的字符串也显得没有那么的智能方便。下面就开始新的C++中的字符串的学习,有关字符串的函数都在<string>中。记得把头文件扩进去。
1.命名空间的using声明
在C++中命名空间的定义被引述了出来。由于可能我们描述函数或者变量等等的名词太少,容易出现冲突。比如你是A班的小李,那很有可能存在B班的小李。当我叫小李的时候,很可能就无法分辨出叫哪个人。所以有了A班的和B班的之分。A、B两个班就是两种不同的命名空间。在C++中用类似 std::something;这样类似的语句来说明这个something是属于std空间的。我们平时使用的大部分基本的C++操作都是属于std空间的,比如标准流式输入输出cin和cout两兄弟。但是如果每用一个名词都要打std是否有些太繁琐了呢。所以可以使用
using namespace std;
这样当你没有给一个对象声明它所属的命名空间的时候,编译器就默认它是属于std的。这要是很多人入门c++的时候在代码中经常能看到的语句。
这里需要注意一点,头文件中是不应该包含using声明的。这是因为头文件的内容会拷贝到所有引用它的文件中,如果头文件中有了using声明,那么每一个使用它的文件中都会有有这个声明。很有可能造成意想不到的冲突。
2.string类型及其初始化
C++中的string是标准库类型。和C不同的是,这里字符串有了属于自己的独立的类型。它的长度是可变的。标准库可以理解成为你平时工作最常使用的工具箱,这里面好东西很多。下面有几种字符串对象的初始化方式。
string s1;//这是默认的初始化,一般来说会得到一个空的字符串
string s2 = s1;//使用s1为s2赋予初始值,产生了一个和s1一模一样的s2
string s3 = "tutu";//使用字面值常量赋予初始值,里面的对应内容自然也就是字面值
string s4 = (5,w);//s4 里的内容是"wwwww"
string s5(s1);//效果同s2
string s6("tutu");//效果同s3
下面有一个点,是关于直接初始化和拷贝初始化的区别。直接初始化相当于建立一个对象然后里面的值就是那么多。而拷贝初始化是利用已有对象的基础上,通过拷贝值的方式再复制出一个。具体来看
string s1 = "tutu";//这里是拷贝初始化
string s2("tutu");//这里是直接初始化
string s3(5,'w');//直接初始化
乍看起来用'='的一般来说就是拷贝初始化。额虽然弄清楚了这点,但是不知道以后有啥用。
3.关于string的操作
假设os是输出流,in是输入流。暂时可以把他们当做是cout 和 cin。
os<<s; //将s的值写到os输出
in>>s;//读取in中的值给s << >>理解成两个箭头 箭头指向哪数据流向哪
getline(in,s);//从输入流中得到一行数据给s
s.empty();//要是s是空的就返回真
s.size();//返回s的大小,字符串的长度
s[n];//n号元素的值,从0开始算
s1+s3;//两个字符串连接在一起
s1=s2;//用s2里的字符串替换掉s1里面的
s1 == s2;//相等则是真 不相等则是假 比strcmp()简单多了吧
s1 != s2;//同理
<,>,<=,>=;//参照字典序比较,大小写不同
4.string对象的读写
来看看下面的代码
#include<iostream>
using namespace std;
int main()
{
string s;
cin>>s;
cout<<s<<endl;
return 0;
}
这里既有string的写也有string的读。但是注意string在写的时候会自动忽略你输入的前面若干个空白。从第一个非空字符开始写,直到下一个空白。如果你尝试输入的是" Hello World "。那么最后输出的结果将会是“Hello”。
针对上面的语句如果使用代码 string s1; cin>>s>>s1; cout<<s<<s1; 那么输出的结果将会是"HelloWorld"注意所有的空格都消失了。hello 和 world分别给了s 和s1。
如果希望不忽略空格,那么可以使用getline()函数。这里并不会忽略空格,直到换行符。
5.string的empty()和size()
按照字面的意思可以得知,empty()当string为空的时候有效。size()得到的是字符串的长度。需要注意的是,size()返回的类型并不是int或者unsigned int。它有自己的类型string::size_type类型。可以理解成为是一个足够大的无符号整数。在一条语句中如果出现了size()建议不要使用int这种带符号的整数等。因为当s.size()<int 当int是一个负数的时候就会自动转化成一个十分大的无符号整数,很容易偏离原有的意思。另外由于学过auto 可以使用
auto size = s.size();
这种方式是很稳妥的。
6.处理string对象中的字符
可以对字符串中的单个字符进行相应的操作。下面列举了一些定义在<cctype>中的十分有用的函数
isalnum(c) 判断c是否是字母或者数字
isalpha(c) 判断c是否是字母
iscntrl(c) 当c是否是控制字符
isdigit(c) c是否是数字
isgraph(c) 当c不是空格但可以打印时是真
islower(c)看看c是否是小写字母
isprint(c) c是否是可打印字符
ispunct(c) c是否是标点符号
isspace(c) c是否是空白
issupper(c) c是否是大写字母
isxdigit(c) c是否是十六进制
tolower(c) 将c转化成小写字母
toupper(c) 将c转化成大写字母
7.范围for
我们很熟悉for循环,这里针对当要逐一处理字符串的时候使用一种新的使用方式。即范围for
形式如
for(declaration : expression)
statement;
其中expression是一种序列对象,比如像字符串这种由多个字部分按顺序组成的对象。后面还要介绍到容器什么的。比如要把字符串里的字符都变成大写 可以使用
string s = "ttttttttt";
for(auto c : s)
c = toupper(c);
在字符串中可以使用下标s[n]来单独访问一个字符。在使用的时候一定注意n别越界。
搞定,跟C中的字符串相比,C++中已经做了很多的改进。打完收工。