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