C語言自學攻略-文件操作(檔案處理)全解析

更新 發佈閱讀 15 分鐘

檔案的輸入與輸出

在C語言中,我們使用FILE指標來開啟檔案:

FILE* fptr;

現在假設我們在主程式同一目錄下有一個message.txt文件,內容如下:

vocus|新世代的創作平台

接著,我們可以使用內建fopen函式來開啟文件。

fptr = fopen("message.txt", "r");
  • 開啟檔案意味著將我們的程式與該檔案連接起來。現在,我們可以對message.txt文件執行不同的文件操作
  • 其中,fopen函式的第二個參數"r" 表示已閱讀模式開啟了文件,這意味著我們只能執行讀取的操作。

而當我們開啟文件時,我們需要確保文件確實存在於指定位置,否則該fopen函式將會回傳NULL 。另一個該注意的點,是每當開啟文件後,在最後程式結束前,要記得使用fclose()來關閉文件,這是一個好習慣,以下示範:

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp = fopen("message.txt","r")
if ( fp == NULL )
printf("檔案開啟失敗 \n");
else
printf("檔案開啟OK \n");
fclose(fp);
return 0;
}

打開文件後,我們可以使用fgets()函式讀取其內容,以下示範:

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp = fopen("message.txt","r");
char content[100]; //用來儲存文件內容
if ( fp == NULL )
printf("檔案開啟失敗 \n");
else{
fgets(content, 100, fp); // fp 是用於讀取文件的文件指針
printf("%s", content);
}
fclose(fp);
return 0;
}
vocus|新世代的創作平台
  • 上圖是程式碼運行後得到的輸出結果,但是,我們只輸出了一行,並沒有輸出所有的文件內容,這是因為fgets()函數一次讀取一行。

因此,要讀取文件的所有內容,我們可以使用迴圈循環,以下示範:

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp = fopen("message.txt","r");
char content[100]; //用來儲存文件內容
if ( fp == NULL )
printf("檔案開啟失敗 \n");
else{
while(fgets(content, 100, fp)){
printf("%s", content);
}
}
fclose(fp);
return 0;
}
vocus|新世代的創作平台
  • while迴圈以fgets() 函式做為循環的條件,該fgets()函數逐行讀取檔案內容並將其儲存在content字串中。如果讀取成功,則條件變為真並列印。
  • 但是,如果函式遇到檔案結束符(End-of-File),則傳回 NULL,條件變為 false,從而終止迴圈。所以有別於前一次輸出,這次輸出了完整的內容。

好,如果現在我們想要將內容寫入文件中,該怎麼做?

要將內容寫入文件,我們必須使用寫入模式來開啟文件,我們以"w"作為函式fopen()的第二個參數,並且使用fputs()函式將內容寫入文件。以下示範:

#include <stdio.h>

int main() {

FILE* fp;
fp = fopen("message.txt", "w");

fputs("I like you\n", fp); //使用換行符號
fputs("I love you", fp);

fclose(fp);

return 0;
}
  • 如果我們嘗試開啟一個不存在的文件,則會建立一個新文件。
  • 如果檔案已存在,則其內容將被刪除,並將新內容新增至該檔案。
vocus|新世代的創作平台
  • 可以看到,內容被重新寫入了。

那今天我們不想刪除原本的內容,而是想將新寫入的內容附加到原本的文件,我們改以"a"作為函式fopen()的第二個參數。以下示範:

#include <stdio.h>

int main() {

FILE* fp;
fp = fopen("message.txt", "a");

fputs(" so much", fp);

fclose(fp);

return 0;
}
  • 如果我們嘗試將內容附加到不存在的文件中,則會建立一個新文件。
  • 如果檔案已存在,則會將附加資料附加到檔案結尾,而不刪除先前的資料。
vocus|新世代的創作平台

剛才我們都是存取和程式碼同一目錄下的文件,假設你想存取外部文件的話,必須提供目錄及文件名稱,現在假設我們要存取一外部文件,而這文件位於 test_content 的目錄下,我們透過提供程式文件的路徑來存取文件內容,以下示範:

#include <stdio.h>

int main() {

FILE* fp;

fp = fopen("D:/test_content/messages.txt", "w");

fputs("I love C!", fp);

fclose(fp);

return 0;
}

現在你已經學會基本的讀寫文件了,不過,除了上面的操作之外,其實還有幾種讀取與寫入的幾種方式,下面一一介紹。

getc : 讀取一個字元

首先,在介紹讀取或寫入單個字元前,我先介紹feof()函式,這裡我順便提一下argcargv*[] 如何使用,我們以一個計算字元數的程式示範如何使用,不同於以往,這次我們要在終端機編譯並執行程式:

#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp; // 定義檔案指標,用於指向要開啟的檔案
int count = 0; // 用來計算檔案的字元數
char ch; // 用於存放讀取的字元

if (argc != 2) // 檢查指令行參數是否正確,應該包含程式名和檔案名兩個參數
{
printf("指令錯誤 "); // 如果指令行參數數量不正確,輸出錯誤提示
return 1; // 結束程式,返回錯誤代碼 1
}

fp = fopen(argv[1], "r"); // 嘗試以讀取模式("r")開啟指令行指定的檔案
if (fp == NULL) // 如果檔案開啟失敗
{
printf("無法開啟檔案"); // 使用 `perror` 輸出具體的錯誤資訊
return 1; // 結束程式
}

// 讀取檔案,直到檔案末尾
while (!feof(fp)) // 檢查檔案是否到達末尾
{
ch = getc(fp); // 使用 `getc` 讀取檔案中的一個字元
count++; // 每次讀取有效字元後,計數器加 1
}

printf("%s檔案的字元數是 %d\n", argv[1], count); // 輸出檔案名稱和字元數

fclose(fp); // 關閉檔案,釋放資源

return 0;
}
  • 我們需要在終端機輸入以下指令來編譯程式並執行:
gcc your_program.c -o your_program

// 本程式的情況
gcc file_handling.c -o file_handling // 生成可執行檔案 file_handling.exe
//接著,我們輸入以下指令來運行
./file_handling.exe message.txt
  • argc 是指令行參數的個數。
  • argv 是指令行參數的各個字串陣列,其中:
    • argv[0] 是運行程式的指令(第一個字串)。
    • argv[1] 是使用者提供的檔案名(第二個字串)。

假設message.txt 的內容如下:

Hello World!
I love C!
  • 則程式輸出結果為 12 + 1 (換行符 ) + 10 = 23

Ok, 接著介紹寫入單個字元,我們撰寫一個程式來將message.txt的內容寫入到另一個文件file.txt中。

putc : 讀取一個字元

#include <stdio.h>

int main() {
FILE *source, *destination;
char ch;

// 打開 source 文件 message.txt,讀取模式
source = fopen("message.txt", "r");
if (source == NULL) {
printf("無法打開 message.txt");
return 1;
}

// 打開 destination 文件 file.txt,寫入模式
destination = fopen("file.txt", "w");
if (destination == NULL) {
printf("無法打開 file.txt");
fclose(source);
return 1;
}

// 從 source 文件中逐字元讀取,並寫入到 destination 文件中
while ((ch = getc(source)) != EOF) { //我們也可以這樣確認是否讀到檔案尾端
putc(ch, destination);
}

printf("Successfully copied from message.txt to file.txt");

// 關閉文件
fclose(source);
fclose(destination);

return 0;
}
  • 程式執行完畢後,你應該能在相同目錄下看到file.txt ,並且內容式複製過後的內容。
  • 另外,特別提一下,若你在 getc 或 putc 前加上 f 對結果也不會有影響,即使用fgetcfputc 效果和原程式相同。

好,再來介紹最後兩個格式化輸出和輸入的函式,fscanf()fprintf() ,在使用上和以前非檔案的輸入輸出非常相像。

fprintf()

以下示範:

#include <stdio.h>
int main()
{
FILE *fp;
int var,i;
int sum = 0;
float average;

fp = fopen("message.txt","w");
if (fp == NULL) { // 檢查檔案是否成功開啟
printf("無法開啟檔案");
return 1;
}

for ( i = 0; i < 5; i++ )
{
printf("請輸入資料 %d ==> ",i+1);
scanf("%d",&var);
sum += var;
fprintf(fp,"%d\n",var); /* 將資料寫入檔案 */
}
// 計算平均值
average = (float) sum / 5.0; // 將平均值寫入檔案,格式化為小數點後 2 位
fprintf(fp,"平均值是 %5.2f",average);
fclose(fp); // 關閉檔案,釋放系統資源
return 0;
}

程式執行後的文件內容:

88
96
46
87
100
平均值是 83.40

fscanf()

以下示範:

假設文件內容如下:

共有25個數字
65 66 67 68 69
70 71 72 73 74
75 76 77 78 79
80 81 82 83 84
85 86 87 88 89

程式碼:

#include <stdlib.h>
#include <stdio.h>
int main()
{
FILE *fp;
char line[100];
int i,j,var;

fp = fopen("message.txt","r"); /* 開啟檔案 */
fscanf(fp, "%[^\n]%*c", line); // 讀取直到換行符的內容
printf("%s\n", line); // 輸出第一行的內容
for ( i = 0; i < 5; i++ )
{
for ( j = 0; j < 5; j++ )
{
fscanf(fp,"%d",&var); // 讀取有效數字。
printf("%c",var);
}
printf("\n");
}
fclose(fp); // 關閉檔案,釋放系統資源
return 0;
}
  • %*c:讀取一個字元(通常是換行符 \n),但不存儲(* 表示忽略該輸入)。這表示讀取完一整行後直接跳至下一行。
  • 就算使用fscanf(fp, "%[^\n]", line);,輸出結果也一樣,因為fscanf(fp,"%d",&var); 自動跳過換行符,只關注數字。

程式執行後的文件內容:

共有25個數字
ABCDE
FGHIJ
KLMNO
PQRST
UVWXY

有關文件的操作目前先介紹到這邊。

留言
avatar-img
電資鼠 - 您的學習好夥伴
23會員
242內容數
在當今數位時代,電資領域人才需求爆發式成長,不論是前端網頁設計、嵌入式開發、人工智慧、物聯網還是軟硬體整合,這些技術都在改變世界。而掌握 C/C++、Python、數位邏輯、電路學與嵌入式開發等大學電資領域的課程,正是進入這個高薪、高需求產業的關鍵!
2025/03/07
本章節將探討左下三角稀疏矩陣。
Thumbnail
2025/03/07
本章節將探討左下三角稀疏矩陣。
Thumbnail
2025/03/07
相信讀者現在對於鏈結串列有了更多的認識,所以我再進一步,示範更多關於鏈結串列的操作,這部分示範會將程式模組化。將鏈結串列的操作寫進一個標頭檔,並在主程式中引入。
Thumbnail
2025/03/07
相信讀者現在對於鏈結串列有了更多的認識,所以我再進一步,示範更多關於鏈結串列的操作,這部分示範會將程式模組化。將鏈結串列的操作寫進一個標頭檔,並在主程式中引入。
Thumbnail
2025/03/07
本章節示範透過「陣列索引」和「指標運算」兩種方式來存取同一個二維陣列 a,並印出相同的數值以及對應的位址,以說明它們其實指向的是同一塊連續的記憶體空間。本文將依序解釋各段程式碼,並示範可能的執行結果與背後原理。
Thumbnail
2025/03/07
本章節示範透過「陣列索引」和「指標運算」兩種方式來存取同一個二維陣列 a,並印出相同的數值以及對應的位址,以說明它們其實指向的是同一塊連續的記憶體空間。本文將依序解釋各段程式碼,並示範可能的執行結果與背後原理。
Thumbnail
看更多
你可能也想看
Thumbnail
C#程式由一或多個檔案組成,包含命名空間、類別、結構、介面、列舉和委派等型別。Main方法是C#應用程式的進入點。在C#中,註解用於在程式碼中添加說明,有單行和多行兩種類型。變數的定義需要指定變數的類型和名稱,可以一次為多個變數賦值。
Thumbnail
C#程式由一或多個檔案組成,包含命名空間、類別、結構、介面、列舉和委派等型別。Main方法是C#應用程式的進入點。在C#中,註解用於在程式碼中添加說明,有單行和多行兩種類型。變數的定義需要指定變數的類型和名稱,可以一次為多個變數賦值。
Thumbnail
<iostream> ​在之前的文章有提到過,<iostream> 是專門處理程式的輸入 (input) 以及輸出 (output) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
Thumbnail
<iostream> ​在之前的文章有提到過,<iostream> 是專門處理程式的輸入 (input) 以及輸出 (output) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
Thumbnail
工具功能 (1) 彈性任意查詢檔案,如對來源目錄設定,檔案修改日期 設定,檔名特定字串或副檔名設定後,自動查出明細,並可展開至各階子目錄處理     (2) 依查詢後結果,可產出 LIST ,提供查詢結果之確認,再依此對檔案作複 (3) 可對檔案作移動,複製至別處,刪除處理,使電腦可騰出硬碟空間
Thumbnail
工具功能 (1) 彈性任意查詢檔案,如對來源目錄設定,檔案修改日期 設定,檔名特定字串或副檔名設定後,自動查出明細,並可展開至各階子目錄處理     (2) 依查詢後結果,可產出 LIST ,提供查詢結果之確認,再依此對檔案作複 (3) 可對檔案作移動,複製至別處,刪除處理,使電腦可騰出硬碟空間
Thumbnail
Lua 開檔寫檔的運用 io.output()...
Thumbnail
Lua 開檔寫檔的運用 io.output()...
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
User Input & Tables 的使用
Thumbnail
User Input & Tables 的使用
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
INI 檔案是一種配置檔案格式,常用於保存設定資料和組態資訊。 它使用簡單的鍵值對結構來組織資料,通常用於程式、應用程式或操作系統中的配置和初始化設定。 INI 檔案每個鍵值對包含一個名稱(鍵)和對應的值。 基本的檔案格式如下: [Section1] Key1 = Value1 Key2 =
Thumbnail
INI 檔案是一種配置檔案格式,常用於保存設定資料和組態資訊。 它使用簡單的鍵值對結構來組織資料,通常用於程式、應用程式或操作系統中的配置和初始化設定。 INI 檔案每個鍵值對包含一個名稱(鍵)和對應的值。 基本的檔案格式如下: [Section1] Key1 = Value1 Key2 =
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News