目錄主要使用函數原型:實現過程中幾個易錯細節小結函數:每次讀寫一個字元函數:每次讀寫一行字元函數:每次讀寫一個塊字元 主要使用函數原型: 1.每次讀寫一個字元: int fgetc(FILE *stream); int fputc(int c, FILE *stream); 2.每次讀寫一行字元: ...
目錄
主要使用函數原型:
1.每次讀寫一個字元:
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
2.每次讀寫一行字元:
char *fgets(char *s , int size , FILE *stream);
char *fputs(const char *s ,FILE *stream);
3.每次讀寫一個塊字元:
size_t fread(void *ptr,size_t size,xize_t nmemb,FILE\*stream);
size_t fwrite(const void *ptr,size_t size,xize_t nmemb,FILE\*stream);
4.另外,每個函數也使用了一些輔助函數,主要列舉如下:
int feof(FILE *stream);
int ferror(FILE *stream);
long ftell(FILE *stream); //獲取當前的位置偏移量
實現過程中幾個易錯細節小結
-
幾個讀取函數的文件指針偏移
int fgetc(FILE *stream),char *fgets(char *s , int size , FILE *stream),與size_t fread(void *ptr,size_t size,xize_t nmemb,FILE*stream)的每次讀取,都是從文件的開始位置,向後讀取;在下一次迴圈到來之前,文件內的當前位置,已經是已讀取的字元之後。
筆者一開始圖方便,將讀取函數fgetc()的返回值直接作為寫入函數fputc()的參數,寫了下麵這行代碼,就導致了一個比較低級的錯誤:
while (!feof(fp_src)) // 每次讀寫一個字元的第19~33行簡易實現 { fputc(fgetc(fp_src), fp_dst); }
導致複製出來的文件末尾都有一個亂碼:
fclose(fp_dst); // 關閉並釋放文件指針堆空間 fclose(fp_src); return 0; }�
因此,此處的迴圈結束條件必須加上fgetc(fp_src)==EOF。
-
行與塊的區別
行與塊的區別,影響到設計的函數結構。
行:即數據至多包含一個換行符“\n”,遇到換行符就進行下一次迴圈;因此,可以以fgets()是否為NULL為迴圈結束條件,即文件stream到達文件末尾即可。
塊:即一個固定的緩存空間,當數據塊中出現換行符或字元串結束標記符等都不會受影響。因此將一個文件分為若幹塊,將不滿一塊時的判斷條件作為迴圈結束條件,即:
*size_t fread(void ptr,size_t size,xize_t nmemb,FILE*stream)< NMEMB並將剩下的字元繼續輸入。
-
函數返回值
如同第二點,返回值非常重要,可以以此為切入口設計程式架構。
單字元 單行 塊 讀取函數 int fgetc(FILE *stream); char *fgets(char *s , int size , FILE *stream); size_t fread(void *ptr,size_t size,xize_t nmemb,FILE*stream); 成功/失敗 讀取到的字元/EOF(-1) 指針s/NULL nmemb/<nmemb 寫入函數 int fputc(int c, FILE *stream); char *fputs(const char *s ,FILE *stream); size_t fwrite(const void *ptr,size_t size,xize_t nmemb,FILE*stream); 成功/失敗 讀取到的字元/EOF(-1) true/NULL nmemb/<nmemb
函數:每次讀寫一個字元
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
if (3 != argc) // 判斷用戶輸入的參數是否有效。
{
perror("argument is invalid.\n");
exit(1);
}
// 分別打開待拷貝和目標拷貝文件
FILE *fp_src = fopen(argv[1], "rb"); // 以二進位形式讀取第一個文件
FILE *fp_dst = fopen(argv[2], "wb"); // 以二進位形式追加寫入第二個文件
if (!fp_dst || !fp_src) // 如果打開錯誤,則直接列印錯誤信息並退出.
{
perror("fopen()");
exit(1);
}
int data = fgetc(fp_src); // 設置變數,存放fgetc得到的字元
while (1)
{
if (feof(fp_src) && data == EOF) // 如果當前游標已經到文件尾,則退出迴圈
{
printf("Copy completed.\n");
break;
}
else if (ferror(fp_src)) // 如果出現未知錯誤,則退出
{
perror("fgetc()");
exit(1);
}
fputc(data, fp_dst);
data = fgetc(fp_src); // 繼續存放fgetc得到的字元
}
fclose(fp_dst); // 關閉並釋放打開文件申請的堆空間
fclose(fp_src);
return 0;
}
函數:每次讀寫一行字元
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define BUFSIZE 100 // 設置每一個緩衝區,即每一行能複製的最大位元組數
int main(int argc, const char *argv[])
{
if (3 != argc) // 判斷用戶輸入的參數是否有效。
{
perror("argument is invalid.\n");
exit(1);
}
// 分別打開待拷貝和目標拷貝文件
FILE *fp_src = fopen(argv[1], "rb"); // 以二進位形式讀取第一個文件
FILE *fp_dst = fopen(argv[2], "wb"); // 以二進位形式追加寫入第二個文件
if (!fp_dst || !fp_src) // 如果打開錯誤,則直接列印錯誤信息並退出.
{
perror("fopen()");
exit(1);
}
char buf[BUFSIZE] = {0}; // 定義緩衝區變數,利用數組實現
while (1)
{
bzero(buf, BUFSIZE); // 每次操作前,進行清空緩衝區操作,以免內容泄露
if (!fgets(buf, BUFSIZE, fp_src)) // 獲取源文件數據,並判斷是否為NULL,如果為NULL有兩種情況判斷
{
if (feof(fp_src)) // 如果當前游標已經到文件尾,則表示覆制完成並退出迴圈
{
printf("Copy completed.\n");
break;
}
else if (ferror(fp_src)) // 如果出現未知錯誤,則退出
{
perror("fgetc()");
exit(1);
}
}
fputs(buf, fp_dst); // 複製完成後,進行粘貼操作
}
fclose(fp_dst); // 關閉並釋放打開文件申請的堆空間
fclose(fp_src);
return 0;
}
函數:每次讀寫一個塊字元
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define SIZE 100 // 設置每一塊能容納的最大位元組數
#define NMEMB 5 // 設置塊數
int main(int argc, const char *argv[])
{
if (3 != argc) // 判斷用戶輸入的參數是否有效。
{
perror("argument is invalid.\n");
exit(1);
}
// 分別打開待拷貝和目標拷貝文件
FILE *fp_src = fopen(argv[1], "rb"); // 以二進位形式讀取第一個文件
FILE *fp_dst = fopen(argv[2], "wb"); // 以二進位形式追加寫入第二個文件
if (!fp_dst || !fp_src) // 如果打開錯誤,則直接列印錯誤信息並退出.
{
perror("fopen()");
exit(1);
}
char buf[SIZE * NMEMB] = {0}; // 定義緩衝區變數,利用數組實現
long pre, cur;
while (1)
{
bzero(buf, SIZE * NMEMB); // 每次操作前,進行清空緩衝區操作,以免內容泄露
pre = ftell(fp_src); // 記錄當前的偏移量;
if (fread(buf, SIZE, NMEMB, fp_src) < NMEMB) // 獲取源文件數據,並判斷異常情況,併進行異常情況判斷
{
if (feof(fp_src)) // 如果當前游標已經到文件尾,則需要把剩餘的內容進行複製,這裡利用pre,cur實現
{
fread(buf, cur - pre, 1, fp_src);
fwrite(buf, cur - pre, 1, fp_dst);
printf("Copy completed.\n");
break;
}
else if (ferror(fp_src)) // 如果出現未知錯誤,則退出
{
perror("fgetc()");
exit(1);
}
}
fwrite(buf, SIZE, NMEMB, fp_dst); // 複製完成後,進行粘貼操作
}
fclose(fp_dst); // 關閉並釋放打開文件申請的堆空間
fclose(fp_src);
return 0;
}