#include <cstdlib>
#include <string>
using namespace std;
int main()
{
int num = 0;
int count = 0;
char ans[90][90];
//while (scanf("%s", ans[num]) != EOF)
while (cin>>ans[num])
{
cout << "輸入了ans[" << num << "] ";
num++;
}
cout << endl;
for (int i = 0; i < num; i++)
{
cout << "ans[" << i << "]:" << ans[i] << endl;
}
return 0;
}
環境:win10+gcc 8.1.0
一段把通過終端接收到的,用空格隔開的字串存到陣列里的小程式,遇到EOF則停止接受字串
這里故意在句尾插入了ctrl+z,此時的ctrl+z應不被識別為EOF,讀到它的時候馬上停下并請求新的輸入
當使用被注釋掉的“應用了scanf的遇EOF則退出回圈”的while時,行為如下:



這里在請求新輸入時,再次輸入ctrl+z,此時仍然不退出while,而是把剛才駐留的ctrl+z(此時它在stdin里變成了ctrl+z原本的ascii碼26,而不是EOF)讀到了陣列里
然后便無視了第二次輸入的ctrl+z,再次執行while,請求新輸入。
注意,這個第二次輸入的ctrl+z好像就憑空消失了。第一次在句尾的ctrl+z好炊訓留了點“痕跡”,留了個ascii碼26,第二次敲入的ctrl+z既不讓scanf直接遇到進而回傳EOF,又不留下“痕跡”。
那么在讀到句尾ctrl+z后的第二次請求輸入時,不輸入ctrl+z呢?
1. 如果直接回車:效果與輸入了ctrl+z一樣,也就是說上面所述的敲入ctrl+z的效果就和沒敲而直接回車一摸一樣,好像ctrl+z不曾發生過。

2. 如果輸入其他的字串:ctrl+z的原始ascii碼粘在這個字串的最前面,并隨之存入陣列


在以上這些動作都結束后,新的一行中,直接輸入ctrl+z,scanf才終于識別出了ctrl+z,while結束了。
不用scanf而使用cin會怎么樣呢?

如果在此時輸入其他字串,行為與上述2一樣,ascii碼26粘在最前面并隨字串存入陣列
如果直接輸入ctrl+z,直接被識別為EOF,而前面ctrl+z帶來的的ascii碼26也存入陣列,while結束。
找了好多相關的問題,比如輸入兩次ctrl+z才結束,比如EOF相關問題
cin的行為倒是好解釋(自己的解釋),就是前面還有其他內容的ctrl+z不被接受為EOF,僅作為一個輸入結束的標志并以“ascii碼26”的本來面貌出現在stdin里,內部指標指到前面正常內容時正常運作,而指標指到它時停下,沒有后續動作,轉而請求新的輸入。
新的輸入進來時,指標仍指著剛才沒處理的ctrl+z(ascii 26),隨著回車,它也隨著其他內容“遲到地”被讀入了。
新的輸入如果是ctrl+z,就作為正常地,“新的一行”的ctrl+z被識別為觸發回傳EOF的條件。這也是為什么沒有兩個“ascii 26”。
而使用scanf的時候就不好解釋了,也就是那個ctrl+z到底去哪了?既不觸發回傳EOF,又不作為ascii碼進入陣列。
可能有朋友會想到,一串字串中間有ctrl+z的話,ctrl+z內容是不會被讀入的,仍然駐留緩沖。
那么如果是這樣,那這個ctrl+z也不會消失的,而且如果是這樣,cin和scanf的行為是不會不一樣的。
還是說有關這個機制有更多的說法呢?
另一種個人想到的可能問題是,while里cin、scanf的判斷條件還是有些差別的,問題就在這差別里。
在第二次的ctrl+z輸入后,scanf讀入了駐留的ascii 26,此時回傳值是1(成功讀入了1個資料),滿足條件1 != EOF,然后走了回圈里的東西,ctrl+z就由于某些原因被無視了。
而>>由于某些原因,不但讀到了駐留的26,還識別了ctrl+z。
這個“可能的原因”如果存在,是什么呢?直覺告訴我可能和c++流有別于C有關,真是如此嗎?或者干脆就是其他的什么原因呢?
小弟愚鈍,請不吝賜教
uj5u.com熱心網友回復:
太長了,能不能簡單描述下。。。uj5u.com熱心網友回復:
Linux:<Ctrl+D>
Windows:
<Enter>、<Ctrl+Z>、<Enter>
uj5u.com熱心網友回復:
情況有點細,簡單描述容易描述不清楚
真要簡單說:
當輸入一串字串,字串末尾是ctrl+z(第一次ctrl+z),以scanf接收。注意,這個ctrl+z肯定不能被識別為EOF,這是顯然的。
按下回車后,程式請求新輸入,再按一次ctrl+z(第二次ctrl+z)并回車,這個ctrl+z仍然無法識別為EOF,程式所作的,僅僅是繼續把剛才留下在句尾的ctrl+z的ascii碼讀下并存到陣列里。
就算此時不按下ctrl+z,僅回車,程式做的也是一樣的事,仿佛ctrl+z(第二次)沒出現過。
只有在這次回車后,再次輸入ctrl+z(第二次ctrl+z),才能讓scanf回傳EOF。
而如果用cin接收一串字串,字串末尾是ctrl+z(第一次),按下回車,然后末尾ctrl+z前的內容都被正常讀入,然后程式請求新的終端輸入。
區別在于,此時再次輸入ctrl+z(第二次),這個ctrl+z馬上能被識別為EOF,且剛才留在句末的ctrl+z的ascii碼也被正常讀入(注意,這是兩次不同的ctrl+z)。不需要讓ctrl+z出現第三次。
uj5u.com熱心網友回復:
更正一個字uj5u.com熱心網友回復:
我試了下,沒出現樓主說的現象。uj5u.com熱心網友回復:
我試了下,沒出現樓主說的現象。
請問兄臺編譯器是什么?
難道是我編譯器bug或其他環境問題?
uj5u.com熱心網友回復:
win10 + c++builderuj5u.com熱心網友回復:
win10 + c++builder
我這里問題是確實存在的
朋友能否告知一下你是指什么情況沒出現?
一樓所貼程式注意把cin的while注釋掉,用上面使用scanf的while就會發現“ctrl+z消失”的情況了
uj5u.com熱心網友回復:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/256457.html
標籤:C++ 語言
上一篇:裂變
