天天看點

檔案結束符的使用

代碼如下      

--------------------------------------------------------------      

   int   main()      

   {      

   char   ch;      

   int   count   =   0;      

   cin.get(ch);      

   while (cin.fail()==false)      

   {      

   cout<<ch;      

   count++;      

   cin.get(ch);      

   }      

   cout<<"\n"<<count<<"characters read\n";      

   return   0;      

   }      

---------------------------------------------------------    

VC6.0控制台模式下(^z在VC中模拟檔案尾)      

為什麼輸入一串字元加^z後,回車,程式不會結束??!!      

   比如輸入:abcd^z       回車      

   程式回顯   abcd      

   按道理      

   當讀到^z時,檢測到了檔案尾,cin将eofbit,failbit都設為1      

   假如eofbit或failbit設為1,cin.fail則傳回true,應該結束程式了,調試中為什麼不結束?      

   輸入:abcd       回車      

   程式回顯:abcd       換行符(看不見),然後等待輸入,此時按下^Z       回車可以      

   為什麼上一種情況不可以?      

   困惑,尋找解答,謝謝!!     

答案:   

  原因分析如下:      

   輸入緩沖是行緩沖。當從鍵盤上輸入一串字元并按回車後,這些字元會首先被送到輸入緩沖區中存儲。每當按下Enter鍵後,cin.get() 就會檢測輸入緩沖區中是否有了可讀的資料。cin.get()還會對鍵盤上是否有作為流結束标志的 Ctrl+Z或者 Ctrl +D 鍵按下作出檢查,其檢查的方式有兩種:阻塞式以及非阻塞式。      

   阻塞式檢查方式指的是隻有在Enter鍵按下之後才對此前是否有Ctrl Z組合鍵按下進行檢查,非阻塞式樣指的是按下Ctrl  D   之後立即響應的方式。假如在按Ctrl D之前已經從鍵盤輸入了字元,則Ctrl D的作用就相當于回車,即把這些字元送到輸入緩沖區供讀取使用,此時Ctrl D不再起流結束符的作用。假如按Ctrl D之前沒有任何鍵盤輸入,則Ctrl D就是流結束的信号。         

   Windows系統中一般采用阻塞式檢查Ctrl Z、Unix/Linux系統下一般采用非阻塞式的檢查Ctrl D。樓主是在Windows系統下,是以使用阻塞式的Ctrl Z   來辨別流的結束。      

   這種阻塞式的方式有一個特點:隻有按下回車之後才有可能檢測在此之前是否有Ctrl Z按下。還有一個特點就是:假如輸入緩沖區中有可讀的資料則不會檢測Ctrl Z(因為有要讀的資料,還不能認為到了流的末尾)。還有一點需要知道:Ctrl Z産生的不是一個普通的ASCII碼值,也就是說它産生的不是一個字元,是以不會跟其它從鍵盤上輸入的字元一樣能夠存放在輸入緩沖區。明白了這幾點之後就可以來解釋樓主提出的問題了。      

   從鍵盤上輸入abcd^z加回車之後在Windows系統上是這樣處理的:由于回車的作用,前面的abcd等字元被送到輸入緩沖區(注意:上面說過了,^z不會産生字元,是以更不會存儲到輸入緩沖區,緩沖區中沒有^z的存在)。這時,cin.get()檢測到輸入緩沖區中已經有資料存在(是以不再檢查是否有^z的輸入),于是從緩沖中讀取相應的資料。假如都讀取完了,則輸入緩沖區重新變為空, cin.get()等待新的輸入。可見,盡管有^z按下,但是由于在此之前還有其它輸入字元(abcd),是以流也不會結束。      

   是以,輸入流結束的條件就是:^z之前不能有任何字元輸入(回車除外),否則^z起不到流結束的作用。   

   還有個問題      

   假如輸入abcd^zabcd      

   程式回顯   abcd      

   并等待輸入,也就是^Z後的不再顯示了      

   -----------------------------------------------      

   假如輸入緩沖區中有可讀的資料則不會檢測Ctrl Z(因為有要讀的資料,還不能認為到了流的末尾)。還有一點需要知道:Ctrl Z産生的不是一個普通的ASCII碼值,也就是說它産生的不是一個字元,是以不會跟其它從鍵盤上輸入的字元一樣能夠存放在輸入緩沖區。     

   假如輸入abcd^zabcd      

   程式回顯  abcd      

   并等待輸入,也就是^Z後的不再顯示了      

   為什麼後面的卻沒有處理呢?      

   是以可以把這種情況下的^z了解為鍵盤輸入的終止,但不是流的終止

--------------------------------------------------------------------------------------------

不過我認為答複仍然沒有解決我的疑問。假如當程式提示"please enter the first data"時,直接輸入^Z。按照2樓或return0x0朋友給出的方法,由于輸入緩沖區中沒有可讀的資料,則會檢測Ctrl Z。可是,實際情況是此時輸入的^Z并未終止程式的運作,仍然需要再輸一遍^Z才能中止程式。這是為什麼呢?

4樓的朋友可能用的是VC2003,正如hai040朋友說的:

vc2003,一次就行  

before input, current err state is:0  

please enter the first data  

^Z  

The first data is -858993460  

after input the first data, current err state is:3  

Press any key to continue

我用的是VC 6.0  轉載:http://lipingke.blog.hexun.com/40431101_d.html