轉載請保留原作者。
一.stdin和stdout
1.意義
stdin表示標准輸入,stdout表示標准的輸出。它們都是文件指針。默認情況下,所指向的文件是控制台。
可以使用freopen進行重定向,或者fopen新建文件指針,都是可以的。
2.緩沖
2.1.scanf的緩沖問題
#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),這個問題我們下一章節繼續。
2.2.fflush
一般來說,stdout是有緩沖的。緩沖的意思就是先把字符存起來,到達某一時刻,把緩存的字符一次性寫入文件。我們知道,硬盤速度比內存慢很多,每寫一個就存入一次速度很慢,如果累計起來一次放入速度會提高。
stdout默認是到達換行符刷新。
fflush一般用於輸出的緩沖刷新。也就是說,輸出到一半,使用fflush可以提前刷新。
但是fflush只能用於輸出的刷新,輸入流不能這樣刷新。fflush(stdin)可能在部分編譯器可以刷新輸入流,達到上文的scanf刷新,但是標准沒有定義這個行為。也就是說,部分編譯器是不支持的。
3.freopen
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”即可。
二.stderr
1.輸出方法
標准錯誤流。fprintf(stderr,...);
使用fprintf指定文件指針為stderr,進行輸出,默認輸出文件還是stdout的文件。也就是說,也可以往控制台輸出,輸出位置一樣的。
2.默認緩沖
讓我們寫個程序檢驗一下。
#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 ");
}
