欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言文件操作零基礎(chǔ)新手入門保姆級(jí)教程

 更新時(shí)間:2021年10月09日 09:40:38   作者:罅隙-  
在實(shí)際應(yīng)用中,我們往往需要對(duì)文件進(jìn)行操作,下面這篇文章主要給大家分享了關(guān)于C語言文件操作的零基礎(chǔ)新手入門保姆級(jí)教程,文中通過示例代碼以及圖片介紹的非常詳細(xì),需要的朋友可以參考下

一、前言

我們?nèi)绾问刮覀冊(cè)O(shè)計(jì)的程序具有“記憶功能”呢?答案是將數(shù)據(jù)以文件的形式另外保存。保存的形式有很多,在本文中我們以最簡單的文本形式保存在記事本上,相信這篇文章一定讓你學(xué)會(huì)。

二、文件操作基礎(chǔ)知識(shí)

①什么是文件

我們一般談的文件有兩種:程序文件數(shù)據(jù)文件
<程序文件>
包括源程序文件(后綴為.c),目標(biāo)文件(windows環(huán)境后綴為.obj),可執(zhí)行程序(windows環(huán)境后綴為.exe)。
<數(shù)據(jù)文件>
文件的內(nèi)容不一定是程序,而是程序運(yùn)行時(shí)讀寫的數(shù)據(jù),比如程序運(yùn)行需要從中讀取數(shù)據(jù)的文件,或者輸出內(nèi)容的文件。

本章討論的是數(shù)據(jù)文件

②數(shù)據(jù)文件類型

文本文件與二進(jìn)制文件

數(shù)據(jù)在內(nèi)存中以二進(jìn)制的形式存儲(chǔ),如果不加轉(zhuǎn)換的輸出到外存,就是<二進(jìn)制文件>(后綴.bin)。

如果要求在外存上以ASCII碼的形式存儲(chǔ),則需要在存儲(chǔ)前轉(zhuǎn)換。以ASCII字符的形式存儲(chǔ)的文件就是<文本文件>(后綴.txt)。

③數(shù)據(jù)如何存儲(chǔ)

一個(gè)數(shù)據(jù)在內(nèi)存中是怎么存儲(chǔ)的呢?
字符一律以ASCII形式存儲(chǔ),數(shù)值型數(shù)據(jù)既可以用ASCII形式存儲(chǔ),也可以使用二進(jìn)制形式存儲(chǔ)。
如有整數(shù)10000,如果以ASCII碼的形式輸出到磁盤,則磁盤中占用5個(gè)字節(jié)(按照一個(gè)字符一個(gè)字符儲(chǔ)存,1  0  0  0  0每個(gè)字符一個(gè)字節(jié)),而二進(jìn)制形式輸出,則在磁盤上只占4個(gè)字節(jié)(int)

④如何讀取二進(jìn)制文件

文本文件是我們通過記事本可以直接理解讀取的,而二進(jìn)制文件如果以記事本的形式打開是我們不能識(shí)別的亂碼。但vs可以以某種方式讀取二進(jìn)制文件,方法如下:

(下圖表示以記事本讀取以二進(jìn)制形式保存的10000) 

 演示二進(jìn)制文件打開方式: 

 第一步:將文件添加到vs下

 第二步:右擊后打開方式選擇二進(jìn)制編譯器

 這就是最后的效果了。

⑤什么是文件名

文件名包含3部分:文件路徑+文件名主干+文件后綴
例如: c: \code\ test.txt  (在后文會(huì)提到對(duì)文件名的絕對(duì)引用和相對(duì)引用)

⑥文件緩沖區(qū)

含義:ANSIC 標(biāo)準(zhǔn)采用“緩沖文件系統(tǒng)”處理的數(shù)據(jù)文件。所謂緩沖文件系統(tǒng)是指系統(tǒng)自動(dòng)地在內(nèi)存中為程序中每一個(gè)正在使用的文件開辟一塊“文件緩沖區(qū)”。文件緩沖區(qū)是用以暫時(shí)存放讀寫期間的文件數(shù)據(jù)而在內(nèi)存區(qū)預(yù)留的一定空間。通過磁盤緩存來實(shí)現(xiàn),磁盤緩存本身并不是一種實(shí)際存在的存儲(chǔ)介質(zhì),它依托于固定磁盤,提供對(duì)主存儲(chǔ)器存儲(chǔ)空間的擴(kuò)充,即利用主存中的存儲(chǔ)空間, 來暫存從磁盤中讀出(或?qū)懭?的信息。。

特點(diǎn):從內(nèi)存向磁盤輸出數(shù)據(jù)會(huì)先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才一起送到磁盤上。如果從磁盤向計(jì)算機(jī)讀入數(shù)據(jù),則從磁盤文件中讀取數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再從緩沖區(qū)逐個(gè)地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(程序變量等)。緩沖區(qū)的大小根據(jù)C編譯系統(tǒng)決定的 。

[擴(kuò)展-三種類型的緩存區(qū)]       鏈接-文件緩沖區(qū)

⑦文件指針

<文件指針>

緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文件類型指針”,簡稱“文件指針”。每個(gè)被使用的文件都在內(nèi)存中開辟了一個(gè)相應(yīng)的文件信息區(qū),用來存放文件的相關(guān)信息(如文件的名字,文件狀態(tài)及
文件當(dāng)前的位置等)。這些信息是保存在一個(gè)結(jié)構(gòu)體變量中的。該結(jié)構(gòu)體類型是有系統(tǒng)聲明的,取名FILE。

每當(dāng)打開一個(gè)文件的時(shí)候,系統(tǒng)會(huì)根據(jù)文件的情況自動(dòng)創(chuàng)建一個(gè)FILE結(jié)構(gòu)的變量,并填充其中的信息,使用者不必關(guān)心細(xì)節(jié)。一般都是通過一個(gè)FILE的指針來維護(hù)這個(gè)FILE結(jié)構(gòu)的變量,這樣使用起來更加方便。
FILE*p//文件類型指針

可以使pf指向某個(gè)文件的文件信息區(qū)(是一個(gè)結(jié)構(gòu)體變量)。通過該文件信息區(qū)中的信息就能夠訪問該文件。也就是說,通過文件指針變量能夠找到與它關(guān)聯(lián)的文件。

三、文件操作函數(shù)

①fopen 與 fclose

1.fopen

<功能>打開文件

<參數(shù)>  filename-文件名         mode-打開方式        

<返回值>一個(gè)文件指針

(打開方式mode表)

 2.fclose

<功能>  關(guān)閉文件

<參數(shù)>  stream-文件指針 

3.使用示范

#include<stdio.h>
#include<sting.h>
#include<errno.h>
int main()
{
	FILE*pw = fopen("test.txt","w");//打開的文件為“test.txt”      打開方式為“w”
    if(pw==NULL)//若打開失敗則說明失敗原因并結(jié)束進(jìn)程
    {
        printf("%s",strerror(errno));//errno是全局錯(cuò)誤變量  strerror將errno解析為錯(cuò)誤原因
        return 0;
    }
	fclose(pw);//關(guān)閉文件
	pw = NULL;//將指針置為空,防止被誤用
	return 0;
}

文件名相對(duì)/絕對(duì)路徑

絕對(duì)路徑:如c:\code\test.txt     包含文件路徑  文件主干  文件后綴

相對(duì)路徑:上圖的表示就是相對(duì)路徑,表示txt文件與源文件在同一路徑下,若要表示上一路                    勁,則用“../”,一次類推上上路徑就是“../../”

FILE*pw = fopen("../test.txt","w");

②fputc與fgetc

1.fputc——輸出函數(shù)

<功能>將一個(gè)字符寫入流中

<參數(shù)>c-輸出的字符

<返回值>正?!祷剌敵龅淖址?/p>

               錯(cuò)誤——返回EOF

<適用>所有流

2.fgetc——輸入函數(shù)

<功能>從流中讀取一個(gè)字符

<返回值>int——返回輸入的字符

               EOF——發(fā)生錯(cuò)誤或到達(dá)文件結(jié)尾

<適用>所有流 

 3.使用示范

#include <stdio.h>
#include <string.h>
#include<errno.h>
//fputc   輸出一個(gè)字母
int main()
{
	FILE*pw = fopen("test.txt","w");
	if (pw == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	fputc('b',pw);//將字符‘b'寫入文件"test.txt"
	fclose(pw);
	pw = NULL;
	return 0;
}
 
//fgetc 讀取一個(gè)字符,讀取一個(gè)后文件指針往后偏移一位
int main()
{
	FILE*pr = fopen("test.txt","r");
	if (pr == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	char ch = 0;//用ch接收輸入的字符
	ch = fgetc(pr);//從文件"test.txt"中讀取,讀取一個(gè)字符后文件指針自動(dòng)往后移一位
	fclose(pr);
	pr = NULL;
	printf("%c",ch);
	return 0;
}

 4.對(duì)所有流的理解

什么是流:流是指信息從外部輸入設(shè)備(如鍵盤)向計(jì)算機(jī)內(nèi)部(如內(nèi)存)輸入和從內(nèi)存                        向外部輸出設(shè)備(顯示器)輸出的過程。                       

上述代碼演示的是對(duì)文件流的操作,我們?cè)谟?strong>標(biāo)準(zhǔn)輸入(stdin)輸出(stdout)流演示一下

③fputs與fgets

1.fputs——輸出函數(shù)

<功能>將字符串寫入流中

<返回值>int——非負(fù)值表示成功

               EOF——發(fā)生錯(cuò)誤

<適用>所有流

2.fgets——輸入函數(shù)

<功能>從流中獲取字符串

<返回值>正?!祷刈址?/p>

               NULL——表示錯(cuò)誤或者到達(dá)文件結(jié)尾

<參數(shù)>n-從流中讀取的最大字符數(shù)(\0會(huì)自動(dòng)占去一位)

3.使用示范

#include <stdio.h>
#include <string.h>
#include<errno.h>
//fputs
int main()
{
	FILE*pw = fopen("test.txt","w");
	if (pw == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	char ch[5] = "abcd";
	fputs(ch,pw);
	fclose(pw);
	pw = NULL;
	return 0;
}
 
//fgets
int main()
{
	FILE*pr = fopen("test.txt","r");
	if (pr == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	char ch[5] = {0};
	fgets(ch,3,pr);//有一位自動(dòng)被\0占用
	printf("%s",ch);
	return 0;
}

④fprintf與fscanf

1.fprintf——輸出函數(shù)

<功能>將特定格式的數(shù)據(jù)寫入流中

<返回值>返回打印的字節(jié)數(shù)。

<適用>所有流

<對(duì)比>printf默認(rèn)將數(shù)據(jù)打印在標(biāo)準(zhǔn)輸出流(stdout)上,而fprintf的輸出流可以選擇。printf             打印的字符數(shù)返回

 2.fscanf——輸入函數(shù)

<功能>從流中讀取特定格式的數(shù)據(jù)

<適用>所有流

<返回值>返回成功轉(zhuǎn)換和分配的字段數(shù)量

3.使用示范

//頭文件同上略
//fprintf
int main()
{
	FILE*pw = fopen("test.txt","w");
	if (pw == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	fprintf(pw,"%d %.2f %c",10,3.14,'a');
	fclose(pw);
	pw = NULL;
	return 0;
}
 
//fscanf
int main()
{
	int a; float b; char c;
	FILE*pr = fopen("test.txt","r");
	if (pr == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	fscanf(pr,"%d %f %c",&a,&b,&c);
	printf("%d %.2f %c", a,b,c);
	return 0;
}

⑤fwrite與fread

1.fwrite——輸出函數(shù)

<功能>將數(shù)據(jù)以二進(jìn)制的形式寫入文件流中

<參數(shù)>buffer-指向?qū)懭霐?shù)據(jù)的指針    size-每一個(gè)元素的大小   count-寫入的最大元素?cái)?shù)

<返回值>實(shí)際寫入的元素?cái)?shù)

<適用>文件流

2.fread——輸入函數(shù)

<功能>將數(shù)據(jù)以二進(jìn)制的形式從文件流中讀取

<返回值>實(shí)際讀入的元素?cái)?shù)

<適用>文件流

 3.使用示范

//頭文件同上略
//fwrite  fread
typedef struct stu
{
	int n;
	float score;
	char name[10];
}stu;
 
int main()
{
	stu s = {10,100.0,"張三"};
	FILE*pr = fopen("test.txt","rb");
	struct stu s1 = { 0 };
	if (pr == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	//fwrite(&s,sizeof(stu),1,pw);
	fread(&s1,sizeof(stu),1,pr);
	fclose(pr);
	pr = NULL;
	return 0;
}

⑥fseek與ftell與rewind

1.fseek

<功能>將文件指針移到指定的位置

<參數(shù)>offset-偏移量        origin-初始化文件指針位置

            origin有三種選擇:SEEK_CUR  從當(dāng)前位置開始

                                           SEEK_END  從文件結(jié)尾開始

                                           SEEK_SET   從文件開頭開始

<返回值>成功返回0,失敗返回非0值

<注意>對(duì)文件指針的修改不可以通過p++的方式實(shí)先

 使用演示(現(xiàn)已知記事本儲(chǔ)存數(shù)據(jù)為“abcdef”)

//fseek
int main()
{
	FILE*pr = fopen("test.txt","r");
	int a = 0;
	if (pr == NULL)
	{
		printf("%s",strerror(errno));
		return 0;
	}
	//定位文件指針
	fseek(pr, -1, SEEK_END);//指向最后一個(gè)的后一個(gè)
	a=fgetc(pr);
    b=ftell(pr);//返回當(dāng)前指針位置
	printf("%c",a);
    printf("%d",b);
	fclose(pr);
	pr = NULL;
	return 0;
}

(若初始化文件指針為SEEK_SET,偏移1則得到b)

2.ftell

<功能>返回當(dāng)前文件指針的偏移量 

3.rewind

<功能>使文件指針回到文件的開始

使用演示

int main()
{
	int n;
	FILE * pFile;
	char buffer[27];
	pFile = fopen("test.txt", "w+");
	for (n = 'A'; n <= 'Z'; n++)
		fputc(n, pFile);
	rewind(pFile);
	fread(buffer, 1, 26, pFile);
	fclose(pFile);
	buffer[26] = '\0';
	puts(buffer);
	return 0;
}

⑦ferror與feof

1.ferror

<功能>檢查流是否發(fā)生了錯(cuò)誤

<返回值>若發(fā)生錯(cuò)誤則返回0,否則返回非0值

2.feof

  

<功能>當(dāng)文件讀取結(jié)束的時(shí)候,判斷是讀取失敗結(jié)束,還是遇到文件尾結(jié)束

<返回值>若不是文件末尾則返回0,是文件末尾則返回非0值

<注意>不能用feof函數(shù)的返回值直接用來判斷文件的是否結(jié)束

1. 文本文件讀取是否結(jié)束,判斷返回值是否為EOF (fgetc),或者NULL(fgets)
例如:
fgetc判斷是否為EOF.
fgets判斷返回值是否為NULL.
2. 二進(jìn)制文件的讀取結(jié)束判斷,判斷返回值是否小于實(shí)際要讀的個(gè)數(shù)。
例如:
fread判斷返回值是否小于實(shí)際要讀的個(gè)數(shù)

使用演示(對(duì)于文本文件)

int main(void)
{
	int c; // 注意:int,非char,要求處理EOF,EOF本質(zhì)上是-1
	FILE* fp = fopen("test.txt", "r");
	if (!fp)
    {
		perror("File opening failed");
		return EXIT_FAILURE;
	}
	//fgetc 當(dāng)讀取失敗的時(shí)候或者遇到文件結(jié)束的時(shí)候,都會(huì)返回EOF
	while ((c = fgetc(fp)) != EOF) // 標(biāo)準(zhǔn)C I/O讀取文件循環(huán)
	{
		putchar(c);
	}
	//判斷是什么原因結(jié)束的
	if (ferror(fp))
		puts("I/O error when reading");
	else if (feof(fp))
		puts("End of file reached successfully");
	fclose(fp);
}

使用演示(對(duì)于二進(jìn)制文件)

enum { SIZE = 5 };
int main(void)
{
	double a[SIZE] = { 1.0, 2.0, 3.0, 4.0, 5.0 };
	double b = 0.0;
	size_t ret_code = 0;
	FILE *fp = fopen("test.bin", "wb"); // 必須用二進(jìn)制模式
	fwrite(a, sizeof(*a), SIZE, fp); // 寫 double 的數(shù)組     sizeof(*)表示這種類型大小
	fclose(fp);
	fp = fopen("test.bin", "rb");
	// 讀 double 的數(shù)組
	while ((ret_code = fread(&b, sizeof(double), 1, fp)) >= 1)
	{
		printf("%lf\n", b);
	}
	if (feof(fp))
		printf("Error reading test.bin: unexpected end of file\n");
	else if (ferror(fp)) {
		perror("Error reading test.bin");
	}
	fclose(fp);
	fp = NULL;
}

⑧補(bǔ)充函數(shù) sscanf sprintf  

1.sprintf

<功能>將特定格式的數(shù)據(jù)寫入字符串

<參數(shù)>buffer-輸出的儲(chǔ)存位置 

<返回值>寫入字符串的數(shù)據(jù)大?。▎挝蛔止?jié))

2.sscanf

<功能>從字符串中讀取特定格式的字符串

3.使用演示

//sprintf  sscanf
typedef struct stu
{
	int n;
	float score;
	char name[10];
}stu;
 
int main()
{
	stu s = {10,3.14,"張三"};
	char buf1[1024] = {0};
	stu s1 = {0};
	sprintf(buf1, "%d %f %s",s.n,s.score,s.name);//不要再加上n=...,score=...
	sscanf(buf1,"%d %f %s",&(s1.n),&(s1.score),&(s1.name));
	printf("%d\n",s1.n);
	printf("%s\n",s1.name);
	return 0 ;
}

⑨補(bǔ)充函數(shù)perror  strerror

 <比較>perror和strerror相比不需要引用errno變量,也不需要使用printf函數(shù),操作更加便捷。同時(shí)自行輸入的字符串起到標(biāo)識(shí)的作用,不會(huì)混淆。

總結(jié)

到此這篇關(guān)于C語言文件操作零基礎(chǔ)新手入門保姆級(jí)教程的文章就介紹到這了,更多相關(guān)C語言文件操作零基礎(chǔ)教程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++回溯算法中的全排列問題分析探討

    C++回溯算法中的全排列問題分析探討

    遞歸中遇到一個(gè)問題全排列的問題,我看見回溯特別神奇,特此記錄一下。對(duì)比一下深度優(yōu)先搜索與廣度優(yōu)先搜索,個(gè)人感覺這里的回溯像是一種遞歸樹中的深度優(yōu)先搜索的算法,他不斷構(gòu)造往下延伸的深度,使其達(dá)到完全編列
    2023-03-03
  • Vscode搭建遠(yuǎn)程c開發(fā)環(huán)境的圖文教程

    Vscode搭建遠(yuǎn)程c開發(fā)環(huán)境的圖文教程

    很久沒有寫C語言了,今天抽空學(xué)習(xí)下C語言知識(shí),接下來通過本文給大家介紹Vscode搭建遠(yuǎn)程c開發(fā)環(huán)境的詳細(xì)步驟,本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-11-11
  • Visual Studio 2019配置qt開發(fā)環(huán)境的搭建過程

    Visual Studio 2019配置qt開發(fā)環(huán)境的搭建過程

    這篇文章主要介紹了Visual Studio 2019配置qt開發(fā)環(huán)境的搭建過程,本文圖文并茂給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • C++ 迷宮游戲?qū)崿F(xiàn)代碼

    C++ 迷宮游戲?qū)崿F(xiàn)代碼

    這篇文章主要介紹了C++ 迷宮游戲?qū)崿F(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C語言運(yùn)算符及其優(yōu)先級(jí)匯總表口訣

    C語言運(yùn)算符及其優(yōu)先級(jí)匯總表口訣

    由于C語言的運(yùn)算符優(yōu)先級(jí)與C++的不完全一樣(主要是增加了幾個(gè)運(yùn)算符),所以這個(gè)口訣不能完全實(shí)用于C++.但是應(yīng)該能夠兼容,大家可以比較一下他們的區(qū)別應(yīng)該就能夠很快掌握C++的優(yōu)先級(jí)的
    2013-07-07
  • C語言靜態(tài)鏈表和動(dòng)態(tài)鏈表

    C語言靜態(tài)鏈表和動(dòng)態(tài)鏈表

    靜態(tài)鏈表和動(dòng)態(tài)鏈表是線性表鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)的兩種不同的表示方式。靜態(tài)鏈表的初始長度一般是固定的,在做插入和刪除操作時(shí)不需要移動(dòng)元素,僅需修改指針。動(dòng)態(tài)鏈表是相對(duì)于靜態(tài)鏈表而言的,一般地,在描述線性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)時(shí)如果沒有特別說明即默認(rèn)描述的是動(dòng)態(tài)鏈表。
    2016-05-05
  • C語言#define拼接宏定義實(shí)現(xiàn)方式

    C語言#define拼接宏定義實(shí)現(xiàn)方式

    今天小編就為大家分享一篇C語言#define拼接宏定義實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • C++的static靜態(tài)成員你有了解嗎

    C++的static靜態(tài)成員你有了解嗎

    這篇文章主要為大家詳細(xì)介紹了C++的static靜態(tài)成員,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • OpenCV實(shí)現(xiàn)二值圖像的邊緣光滑處理

    OpenCV實(shí)現(xiàn)二值圖像的邊緣光滑處理

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)二值圖像的邊緣光滑處理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • visual studio 2019編譯c++17的方法

    visual studio 2019編譯c++17的方法

    這篇文章主要介紹了visual studio 2019編譯c++17的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03

最新評(píng)論