今天看了string和vector,感觉比起之前用C语言操作是要方便很多,但是又多了许多的规则要记住,c++学习是个漫长的过程啊。
标准库类型的string是表示可变长字符序列。用之前要先包含头文件#include <string>,还有就是string是属于std这个命名空间的,所以要惯例加上using namespace std;
string初始化
先来说说怎么初始化string:有两种初始化方式,一种的直接初始化,另外一种是拷贝初始化。
string s1;//默认初始化一个空串
string s2(s1);//s2是s1的副本
string s2 = s1;//等价于上面
string s3("value");//s3是字面值“value”的副本,出了最后的‘\0’
string s3 = "value";//同上
string s4(n,'c');//把s4初始化为n个字符c组成的串
直接初始化和拷贝初始化很容易区分,就是看有没有赋值号(=),有的话就是拷贝初始化。
string对象上的操作
os<<s 将s写到输出流os中,返回os
is>>s 从is中读取字符串给s,字符串以空白分隔,返回isgetline(is,s) 从is中读取一行赋给s,返回is s.empty() s为空返回true,否则返回false s.size() 返回s中字符的个数 s[n] 返回s中第n个引用的,位置从0计起 s1 + s2 返回s1和s2连接后的结果 s1 = s2 用s2来替代s1中原来的字符 s1 == s2 如果字符完全一样返回他们相等 s1 != s2 <,<=,>,>= 利用字典中的顺序进行比较,且对大小写敏感。
在读取操作时候string对象回自动忽略开头的空白(即空格符,换行符,制表符等)并从第一个真正的字符开始读起,只要遇见下一处空白为止。例如,输入的是“ Hello World ”,输出的将是"Hello"。输出结果中没有任何空格。输入和输出一样,也都是从非空白第一个字符算起,到第一个空白结束。
cin >> s1 >> s2;
cout << s1 << s2;
依旧把上面的输入,这时候输出的就是“Hello World”。这是需要记住的是空白是结束。第一个非空白的开始。
读取未知数量的string对象
用while(cin >> s),可以用于读取未知数量的字符串,但是你会发现问题来了,不能退出了。这里对这个做分析:因为cin是标准输入,作用就是接收来自终端的输入然后送入缓冲区中,当正确输入后,返回的是真。所以就退出不了。只有当检测到EOF也就是流的结束时候才能退出。流结束标志是 Ctrl+Z 或者 Ctrl+D 键按下作出检查。其检查的方式有两种: 阻塞 式以及非阻塞式。
- 阻塞式:windows一般用这种方法,这种方法是输入结束后再判断时候有Ctrl+Z,如果有就结束。所以,当你输入完就Ctrl+Z的话,这时候回自动把Ctrl+Z给忽略了,没有起作用,依然不能退出,这里只能输入完后回车,然后再Ctrl+Z,在回车,这时候就能退出来了。
- 非阻塞式:unix和linux一般用是的这个,这个退出就比windows方便多了,你只需要输入完回车,然后Ctrl+D,就退出了。不用再由cin来判断了。
使用getline读取一整行
getline函数的参数是一个参数输入流和一个string对象,就是从输入流中读入内容直到遇到换行符为止,这时候换行符也被读进来了,但是返回时候就把换行符给丢弃了,得到的string对象是没有换行符的。
比较string对象
string的比较是按照字典顺序来比较的:
1、如果两个string对象的长度不同,而且比较短的string对象的每个字符都与较长的string的对象相对应位置上的字符相同,就说较短的string对象小于较长的string对象。2、如果两个string对象再某些对应的位置上不一致,则string对象比较的结果其实就是string对象中第一对相异字符比较的结果
这个是书上的原话比较拗口。用大白话来说就是
1、比较两个string对象,如果其中一个是另一个的一部分,那么这个少的就是小于。2、完全不同时候,就一个字符一个字符比较,直到第一对不同的字符,那么比较的就是他们俩个了。
string str1 = "Hello";
string str2 = "HelloWorld"
string str3 = "Hiya"
用上面就规则可以看出str1就是str2你一部分所以 str1 < str2。然后看str1和str2他们第一个字符相同都是'H',但是第二个字符就不同了,所以我们需要比较的是‘e’和‘i’,又因为‘e’ < 'i',所以str1<str2。
处理string字符串
对字符串的操作自然不用多说,很多情况下都是在做字符的处理,什么变个大写,正则表达式,等等,c++给我们提供一些函数可以处理一些简单的字符串,这些函数在cctype这个头文件里。
isalnum(c) 当c是字母数字,即字母或数字,该函数返回true isalpha(c) 当c是字母,该函数返回真 isblank(c) 当c是空格或水平制表符,该函数返回true iscntrl(c) 当c是控制字符,该函数返回true isdigit(c) 当c是数字(0~9),该函数返回true isgraph(c) 当c是除空格之外的打印字符,该函数返回true islower(c) 当c是小写字母,该函数返回true isprint(c) 当c是打印字符(包括空格),该函数返回true ispunct(c) 当c是标点符号,该函数返回true isspace(c) 当c是标准空白字符,如空格、进纸、换行符、回车、水平制表符或者垂直制表符,该函数返回true isupper(c) 当c是大写字母,该函数返回true isxdigit(c) 当c是十六进制的数字,即0~9、a~f、A~F,该函数返回true tolower(c) 当c是大写字符,则返回其小写,否则返回该参数 toupper(c) 当c是小写字母,则返回其大写,否则返回该参数
当我们处理字符串里每个字符时候,我们最好用range forfor (declaration : expression)statement举个栗子来说明这货怎么用:
string str("hello world");
for (auto c : str)
{
cout << c << endl;
}
range for有两个参数,第一个表示每次取出来了那个元素,第二个就是我们要取的那个字符串,这样就很容易理解了,循环的次数取决于元素的个数,这种for和传统的for相比:
- 优点是不用人为判断循环次数,减少错误;
- 缺点恰恰也是优点,我们不能人为的限定循环次数。
上面的那种方法是不能修改字符串的,因为当中只是简单的拷贝给了c并不是真正的str里的元素,所以只要把改成&c,直接使用引用就可以了。
//把s全部转化成大写
string s("hello world");
for (auto &c : s)
{
c = toupper(c);
}
cout << s << endl;
string对象也有下表操作,就是类似于数组的那个。要注意的几个问题是:
- 下标操作每次操作一个字符
- 从0算起,到s.size()-1为止
- 访问未知空间(小于0,大于s.size()-1)将发生不可预测错误
- 下表类型是string::size_type这是个非负的数
总结:
string的操作重要性相比都很清楚,在实际过程中,无论是软件开发,web开发,web后台开发,就连嵌入式开发,有很大一部分时间都是在对字符串进行操作。字符串也是人和计算机的广泛的交互方式。