C語言學習趣事_關於C語言中的輸入輸出資料流_續一

來源:互聯網
上載者:User

      這兩天趕上高考,家裡有參加高考的,所以沒有來園子裡面逛逛, 今天高考完了,得閑了,所以出來透透氣。

      上次我寫了些關於printf()函數的的文字, 感覺自己對輸入輸出不是很瞭解, 並且自己表述的也不是很完整,還幾處小毛病,因此想接著上次的話題繼續瞎掰。

      那麼這次瞎掰點什麼呢 ? 那就從輸入輸出說起吧..................

1、流

    我不知道為什麼國內要把stream 翻譯成流, 不過這個翻譯倒是挺形象的。 我們知道C語言是伴隨那個偉大的系統——Unix——而成長的,在Unix及其衍生的系統中,

系統資源都是當做檔案來看待的。C繼承了這個傳統,當我們從鍵盤輸入字元的時候,C會把輸入裝置(即鍵盤)當做檔案來處理。當我們利用C開發工具提供的輸入輸出函數

來進行輸入和輸出時,C會把輸入輸出的內容當做“流”來處理。

    實際上流是一個理想話的對象,實際輸入或輸出裝置處理的內容映射到這個資料流中,而C會中這個資料流中擷取自己需要的資訊。

2、檔案

     檔案: 不知道怎麼精確定義這個名詞, 如果照大部分資料來看,檔案是指儲存在儲存介質上的一堆0101資訊的集合,或者可以認為是儲存介質上一Block Storage地區。

    前面說過在C中,系統資源當做檔案來處理, 這裡我們主要討論裝置檔案。

    在C運行後,會預設自動開啟三個裝置檔案: 標準輸入檔案、標準輸出裝置和標準錯誤輸出檔案。

    即:   STDIN   標準輸入檔案  (stdin)

            STDOUT  標準輸出檔案 (stdout)

            STDERR  標準錯誤輸出檔案 (stderr)

在有些系統裡面應該是這樣定義的:  #define  STDIN_FILENO   0    

                                               #define  STDOUT_FILENO  1

                                               #define  STDERR_FILENO  2

有的系統是這樣定義的:

                                              #define stdin     (&_iob[0])
                                              #define stdout   (&_iob[1])
                                              #define stderr    (&_iob[2])

3、 緩衝型輸入系統和非緩衝型輸入系統

     緩衝型輸入系統:是指當C要從從輸入檔案(這裡值標準輸入裝置,通常就是鍵盤)讀入資料流時,只有當使用者按下Enter ——(char)13 後使用者輸入的內容才能被被C使用。

     非緩衝型的系統:是指當C從輸入檔案讀如資料流時, 不需要等待使用者按下Enter鍵,C就能立即使用。

     如所示:

對於C而言,或者說對用C實現的執行實體而言,是否是緩衝或不緩衝,這個由系統決定,目前大部分系統對C而言是緩衝型輸入系統。

4、  getc()、putc()、getchar()、putchar()

需要說明的是這兩組函數應該是在效果上:  getc()== getchar()

                                                      putc()==putchar()

但是他們的原型,或者說定義形式卻是不一樣的。

首先來看:getc()和getchar()

在C中getc()的函數原型:

Exp:

     char  getc(FILE *);

     就是說如果要使用getch();函數你需要給他傳遞一個指標。

     那麼getchar()是怎麼實現的呢? 這裡有兩種實現方式: 函數和宏;  我們就說說宏的定義:

Exp:

      #define   getchar()    getc(stdin)

同樣來看:putc()和putchar(); 同樣putc()需要一個檔案指標,即其函數原型如:

Exp:

      int putc(FILE *);

於是putchar()的宏定義就是:

Exp:

    #define  putchar()  putc(stdout)

5、 EOF

     在用getchar()時,我們會從標準輸入裝置一個一個字元的讀取所輸入的字元,包括空白字元,例如:空格 、定位字元 和 斷行符號;在進行判斷的時候可以用一個EOF

來判斷是否是輸入的結束,這樣可以輸入任何想輸入的字元。

Exp:

       char  chInPut;

       while(EOF != (chInPut=getchar() ))

         {

               putchar(chInPut);

         }

當我們輸入:a  b  c  dd 

就會有輸出:a  b  c  dd

6、getc()

     在VC 6.0中有兩個get()的定義, 一個是宏,一個是函數

宏的定義如下:

    #define getc(_stream)     (--(_stream)->_cnt >= 0  ? 0xff & *(_stream)->_ptr++ : _filbuf(_stream))   

函數定義如下:

   _CRTIMP int __cdecl getc(FILE *);           

   在C語言的各家編譯器提供廠商裡面有一個不成為的“潛規則”,那就是如果一個標識符前面如果是以底線開頭,這樣的標識符通常是編譯器預定義的宏,或者預定義的標誌符。   

   我們看宏定義;這裡用到的宏實際還用到了一個預定義的函數:

                     _CRTIMP int __cdecl _filbuf(FILE *)

    從這個函數可以看出在getc()宏中使用的:_stream是一個具有檔案指標類型性質的預定義標識符。為了弄明白這個宏我們需要知道FILE類型的各個域;

其實FILE類型是另一個類型的重定義:  

Exp :

struct _iobuf

{

        char *_ptr;    
        int   _cnt;     
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
};

typedef  _iobuf  FILE;

  從上面可知FILE類型的結構體具有一個_cnt的域;這樣我們就來解析getc()的宏;首先看:

           --(_stream)->_cnt >= 0

   在C語言的規範裡面,我們知道 -> 的預算優先順序與尾碼 --的一樣,同時高於首碼 -- 的優先順序, 因此這裡就是每次執行這個宏的時候,就是先判斷_stream->cnt - 1

後其值是否大於等於0;如果大於或等於0的話,那麼這個宏就返回:0xff & *(_stream)->_ptr++ ; 如果小於0的話,那麼這個宏就返回: _filbuf(_stream)當大於等於

0的時候就說明緩衝區內還有文字資料流字元,這時取出當前字元並與0xFF進行位與作為getc(_stream)的傳回值, 並且將字元指標後移一位。

  當 _stream->cnt - 1的值小於0的時候就表示緩衝區內的字元已經全部遍曆過。但這時緩衝區內的內容還存在,只是指向緩衝區的指標已經移動到緩衝區後面,因此這

時就需要更新緩衝區內的內容,通過函數_filbuf(_stream)來實現, 函數_filbuf(FILE *) 同時將_stream的各個域重新賦值。

  細心的朋友也許可以發現: #define stdin     (&_iob[0])   中的_iob[0];其實也是一個FILE類型的指標數組,其引用是通過: extern FILE _iob[]; 來實現的。

就像前面說的 va_list 一樣_stream 標識符由編譯器的供應商定義,並且由編譯器解釋。這裡我們就不在討論這個FILE類型的預定義標識符。

如果那位大俠需要自己嘗試做個C的編譯工具,可以研究研究。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.