C++之(cin)与(!cin)的原理分析

在判断文件打开成功与否或是连续从流中读取数据时,就要用到对流对像的操作,比如if(!cin) 或是 whie(cin) 等等。

代码 while(cin>>val),我们都知道 cin 是一个流对象,而>>运算符返回左边的流对象,也就是说 cin>>val 返回 cin,于是 while(cin>>val)就变成了 while(cin),问题就变成了一个流对象在判断语句中的合法性。

不管是 while(cin)还是 if(cin),都是合法的,为什么呢?我们自己定义一个类,然后定义该类的对象,然后使用 if 语句来判断它是不合法的。这说明,流对象具有某种转换函数,可以将一个流对象转换成判断语句可以识别的类型。

打开 iostream.h 文件,找到 cin 的定义,发现是来自于 istream.h,其中的模板类basic_istream 继承自 basic_ios,打开 basic_ios 的定义,发现它有两个重载函数。operator void *() const 和 bool operator!() const。这两个函数使得流对象可作为判断语句的内容。

operator void*() const //转化函数
{
return this->fail() ? 0 : const_cast<basic_ios*>(this);
}

bool operator!() const
{
return this->fail();
}

结论:
1、operator void () const; 函数在 while(cin)或是 if(cin)时被调用,将流对象转换成 void 类型。

2、bool operator!() const; 函数在 while(!cin)或是 if(!cin)时被调用,将流对象转换成 bool 类型。

需要指出的是,上述两个类型转换都是隐式的。
因此,可以简单的理解调用过程为:

while(cin) =====> while(!cin.fail()) //while the stream is OK
while(!cin) =====> while(cin.fail()) //while the stream is NOT OK

简单测试:

#include<iostream>

using namespace std;

class A {
public:
    A() {}
    ~A() {}
    operator void * () const {
        return (void*)this;
    }
    bool operator!()const {
        return true;
    }
};

int main() {
    A a;
    if (a) cout << "operator void * () const" << endl;
    if (!a) cout << "bool operator!()const" << endl;
    system("pause");
    return 0;
}

输出结果:

这里写图片描述

通过调试可以看到if(a)调用的就是operator void * () const这个函数
if(!a)调用的bool operator!()const。

void _0_1::_1() { int a; student s; cin >> s.num[N]; cin >> s.name; cin >> s.sex; cin >> s.score1; cin >> s.score2; cin >> s.score3; i.v.push_back(s); cout << "是否继续添加学生信息?\n1. 继续\n2. 返回上一级菜单\n"; cin >> a; if (a == 1) { return _1(); } return; } void __1::_2() { int a = 3; vector<_>::iterator p = i.v.begin(); cout << "请输入要删除的学生学号:"; string num; cin >> num; for (; p != i.v.end(); p++) { if (p->num == num) { i.v.erase(p); a = 1; break; } } if (a == 1) { cout << "删除成功!" << endl; } else { cout << "未找到该学生记录!" << endl; } system("pause"); } 这里给出了两个修改后的函数 `_1` 和 `_2`,可能还需要对程序中的一些变量或类进行调整。 在 `_1` 中,我们添加了一个 `student` 类型的变量 `s`,用于存储新添加的学生信息。我们在输入学生信息后,将 `s` 插入到 `vector` 容器 `i.v` 的末尾,并询问用户是否继续添加学生信息。如果用户输入了 1,那么继续调用 `_1` 函数进行添加;否则返回上一级菜单。 在 `_2` 中,我们添加了一个 `vector<_>::iterator` 类型的迭代器 `p`,用于遍历 `i.v` 容器中的学生信息。我们先让用户输入要删除的学生的学号,然后在容器中查找是否有符合条件的学生记录。如果找到了,就通过 `vector` 容器的 `erase()` 方法将该学生记录从容器中删除,并输出删除成功信息;否则输出未找到该学生记录的提示信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值