(8)string对象上的操作1

 读写操作

//读写string对象的测试。
//本程序输入两string类,输出两string类。 #include <iostream> #include <string> using std::cin; using std::cout; using std::endl; int main() { //未初始化的为空string std::string s, ss; //和以前一样,">>"最终会返回左侧操作符(先把键盘输入存入对象再返回操作符),所以可以连续输入和输出。 /* *执行读取操作时,string对象会自动忽略开头的空白(空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇到下个空白为止。 *这意味着你输入“ 哈哈 ”,输出的是没有空格的“哈哈”。 */ cin >> s >> ss; /* *如果s存了一个字符,s[2]不存在,则程序运行到这崩溃; *如果s存了2个字符,s[2]输出空字符。 */ cout << "——" << s[2] << "——" << endl; //输出的字符串不会输出空字符。 cout << s << ss << endl; system("pause"); return 0; }

 

//读取未知数量的string对象的测试。
//本程序不限制输入的string类数量,且每次输入后会立即输出输入作为结果。 /* *注意,这里的未知数量指的不是未知字符串,而是string对象——可以这样理解,一个string对象存的字符串、数字等是不能出现空格的。 *(这个理解是错的,因为马上后面的getline函数就可以实现保存空白符的功能。真正的理解是,一个对象可以保持相当数量的字符串,所以字符串的长短和对象的多少没有关系) */ #include <iostream> #include <string> using std::cin; using std::cout; using std::endl; int main() { std::string word; //非法输入或者文件终止符:ctrl+z可以终止循环 。 while (cin >> word) /* *和我原来想的不一样....我原来以为是全部输入完了再输出,我错了,这是一个while,每次输入都会执行其体内的语句。 *仔细想想这好像是个不应该存在的功能。你输入的内容并不需要当作输出再输出一次,因为你输入的内容本身就可以显示在屏幕上了。 *所以只需要是一个没有循环体的while (cin >> word)就可以把你想显示在屏幕上的内容显示出来了。 */ cout << word << endl; }

 getline函数

//getline在string对象上的使用。
//本程序可以实现一整行的输出(虽然现在看来输入一行然后再输出一行一摸一样的东西好像没什么用),或者说是包含空白符的string对象的输出。
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
int main()
{
	std::string s;
	/*getline函数
	*1.参数是一个输入流和一个string对象:getline(cin,s)。
	*2.当我们希望能在最终得到的字符串中保留输入的空白符时,用他代替">>"运算符。
	*3.这个函数的操作是:从给定输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读内容存入string对象中(不存换行符)。
	*   即这个触发getline函数返回的那个换行符实际上被丢弃了,所以得到的string对象并不包含这个换行符(虽然读取了,但是读取的目地只是触发函数返回)。
	*/
	/*为什么getline函数能和cin一样作为判断条件?
	*因为和cin运算符一样,getline返回的是一个流参数——我的理解是(不一定对):cin返回的是cin这个流本身,getline返回的是一个输入流(换行符触发返回,把输入流存入string对象后返回流然后结束。)。
	*/
	//这个函数在命名空间中,所以还是得声明这个空间才能调用。
	//如果输入的第一个字符是换行符,则s是一个空string。
	while (std::getline(cin, s))
		//注意这里cout还是输出s而不是整个getline函数!即getline函数的作用是体现在“把输入的东西存入string对象(包括空白符)”。
		cout << s << endl;
	return 0;
}

string对象,或者说靠cin操作符、getline函数输入的内容都不可能有换行符,因为换行符在这两东西的定义中都代表了“输入结束”的意思。

 

要注意的一点是,有些操作是定义在命名空间std里的,而有些操作是string类里的成员函数所定义的操作(比如接下来要说的empty函数),这两种是不一样的,虽然都是对string类的操作,所以在使用的方法上也是有区别的。

 string的成员函数empty和size的操作

 

//empty函数——根据string对象是否为空返回一个布尔值
//本程序只输出非空行 #include <iostream> #include <string> using std::cin; using std::cout; using std::endl; int main() { std::string s; while (std::getline(cin, s)) { //这个if理解为:s.empty()=1【是空的】--》if(!1)——即如果【if】(s【s.empty】不是【!】一个空string)就执if函数体。 if (!s.empty()) cout << s << endl; else cout << "error" << endl; } return 0; }

 

//size函数——返回字符串长度
//本程序只输出超过一定长度的string对象。 #include <iostream> #include <string> using std::cin; using std::cout; using std::endl; int main() { std::string s; while (std::getline(cin, s)) { /* *如果输入的字符串长度大于2,则执行if函数体。注意,这个大于2和s[2]这个操作中的2不一样: *输入abc,字符串长度是3(不包括最后的空字符),而s[n]中的n最高虽然也能到3,但s[3]是空字符——因为是从0开始计数,s[0]是“a“. */ if (s.size() > 2) cout << s << endl; else { //这里即验证了s[2]中的数字和字符串长度一样时会发生什么 cout << "in less then size of string " << endl; cout << s[2] << endl; } } return 0; }

关于size函数的补充:string::size_type类型

对于size函数来说,返回的值既不是int类型也不是unsigned类型,而是string::size_type类型。string类及其她大多数标准库类型都定义了几种配套类型。

这些类型体现了标准库类型与机器无关的特性————这句话暂时这么理解:既然是C++自己根据自己库建立的类型,那么肯定机器无关,即任何机器只要有C++语言,就可以定义这些类型。也可以这么看,只有C++的那些库类型才需要这些相应的类型,没有那些库类型的就没有这些东西的必要。

string::size_type类型是定义在string中的,所以具体使用的时候要这样:

std::string::size_type;

尽管我们现在还不清楚这种类型的细节,但有一点我们需要知道:它是一个无符号的值,且能足够放下任何string对象的大小——所有size函数返回值的类型都是它。

过去这种类型不好使用和理解,现在C++11新标准中已经允许我们用auto或者decltype来推断变量的类型了,比如:

auto len = s.size(); //len类型是string::size_type

特别注意的是,下面这种代码会出现意想不到的结果:  

if (s.size() < -2)
    cout << s << endl;

知道为什么么?

注意(敲重点),size函数返回的是一个无符号数!用她来和一个带符号的负数进行比较会出现问题的,因为这个带符号的负数会转化成一个及其大的无符号值!

换句话说,一条表达式中有了size函数就不要再用int类型的值了——这样说来,前面的这段代码:

if (s.size() > 2)
    cout << s << endl;

这里面的2岂不是无符号数?我猜这是一个临时值2,或者说是传说中的纯右值~  

posted on 2017-10-13 08:08  wuduojia  阅读(162)  评论(0编辑  收藏  举报

导航