轉載請保留原作者。
目錄
- 一.stdin和stdout
- 1.意義
- 2.緩沖
- 2.1.scanf的緩沖問題
- 2.2.fflush
- 3.freopen
- 二.stderr
- 1.輸出方法
- 2.預設緩沖
stdin表示标準輸入,stdout表示标準的輸出。它們都是檔案指針。預設情況下,所指向的檔案是控制台。
可以使用freopen進行重定向,或者fopen建立檔案指針,都是可以的。
#include<stdio.h>
using namespace std;
int main(){
int a;
while(scanf("%d",&a)!=1)printf("error!");
return 0;
}
這段代碼的原意是,如果讀入不到a,那麼就輸出error。
但是,stdin中的内容,scanf不是按照行讀入字元,而是根據連續的字元流讀入字元。是以,如果讀入一個非法字元,例如非數字的字元,那麼會出問題。因為讀入後,scanf發現錯誤,然後輸入error,再次讀入下一個字元時,上次的那個字元還殘留在流中,是以導緻無限輸出error。
對于這個做法,有人會使用fflush(stdin),這個問題我們下一章節繼續。
一般來說,stdout是有緩沖的。緩沖的意思就是先把字元存起來,到達某一時刻,把緩存的字元一次性寫入檔案。我們知道,硬碟速度比記憶體慢很多,每寫一個就存入一次速度很慢,如果累計起來一次放入速度會提高。
stdout預設是到達換行符重新整理。
fflush一般用于輸出的緩沖重新整理。也就是說,輸出到一半,使用fflush可以提前重新整理。
但是fflush隻能用于輸出的重新整理,輸入流不能這樣重新整理。fflush(stdin)可能在部分編譯器可以重新整理輸入流,達到上文的scanf重新整理,但是标準沒有定義這個行為。也就是說,部分編譯器是不支援的。
freopen(const char *filename,const char *mode,FILE *stream);
把stream重定向到filename的檔案名去。
例如,
freopen(“a.txt”,”r”,stdin);
表示把a.txt作為輸入重定向stdin。這樣,預設scanf就會從a.txt讀入而不是控制台。
第二個參數mode,表示模式,例如r表示文本讀入,w表示文本寫入,rb表示二進制讀入等。
如果在重定向到檔案後,重定向回控制台進行輸入輸出,可以把filename設定為“CON”即可。
标準錯誤流。
fprintf(stderr,...);
使用fprintf指定檔案指針為stderr,進行輸出,預設輸出檔案還是stdout的檔案。也就是說,也可以往控制台輸出,輸出位置一樣的。
讓我們寫個程式檢驗一下。
#include<stdio.h>
using namespace std;
int main(){
fprintf(stdout,"stdout ");
fprintf(stderr,"stderr ");
}
輸出:stderr stdout
看上去stderr先輸出?沒錯,就是這樣,沒有換行符的時候,stdout不會自動重新整理,但是stderr每寫一個字元都要重新整理。是以,stderr先輸出,程式結束的時候再重新整理一次,輸出stdout。
如果先加上fflush,那麼就是stdout先了。
#include<stdio.h>
using namespace std;
int main(){
fprintf(stdout,"stdout ");fflush(stdout);
fprintf(stderr,"stderr ");
}