標準IO?
?C語言標準IO概述
標準IO(Standard Input/Output)是C語言中用于處理文件和數據流的一組函數庫,定義在<stdio.h>
頭文件中。與低級IO(如read
/write
)相比,標準IO提供了緩沖機制,提高了數據讀寫的效率。標準IO的核心是FILE
結構體指針,通過它操作文件流。
fopen/fclose
功能
fopen
:打開文件并返回文件指針。fclose
:關閉文件并釋放資源。
函數原型
FILE *fopen(const char *filename, const char *mode);
int fclose(FILE *stream);
參數說明
filename
:文件路徑。mode
:打開模式(如"r"
只讀,"w"
寫入,"a"
追加等)。stream
:已打開的文件指針。
示例
FILE *fp = fopen("test.txt", "w");
if (fp == NULL) {perror("Error opening file");return 1;
}
fclose(fp);
fgetc/fputc
功能
fgetc
:從文件流中讀取一個字符。fputc
:向文件流寫入一個字符。
函數原型
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
示例
FILE *fp = fopen("test.txt", "r");
int ch = fgetc(fp); // 讀取一個字符
fputc('A', fp); // 寫入字符'A'
fgets/fputs
功能
fgets
:從文件流讀取一行字符串。fputs
:向文件流寫入字符串(不自動添加換行符)。
函數原型
char *fgets(char *str, int n, FILE *stream);
int fputs(const char *str, FILE *stream);
參數說明
str
:存儲讀取數據的緩沖區。n
:最多讀取的字符數(包括\0
)。
示例
char buffer[100];
fgets(buffer, 100, stdin); // 從標準輸入讀取
fputs("Hello", stdout); // 輸出到標準輸出
fscanf/fprintf
功能
fscanf
:格式化輸入(類似scanf
,但針對文件流)。fprintf
:格式化輸出(類似printf
,但針對文件流)。
函數原型
int fscanf(FILE *stream, const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
示例
int num;
fscanf(fp, "%d", &num); // 從文件讀取整數
fprintf(fp, "Number: %d", 42); // 寫入格式化字符串
fread/fwrite
功能
fread
:從文件流讀取二進制數據塊。fwrite
:向文件流寫入二進制數據塊。
函數原型
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
參數說明
ptr
:數據緩沖區指針。size
:每個數據項的字節數。nmemb
:要讀寫的數據項數量。
示例
int arr[5] = {1, 2, 3, 4, 5};
fwrite(arr, sizeof(int), 5, fp); // 寫入數組
fread(arr, sizeof(int), 5, fp); // 讀取數組
fseek/rewind/ftell
功能
fseek
:設置文件流的位置指針。rewind
:重置文件指針到開頭。ftell
:返回當前文件指針位置(字節偏移量)。
函數原型
int fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);
long ftell(FILE *stream);
參數說明
offset
:偏移量。whence
:基準位置(SEEK_SET
開頭,SEEK_CUR
當前位置,SEEK_END
末尾)。
示例
fseek(fp, 10, SEEK_SET); // 移動到第10字節
rewind(fp); // 回到文件開頭
long pos = ftell(fp); // 獲取當前位置
利用fread和fwrite實現圖片的拷貝
#include "../head.h"int main(void)
{FILE *fsrc = NULL;FILE *fdst = NULL;ssize_t nret = 0;char srcfile[256] = {0};char dstfile[256] = {0};char tmpbuff[4096] = {0};printf("請輸入源圖片:\n");fgets(srcfile, sizeof(srcfile), stdin);srcfile[strlen(srcfile)-1] = '\0';printf("請輸入目的圖片:\n");fgets(dstfile, sizeof(dstfile), stdin);dstfile[strlen(dstfile)-1] = '\0';fsrc = fopen(srcfile, "r");if (NULL == fsrc){perror("fail to fopen");return -1;}fdst = fopen(dstfile, "w");if (NULL == fdst){perror("fail to fopen");return -1;}while (1){nret = fread(tmpbuff, 1, sizeof(tmpbuff), fsrc);if (0 == nret){break;}fwrite(tmpbuff, 1, nret, fdst);}fclose(fsrc);fclose(fdst);return 0;
}
統計一個文件中出現最多的字符是哪個,出現了多少次
鏈表法
#include "../head.h"
#include "cirlist.h"int find_max_char(char *filename, int *pmaxchar, int *pmaxcnt)
{FILE *fp = NULL;linknode *pcirlist = NULL;linknode *ptmpnode = NULL;char ch = 0;pcirlist = create_empty_linklist();fp = fopen(filename, "r");if (NULL == fp){perror("fail to fopen");return -1;}while (1){ch = fgetc(fp);if (EOF == ch){break;}/* 如果第一次出現則新增該節點 */ptmpnode = find_linklist(pcirlist, ch);if (NULL == ptmpnode){insert_tail_linklist(pcirlist, ch);}/* 從鏈表中找到節點,計數器自加 */ptmpnode = find_linklist(pcirlist, ch);ptmpnode->cnt++;}fclose(fp);ptmpnode = find_max_node(pcirlist);if (ptmpnode != NULL){*pmaxchar = ptmpnode->data;*pmaxcnt = ptmpnode->cnt;}destroy_linklist(&pcirlist);return 0;
} int main(void)
{char filename[256] = {0};int maxcnt = 0;int maxchar = 0;int ret = 0;printf("請輸入要檢測的文件名:\n");m_fgets(filename);ret = find_max_char(filename, &maxchar, &maxcnt);if (ret != 0){printf("fild max char failed\n");return -1;}printf("出現最多的字符:%c, 次數:%d\n", maxchar, maxcnt);return 0;
}
數組法
#include "../head.h"int find_max_char(char *filename, int *pmaxchar, int *pmaxcnt)
{FILE *fp = NULL;int cnt[256] = {0};char ch = 0;int max = 0;int i = 0;fp = fopen(filename, "r");if (NULL == fp){perror("fail to fopen");return -1;}while (1){ch = fgetc(fp);if (EOF == ch){break;}cnt[ch]++;}fclose(fp);max = 0;for (i = 1; i < 256; i++){if (cnt[i] > cnt[max]){max = i;}}*pmaxchar = max;*pmaxcnt = cnt[max];return 0;
} int main(void)
{char filename[256] = {0};int maxcnt = 0;int maxchar = 0;int ret = 0;printf("請輸入要檢測的文件名:\n");m_fgets(filename);ret = find_max_char(filename, &maxchar, &maxcnt);if (ret != 0){printf("fild max char failed\n");return -1;}printf("出現最多的字符:%c, 次數:%d\n", maxchar, maxcnt);return 0;
}
文件IO
1.概念
- 標準IO是有緩存的IO,文件IO沒有緩存,適合于通信、硬件設備操作
- 標準IO是庫函數,文件IO是系統調用
2.系統調用與庫函數
- 系統調用:是Linux內核中的代碼,只能在Linux系統中使用
- 庫函數:是對系統調用的封裝,可以在不同的操作系統中安裝并使用,庫函數最終還是要調用系統 調用完成對應功能
3.文件IO函數接口
1. 函數接口:
2. 文件打開:
注意:
- 有三個特殊的文件描述符:標準輸入(0)、標準輸出(1)、標準錯誤(2)
- 文件描述符特點: 非負整數
- 取尚未被占用的最小的非負整數 文件描述符是有上限的,到達上限后再打開會報錯誤
3. 關閉文件描述符
4. 請寫出標準IO對應的文件IO的打開方式
5. 文件IO讀寫
1. write
2. read
6. 文件描述符偏移量的定位
1. lseek
7. 文件IO與標準IO互相轉換的函數
1. fileno 功能:根據文件流指針獲得文件描述符
2. fdopen 功能:根據已經打開的文件描述符獲得文件流指針
3. feof 功能:判斷文件流指針是否到達末尾
4. ferror 功能:判斷文件流指針是否出錯
目錄IO
1.操作方式:
- 打開目錄文件
- 讀取目錄文件中的目錄項
- 關閉目錄文件
2.函數接口:
1. opendir
2. closedir
3. readdir
4. getcwd
5. chdir
6. mkdir
注意:
- r:讀權限,決定用戶是否能夠查看目錄下所有文件名
- w:寫權限,決定用戶是否能夠在目錄下新建文件
- x:執行權限,決定用戶是否能夠進入目錄
7. rmdir
3.文件名和路徑:
- file.txt:文件名
- ./file.txt:路徑