C语言标准 I/O
標準I/O:
1.I/O(Input/Output)就是輸入與輸出的簡稱.
2.標準I/O是ANSI C標準(C庫)中定義的一系列用于I/O操作的函數(shù).編程中,我們只要包含了相對應(yīng)的頭文件(.h)就可以調(diào)用我們要使用的標準輸入輸出函數(shù).
3.標準I/O一般用于終端的輸出與輸出.
系統(tǒng)調(diào)用:
操作系統(tǒng)的主要功能是為管理硬件資源和并且為應(yīng)用程序和硬件資源之間提供一個既用于阻隔又用于連接的橋梁.為了達到這個目的,操作系統(tǒng)的內(nèi)核(操作系統(tǒng)的核心部分)提供一系列具備預(yù)定功能的內(nèi)核函數(shù),通過被稱為"系統(tǒng)調(diào)用"的"編程接口API"供應(yīng)用程序使用.應(yīng)用程序?qū)?shù)據(jù)通過"系統(tǒng)調(diào)用"傳遞給內(nèi)核函數(shù),內(nèi)核函數(shù)再將數(shù)據(jù)傳遞給硬件處理后,數(shù)據(jù)通過內(nèi)核最后返回給應(yīng)用程序.
"流":
當(dāng)用標準I/O打開一個文件時,系統(tǒng)會創(chuàng)建一個FILE結(jié)構(gòu)體來描述該文件,我們稱這個FILE結(jié)構(gòu)體為"流".之后,所有的I/O操作都圍繞這個"流"進行(操作這個流(FILE結(jié)構(gòu)體)就等于直接操作文件本身).
創(chuàng)建"流"的同時,系統(tǒng)會在用戶空間創(chuàng)建一個緩存區(qū),在進行實際的I/O操作之前,我們先將數(shù)據(jù)存儲到這個緩存區(qū)中,直到達到某個條件,我們才對緩存區(qū)中的數(shù)據(jù)進行實際的I/O讀寫操作.
因為每一次實際的I/O操作都要使用系統(tǒng)調(diào)用,如果不使用標準I/O,系統(tǒng)緩存區(qū)也就不存在,那么每讀寫一個數(shù)據(jù)就要使用一次系統(tǒng)同調(diào)用.這樣的話系統(tǒng)使用效率將會大大降低.而如果使用了標準I/O,多個數(shù)據(jù)首先是保存在系統(tǒng)緩存區(qū)中,當(dāng)條件滿足是,我們才一次性的對緩存區(qū)中的數(shù)據(jù)進行實際的I/O讀寫操作,從而減少了使用系統(tǒng)調(diào)用的次數(shù),大幅提升了系統(tǒng)的使用效率.
標準I/O的緩沖類型:
緩存區(qū):
在進行標準輸入與輸出時,數(shù)據(jù)并不是直接被函數(shù)獲取(輸入)或者打印顯示到終端(輸出),而是先保存在一個系統(tǒng)自動分配的緩存區(qū)內(nèi).當(dāng)滿足一定的條件時,數(shù)據(jù)才進行實際的I/O(輸入輸出)操作.
緩沖類型:
全緩沖: 填滿緩沖區(qū)后才進行實際的I/O操作.
行緩沖: 當(dāng)輸入和輸出中遇到換行符時,進行實際的I/O操作.
無緩沖: 不進行數(shù)據(jù)緩存,直接進行實際的I/O操作.
"流"的打開(創(chuàng)建FILE結(jié)構(gòu)體):
#include //頭文件
FILE *fopen(const char *path,const char *mode); //函數(shù)原型
參數(shù) : path : 實參傳遞的是文件的路徑(包括文件名),用一個字符串表示: "****".
這里形參是一個指針常量,指針指向的存儲空間中的值不能改變.
mode : 實參傳遞的是文件的打開方式,用一個字符串表示: "**".
"r" : 以只讀方式打開文件,文件必須存在.
"r+" : 以可讀寫的方式打開文件,文件必須存在.
"w" : 以只寫方式打開文件,文件不存在則創(chuàng)建;文件存在則擦除文件中的內(nèi)容.
"w+" : 以可讀寫的方式打開文件,文件不存在則創(chuàng)建;文件存在則擦除文件中的內(nèi)容.
"a" : 以只寫方式打開文件,文件不存在則創(chuàng)建;文件存在則新內(nèi)容從文件內(nèi)容末尾開始寫入.
"a+" : 以可讀寫方式打開文件,文件不存在則創(chuàng)建,文件存在則新內(nèi)容從文件內(nèi)容末尾開始寫入.
返回值 : 執(zhí)行成功返回FILE結(jié)構(gòu)體指針(流指針);出錯返回NULL.
編程操作 : FILE *fp; //定義FILE結(jié)構(gòu)體指針變量,這個指針指向的FILE結(jié)構(gòu)體的內(nèi)存空間是系統(tǒng)自動分配的.
fp = fopen("文件路徑","文件打開方式");
注 : 操作系統(tǒng)啟動時,系統(tǒng)會自動打開三個流: 標準輸入流 : stdin ,默認鍵盤.
標準輸出流 : stdout,默認當(dāng)前終端.
標準錯誤流 : stderr,默認向當(dāng)前終端輸出錯誤信息.
流的關(guān)閉:
流打開后,如果我們不再使用它,就一定要將其關(guān)閉(釋放FILE結(jié)構(gòu)體指針變量指向的內(nèi)存空間).
#include //頭文件
int fclose(FILE *fp); //函數(shù)原型
參數(shù) : 打開的流指針fp.
返回值 : 執(zhí)行成功返回0;出錯返回EOF(數(shù)值上等于-1).
使用這幾個標準I/O時流的打開和關(guān)閉都是系統(tǒng)自動完成的.
常用標準輸出函數(shù):
按字節(jié)輸出:向終端輸出一個字節(jié)(字節(jié)).
#include //頭文件
int putchar(int c); //函數(shù)原型,在系統(tǒng)頭文件中定義.
參數(shù) : c :傳遞給形參c的實參是一個整型常量\字符型常量\整型變量\字符型變量.;
返回值 : 成功返回輸出的字符;出錯返回-1.
格式化輸出 :
格式化輸出就是將數(shù)據(jù)按照一定的格式輸出.
#include //頭文件
int printf(const char *format, ...); //函數(shù)原型
參數(shù) : format :是一個字符串,用"*****"的形式編寫.這個字符串可以同時包含自定義輸出信息和格式轉(zhuǎn)換符,如
果沒有數(shù)據(jù)需要格式化輸出時,我們就可以只輸出自定義信息;反之,我們也可以只格式化輸出數(shù)據(jù),
而不帶自定義輸出信息.
... :形參表,傳遞的實參是與參數(shù)format中格式轉(zhuǎn)換符對應(yīng)的常量或變量.格式轉(zhuǎn)換符與傳遞的實參是一
一對應(yīng)的: 實參是何種數(shù)據(jù)類型,format中就要使用對應(yīng)的格式轉(zhuǎn)換符;傳遞的實參有多少個,format
中就要有對應(yīng)的多少個格式轉(zhuǎn)換符.多個實參之間用','隔開.
返回值 : 成功返回輸出的數(shù)據(jù)字節(jié)數(shù);出錯返回負數(shù).
緩沖類型: 行緩沖,遇到換行符'\n'才進行實際的I/O操作.我們使用printf函數(shù)進行實際數(shù)據(jù)的輸出時,一定不要漏寫換行符'\n',不然可能造成數(shù)據(jù)讀寫錯誤.
格式轉(zhuǎn)換符: %d : 格式化輸入輸出十進制整數(shù).
%u : 格式化輸入輸出無符號十進制整數(shù).
%o : 格式化輸入輸出八進制整數(shù).
%x : 格式化輸入輸出十六進制整數(shù).
%c : 格式化輸入輸出單個字符.
%s : 格式化輸入輸出一個字符串.
%f : 格式化輸入輸出小數(shù)形式的十進制浮點數(shù).
%e : 格式化輸入輸出指數(shù)形式的十進制浮點數(shù).
%p : 格式化輸入輸出十六進制表示形式的指針數(shù)據(jù).
格式轉(zhuǎn)換修飾符: 在格式轉(zhuǎn)換符的%右邊使用(%ld),對數(shù)據(jù)的輸出格式作進一步的修飾.
n : 整型數(shù)n,指定輸出整型數(shù)據(jù)的域?qū)?實際域?qū)挻笥趎按實際域?qū)捿敵?實際域?qū)捫∮趎則在數(shù)據(jù)的左
邊補空格,右對齊.
比如: 要輸出數(shù)據(jù)134,若指定域?qū)抧為2,則輸出格式為"134";若指定域?qū)挒?,則輸出為" 134".
-n: 使用方法跟第一條一樣.區(qū)別在于若實際域?qū)捫∮趎,則在數(shù)據(jù)的右邊補空格,左對齊.
0n: 使用方法跟第一條一樣.區(qū)別在于若實際域?qū)捫∮趎,則在數(shù)據(jù)的左邊補0,右對齊.
.n: 若輸出數(shù)據(jù)為浮點數(shù),則是指定小數(shù)點后的顯示位數(shù)(四舍五入);若輸出數(shù)據(jù)為字符串,則是指定
實際輸出的字符的個數(shù).
l : 不是數(shù)字1,是小寫字母l.若輸出數(shù)據(jù)是整型數(shù),則是指定輸出長整數(shù)數(shù)據(jù);若輸出數(shù)據(jù)是浮點型,
則是指定輸入輸出雙精度浮點型數(shù)據(jù)
+ : 在有符號整數(shù)前顯示正號'+'.
# : 在輸出數(shù)據(jù)前顯示前綴: %#o,顯示八進制前綴0.%#x,顯示十六進制前綴0x
如果大家對C/C++感興趣的話,本小編這里準備了一大堆的學(xué)習(xí)資料可以免費分享給有需要的朋友們,學(xué)習(xí)群:前面八七三,中間五二一,后面八零三。連起來就可進群然后免費領(lǐng)取一份學(xué)習(xí)資料哦!!!!
常用標準輸入函數(shù):
按字節(jié)輸入: 從終端中獲取一個字節(jié)(字符).
#include //頭文件
int getchar(void); //函數(shù)原型
返回值: 成功返回讀取到的字符,出錯返回-1.
注: getchar函數(shù)一般用于阻塞程序執(zhí)行(防止程序閃退)或者消除在格式化輸入整型數(shù)據(jù)后,回車符對數(shù)據(jù)的影響.
格式化輸入: 將數(shù)據(jù)按照一定的格式輸入.
#include //頭文件
int scanf(const char *format, ...); //函數(shù)原型
參數(shù): format : 是一個字符串,但跟printf函數(shù)不同的是,format中只包含格式轉(zhuǎn)換符,不包括自定信息.
... : 形參表,傳遞的實參是用于接收輸入數(shù)據(jù)的自定義緩存區(qū)的地址.其它使用特性(格式)跟printf函數(shù)一致.
注: 1.地址涉及到以后要學(xué)習(xí)的指針部分知識,暫時不做介紹.
2.scanf函數(shù)跟printf函數(shù)一樣,一次可以操作多個數(shù)據(jù).但scanf函數(shù)操作多個數(shù)據(jù)使用起來稍微復(fù)雜,容易出錯.而且操作多個數(shù)據(jù)的情況也特別少,故我們重點學(xué)習(xí)如何通過scanf函數(shù)進行單個數(shù)據(jù)的輸入.
返回值: 成功返回與指定格式相匹配的數(shù)據(jù)的個數(shù),當(dāng)匹配不成功返回值為0;出錯返回-1.
緩沖類型: 行緩沖,遇到空格或回車則認為當(dāng)前數(shù)據(jù)輸入結(jié)束.
注: scanf函數(shù)對格式轉(zhuǎn)換符和格式轉(zhuǎn)換修飾符的使用與printf函數(shù)一樣,但scanf函數(shù)一般只使用格式轉(zhuǎn)換符,不使用格式轉(zhuǎn)換修飾符.
標準出錯函數(shù):
當(dāng)程序中某個函數(shù)執(zhí)行出錯,我們可以通過標準出錯函數(shù)向終端輸出錯誤信息:
#include //頭文件
#include //頭文件
void perror(const char *s); //函數(shù)原型
參數(shù): s : 實參是一個自定義字符串,一般填寫出錯的函數(shù)的函數(shù)名.
注 : 標準出錯函數(shù)是無緩沖類型,出錯信息直接輸出到終端顯示.
頭文件 : #inlcude
----------------------------------------------------------------------------------------------
char *gets(char *s); //從標準輸入流中讀取一行字符,遇到換行符\n才結(jié)束讀取.
遇到空格繼續(xù)讀取,容易造成自定義緩存區(qū)buffer的溢出,不建議使用.
參數(shù) : s : 自定義的用于存儲接收到的數(shù)據(jù)的緩存區(qū)buffer.
返回值 : 成功返回自定義緩存區(qū)buffer的地址;出錯或者標準輸入流中沒有數(shù)據(jù)返回NULL.
編程方法 : char *p = NULL;
char a[n]; //自定義緩存區(qū)buffer.
p = gets(a);
----------------------------------------------------------------------------------------------
char *fgets(char *s, int size, FILE *stream); //從標準輸入流"stream"中讀取一行字符,
達到讀取的限制大小或者遇到換行符結(jié)束讀取.
參數(shù) : s : 自定義的用于存儲接收到的數(shù)據(jù)的緩存區(qū)buffer.
size : 指定一次獲取的字符的個數(shù)
stream : 標準輸入流stdin.
返回值 : 成功返回自定義緩存區(qū)buffer的地址;出錯或者標準輸入流中沒有數(shù)據(jù)返回NULL.
注 : fgets函數(shù)比gets函數(shù)要安全.因為不會造成自定義緩存區(qū)buffer的溢出.
-----------------------------------------------------------------------------------------------
int puts(const char *s); //向標準輸出流中輸出一個字符串.
參數(shù) : s : 自定義的用于存儲待輸出的數(shù)據(jù)的緩存區(qū)buffer.
返回值 : 成功返回非負整數(shù);出錯返回EOF.
-----------------------------------------------------------------------------------------------
int fputs(const char *s, FILE *stream); //向標準輸出流stream(stdout)中輸出一個字符串.
參數(shù) : s : 自定義的用于存儲待輸出的數(shù)據(jù)的緩存區(qū)buffer.
返回值 : 成功返回非負整數(shù);出錯返回EOF.
-----------------------------------------------------------------------------------------------
int fprintf(FILE *stream, const char *format, ...); //實現(xiàn)與printf函數(shù)一樣的功能.
新增參數(shù) : stream : 標準輸出流stdout.
其它屬性跟printf函數(shù)一樣.
-----------------------------------------------------------------------------------------------
int fscanf(FILE *stream, const char *format, ...); //實現(xiàn)與scanf函數(shù)一樣的功能.
新增參數(shù) : stream : 標準輸入流stdin.
其它屬性跟scanf函數(shù)一樣.
-----------------------------------------------------------------------------------------------
使用標準I/O進行文件操作:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
參數(shù) : ptr : 用于保存從文件流中讀取的數(shù)據(jù)的自定義緩存區(qū)buffer.
size : 每個數(shù)據(jù)的大小.
nmemb : 讀取數(shù)據(jù)的個數(shù).
stream : 打開的文件流指針,數(shù)據(jù)從流中讀取.
返回值 : 成功返回讀取到的數(shù)據(jù)的個數(shù);出錯或者到達文件末尾返回0.
-----------------------------------------------------------------------------------------------
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
參數(shù) : ptr : 保存了要寫入文件流中的數(shù)據(jù)的自定義緩存區(qū)buffer.
size : 每個數(shù)據(jù)的大小.
nmemb : 寫入數(shù)據(jù)的個數(shù).
stream : 打開的文件流指針,數(shù)據(jù)寫入流中.
返回值 : 成功返回寫入的數(shù)據(jù)的個數(shù);出錯返回0.
總結(jié)
- 上一篇: PowerShell遍历文件夹下的子文件
- 下一篇: 丘处机《摄生消息论》(转)