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