天天看點

stderr,stdin,stdout相關

轉載請保留原作者。

目錄

  • 一.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 ");
}