作者khoguan (Khoguan Phuann)
看板C_and_CPP
标题Re: [问题] acm100...time exceed..
时间Sun Jun 12 09:57:38 2005
※ 引述《tvbic (轻薄的机掰)》之铭言:
: while(true)
: {
: cin>>a>>b;
: cout<<a<<" "<<b<<" "<<test(a,b)<<endl;
: }
: =============================================
: while(cin>>a>>b)
: {
: cout<<a<<" "<<b<<" "<<test(a,b)<<endl;
: }
: =========================================================
: 请问一下...这二种写法有什麽不一样吗..??
: 第二个可以过...可是第一个过不了...显示time limit exceeded
推文有解释过的,就不再说了。
将 cin 的读入放到 while 的条件测试中,是 C++
极常用的 idiom. 一方面达到读值的作用(side effect)
一方面 cin >> a >> b 这整个 expression 的结果就
是传回被读值後的 cin, cin 本身无所谓 true 或 false,
可是 while 条件需要 true 或 false, 於是程式就要去
找 cin 所属的 class (也就是 istream)是否有定义任何
conversion operator, 结果很高兴的发现了它有重载(overload)
operator void*
operator void* 若是传回 null (0) 就代表 false, 其他一切
non-null pointer 值就是 true. 在 operator void* 这个
overloaded function 的定义中,其实它是测试 cin 的状态是否为
fail(),若成员函式 fail()为真,则operator void* 传回 null
pointer (0), 那麽 while 的测试就失败,回圈结束;否则 operator void*
就传回某个 non-null pointer 表示为 true, 那麽 while就测
试成功了,回圈继续。
那麽这个 fail() 何时会为真呢?情况有数种,包括读到档尾(eof),
或是读到不合预期的东东,像是我们这里要读 int a, 和 int b,
也就是 cin >> a >> b; 结果却读到了英文字母,那就会 fail(),
甚至另外也会检查 istream buffer 是否坏掉了,那也会 fail().
另外 istream 也有重载 operator ! 其结果和上述颠倒。fail()
时传回真, !fail() 传回假。
另外补充,有很多人会写
while ( ! cin.eof() ) {
cin >> a >> b;
// 或是
getline(cin, str);
// ...
// 处理 a,b 或 str
}
这种写法通常是错误的,因为 eof() 几乎都是发生在回圈内。
好比说资料共十笔,那麽回圈跑十次,都没问题,甚至第十一次
还是可以继续进入回圈,只是在这次的回圈内,cin 要再读进一笔
资料时,才会发现已经读到档尾了(读完第十笔时还不知道!)
读取失败,而 a,b 或是 str 的值仍然保留上一次读到的,结果
程式还认定说它是有效的并加以处理,那就错了。
所以正确的写法同样是将 cin >> a >> b 或是 getline(cin, str)
写进 while (...) 条件中。至於 eof() 的使用时机,反而要在
整个回圈结束,在程式後面,有需要检查为什麽会结束回圈时,
才来使用 eof(), 因为如同前面所说, 有可能是到了档尾,也有
可能是读到不合所需的资料,或是 istream buffer 坏掉。
但像 ACM 的 input, 都可以放心的假定它给的资料不会有这些问题。
所以都不用再做离开回圈後的额外检查。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.130.208.166
1F:推 Frozenmouse:原来是这样@@ 谢谢指教:P 220.138.122.24 06/12
2F:→ Frozenmouse:之前一直不会解释为什麽cin>>a会回传什麽||| 220.138.122.24 06/12
3F:推 JuinT630:我了解了!谢谢大大的说明! 218.170.46.188 06/14