C語言的標準輸入輸出

來源:互聯網
上載者:User

標籤:safe   des   printf函數   工作   keyword   變數   sso   syntax   進位   

歡迎探討,如有錯誤敬請指正 

如需轉載,請註明出處 http://www.cnblogs.com/nullzx/

1. 標準輸入輸出

標準輸入、輸出主要由緩衝區和操作方法兩部分組。緩衝區實際上可以看做記憶體中的字串數組,而操作方法主要是指printf、scanf、puts、gets,getcha、putcahr等操作緩衝區的方法。在C++以及Java等物件導向的程式設計語言中,將緩衝區以及操作緩衝區的方法封裝成一類對象,這類對象就稱為流。

緩衝區最大的特點主要體現在資料的一次性,即資料被printf、scanf從緩衝區中取出後就被使用了,或者說消耗了。可以把緩衝區比喻成管道,緩衝區中的資料比喻成水流,printf、scanf等方法比喻成開關,當開啟開關,水就會慢慢流逝,而流出去的水就再也收不回來了。

由於不同系統,不的硬體底層實現輸入輸出的具體方法可能不一樣,C語言要求系統為每個程式提供兩個指標,這兩個指標分別指向兩個結構體,這兩個結構體分別表示了鍵盤和螢幕在記憶體中的抽象表示(緩衝區的地址值被記錄在這個結構體中),並將指向這兩個結構體的指標命名為stdin和 stdout.這兩個指標就是所謂的標準輸入和標準輸出。

還有一點應該始終銘記,標準輸入和輸出緩衝區中儲存的是字元的ASCII碼值。比如你想從鍵盤上輸入了123給一個變數,那麼在緩衝區中儲存是三個位元組,分別是字元‘1’的ASCII碼值,字元‘2’的ASCII碼值,字元‘3’的ASCII碼值,然後將這個這三個ASCII值序列轉換為一個數值給這個變數。同理,從螢幕輸出“123”,電腦並不認為它輸出的是一個數值,電腦實際上僅僅是描繪了一個‘1’的ASCII碼值對應的圖形,‘2’的ASCII的值對應的圖形,‘3’的ASCII碼值對應的圖形。

2. getchar、putchar

putchar的作用主要是向輸出緩衝區中寫入一個字元。

getchar的作用主要是向輸入緩衝區中讀取一個字元。如果碰到檔案結尾,返回-1

getchar原始碼

12345678910 int getchar(void){     static char buf[BUFSIZ];     static char* bb = buf;     static int n = 0;     if (n == 0) {         n = read(0, buf, BUFSIZ);         bb = buf;     }     return(--n >= 0) ? (unsigned char)*bb++ : EOF; }

OEF是一個宏,表示-1。getchar的傳回值是int,對於檔案來說-1表示了檔案的結尾。我們可以在鍵盤上利用Ctrl+Z來實作類別似的效果

從getchar的原始碼中可以看出,如果發現字元數組buf已空(n==0),則調用read方法從鍵盤讀取資料(該方法會導致阻塞),並讓指標指向數組的首地址。如果緩衝區還有字元沒有被讀取(n > 0),則讀取它,同時n-1,指標(bb)向後移動一位。當緩衝區已空(n==0),且read函數讀取失敗時(讀取到了檔案末尾),返回EOF。

從scanf的原始碼中可以看出getchar可以讀入任何字元,包括空白符(空白符包括:空格、分行符號、定位字元等)。

3. gets、puts

puts函數主要向輸出緩衝區寫入一個字串,並再字串輸出結束以後,再額外輸出一個分行符號 ‘\n‘

gets用於從輸入資料流的緩衝區中讀取字元到指定的數組。讀取過程中會忽略所有的前置空白符,讀入的第一個字元為非空白符,直到遇到分行符號才停止讀入,結束的分行符號(‘\n‘)被gets函數讀從緩衝區讀取走了,存於數組中,然後被替換成‘\0‘

gets 原始碼(只需要看for迴圈這部分代碼,FLOCKFILE(stdin)表示對輸入緩衝區加鎖對;FUNLOCKFILE(stdin) 表示對輸入緩衝區解鎖)。

1234567891011121314151617181920 char* gets(char *buf){     int c;     char *s;     static int warned;     static const char w[] = "warning: this program uses gets(), which is unsafe.\n";    FLOCKFILE(stdin); ORIENT(stdin, -1);     if (!warned) {         (void)_write(STDERR_FILENO, w, sizeof(w) - 1);        warned = 1;     }     for (s = buf; (c = __sgetc(stdin)) != ‘\n‘;)         if (c == EOF)             if (s == buf) {                 FUNLOCKFILE(stdin); return (NULL);             } else                break;         else            *s++ = c; *s = 0;         FUNLOCKFILE(stdin); return (buf); }

從原始碼可以看出,如果讀入了‘\n‘則停止,並替換成‘\0‘

4. printf的使用

定義函數 int printf(const char * format,...);

函數說明 printf()會根據參數format字串來轉換並格式化資料,然後將結果寫出到標準輸出裝置,直到出現字串結束(‘\n‘)為止。

參數format字串可包含下列三種字元類型:

(1)一般文本,伴隨直接輸出。

(2)逸出字元,如\t、\n等。

(3)格式轉換字元,格式轉換為一個百分比符號(%)及其後的格式字元所組成。一般而言,每個%符號在其後都必需有一printf的參數與之相呼應(只有當%%轉換字元出現時會直接輸出%字元)

格式轉換字元詳解 “%[符號][寬度][.精度]類型”

[寬度]:表示最少輸出的字元個數

[符號]:“-”表示對齊

(1)%-8,靠左對齊,當顯示字元不足8時,右補空格

(2)%08,靠右對齊,當顯示字元不足8時,左補0

[.精度]對於浮點數表示小數點後的位元

數值小數點後的位元大於顯示精度,則只能顯示[.精度]個小樹位元(四捨五入),如果數值小數點後的位元小於顯示精度,則補零。

%.5 小數點後顯示5位

類型

(1)%d:用於顯示十進位有符號數,char,short,int,long long

(2)%u:用於顯示十進位無符號數,unsinged short,unsigned int,

unsigned long long

(3)%x: 用於顯示十六進位整數,所有有符號及無符號整型

(4)%f:用於顯示十進位浮點數,float,double

(5)%c:顯示字元

(6)%s:顯示字串

printf(“%s”,xxx)puts(xxx)的區別:puts函數會自動添加換行,而printf(“%s”,……)不會。

5. scanf的使用

定義函數 int scanf(const char * format,...);

函數說明 scanf()會將輸入的資料根據參數format字串來轉換並格式化資料。Scanf()格式轉換的一般形式如下:

“%[寬度][資料所佔位元組數]輸入類型”

[寬度]:最多輸入的字元個數

[資料類型]:

h表示兩位元組,short 

l表示八位元組,用於long long和 double

什麼都沒有表示四位元組

[資料類型]輸入類型

(1)%d:int 

(2)%f:float 

(3)%lf:double 

(4)%hd:short 

scanf(“%c”,&x) 等價於 x = getchar(),雖然getchar的傳回值是int類型,但不影響使用

(5)%s:字串

用scanf讀取字串時,忽略前置的空白符,再次遇到空白符會結束輸入,並將再次遇到的空白符留在緩衝區內,自動添加字串數組的結束標誌‘\n‘

12345678 #include <stdio.h> void main(int argc, char* argv[]){     char a[20]; int ch; scanf_s("%s",a,20);     printf("%s\n", a);     while ((ch = getchar()) != EOF ){         putchar(ch);     } }

我們輸入i love you(ctrl+z)

scanf_s 讀取字元‘i以後結束(i後是空格),通過getchar函數第一個讀取的字元就是空格,getchar會一直讀取緩衝區中,直到緩衝區為空白。

6. fgets、fputs、fscanf、fprintf、fgetchar、fputchar

上述方法只是多了個參數FILE * stream,表示這時的輸入以stream指定的檔案作為輸入或者輸出

char* fgets(char* _Buf, int _MaxCount, FILE* _File);

int fputs(const char * _Str,FILE* _File);

int fprintf(FILE* _File, const char * _Format, ...);

int fscanf(FILE* _File, const char * _Format, ...);

int fgetc (FILE* _File) ;

int fputc(int _Ch, FILE* _File);

7. 其它相關函數

int sprintf( char *_Dest, const char * format,...);

函數說明sprintf和printf函數很類似,printf是將結果寫入到標準輸出資料流中,而sprintf是將結果寫入到字串數組_Dest中。傳回值傳回值返回參數str字串長度,失敗則返回-1。

1234567 #include<stdio.h>void main(){     char* a = "This is string A!";     char buf[80];     sprintf_s(buf,"begin %s end\n", a);     printf("%s",buf); }

int sscanf_s(const char * _Src, const char * _Format, ...);

sscanf函數與scanf類似,只不過scanf是從輸入資料流中讀取資料,而sscanf是從字串數組_Src中讀取資料

1234567 #include<stdio.h> void main(int argc, char* args[]){     int i; double n;     char str[20] = "123 3.1415";     sscanf_s(str, "%d%lf", &i, &n);     printf("%d\n%f\n", i, n); }

 

 

設定流緩衝

int fflush(FILE* stream);

void setbuf(FILE* stream, char* buf);

int setvbuf(FILE* stream, char* buf, int mode);

資料總是先寫入(或者讀取)到流中,當緩衝區滿了後,在將其寫入到裝置(或者擷取讀取到程式中),這樣的工作方式效率更高。但是有時候我們可能需要更快的相應速度,我們可以調用fflush方法來沖刷緩衝區,注意這裡沖刷的意思不是將緩衝區的內容刪除,而是將還未滿的緩衝區中的內容寫入到裝置(或者讀取到程式中)

setbuf中可以由參數buf自己設定緩衝區的位置和大小(大小由buf數組的大小決定)。

setvbuf中的第三個參數決mode定了緩衝區的緩衝類型。它由三種取值

_IOFBU:全滿緩衝類型

_IOLBU:行滿緩衝類型

_IONBU:無緩衝類型

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.