国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄

這篇具有很好參考價(jià)值的文章主要介紹了C語(yǔ)言進(jìn)階之文件操作及改造通訊錄。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

1.為什么使用文件

我們前面學(xué)習(xí)結(jié)構(gòu)體時(shí),寫通訊錄的程序,當(dāng)通訊錄運(yùn)行起來(lái)的時(shí)候,可以給通訊錄中增加、刪除數(shù)據(jù),此時(shí)數(shù)據(jù)是存放在內(nèi)存中,當(dāng)程序退出的時(shí)候,通訊錄中的數(shù)據(jù)自然就不存在了,等下次運(yùn)行通訊錄程序的時(shí)候,數(shù)據(jù)又得重新錄入,如果使用這樣的通訊錄就很難受。

我們?cè)谙爰热皇峭ㄓ嶄浘蛻?yīng)該把信息記錄下來(lái),只有我們自己選擇刪除數(shù)據(jù)的時(shí)候,數(shù)據(jù)才不復(fù)存在。這就涉及到了數(shù)據(jù)持久化的問(wèn)題,我們一般數(shù)據(jù)持久化的方法有,把數(shù)據(jù)存放在磁盤文件、存放到數(shù)據(jù)庫(kù)等方式。

使用文件我們可以將數(shù)據(jù)直接存放在電腦的硬盤上,做到了數(shù)據(jù)的持久化。

2. 什么是文件

磁盤上的文件是文件

但是在程序設(shè)計(jì)中,我們一般談的文件有兩種:程序文件、數(shù)據(jù)文件(從文件功能的角度來(lái)分類的)。

2.1 程序文件

包括源程序文件(后綴為.c),目標(biāo)文件(windows環(huán)境后綴為.obj),可執(zhí)行程序(windows環(huán)境后綴為.exe)。

2.2 數(shù)據(jù)文件

文件的內(nèi)容不一定是程序,而是程序運(yùn)行時(shí)讀寫的數(shù)據(jù),比如程序運(yùn)行需要從中讀取數(shù)據(jù)的文件,或者輸出內(nèi)容的文件。

在之前的文章所處理數(shù)據(jù)的輸入輸出都是以終端為對(duì)象的,即從終端的鍵盤輸入數(shù)據(jù),運(yùn)行結(jié)果顯示到顯示器上。其實(shí)有時(shí)候我們會(huì)把信息輸出到磁盤上,當(dāng)需要的時(shí)候再?gòu)拇疟P上把數(shù)據(jù)讀取到內(nèi)存中使用,這里處理的就是磁盤上文件。

2.3 文件名

一個(gè)文件要有一個(gè)唯一的文件標(biāo)識(shí),以便用戶識(shí)別和引用。
文件名包含3部分:文件路徑+文件名主干+文件后綴
例如: c:\code\test.txt
為了方便起見(jiàn),文件標(biāo)識(shí)常被稱為文件名。

3. 文件的打開(kāi)和關(guān)閉

3.1 文件指針

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

struct _iobuf {
        char* _ptr;
        int   _cnt;
        char* _base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char* _tmpfname;
    };
    typedef struct _iobuf FILE;

不同的C編譯器的FILE類型包含的內(nèi)容不完全相同,但是大同小異。

每當(dāng)打開(kāi)一個(gè)文件的時(shí)候,系統(tǒng)會(huì)根據(jù)文件的情況自動(dòng)創(chuàng)建一個(gè)FILE結(jié)構(gòu)的變量,并填充其中的信息,使用者不必關(guān)心細(xì)節(jié)。

一般都是通過(guò)一個(gè)FILE的指針來(lái)維護(hù)這個(gè)FILE結(jié)構(gòu)的變量,這樣使用起來(lái)更加方便。

下面我們可以創(chuàng)建一個(gè)FILE*的指針變量:

FILE* pf;//文件指針變量

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

3.2 文件的打開(kāi)和關(guān)閉

文件在讀寫之前應(yīng)該先打開(kāi)文件,在使用結(jié)束之后應(yīng)該關(guān)閉文件。
在編寫程序的時(shí)候,在打開(kāi)文件的同時(shí),都會(huì)返回一個(gè)FILE*的指針變量指向該文件,也相當(dāng)于建立了指針和文件的關(guān)系。
ANSIC 規(guī)定使用fopen函數(shù)來(lái)打開(kāi)文件,fclose來(lái)關(guān)閉文件。

//打開(kāi)文件
FILE * fopen ( const char * filename, const char * mode );
//關(guān)閉文件
int fclose ( FILE * stream );
文件使用方式 含義 如果指定文件不存在
“r”(只讀) 為了輸入數(shù)據(jù),打開(kāi)一個(gè)已經(jīng)存在的文本文件 出錯(cuò)
“w”(只寫) 為了輸出數(shù)據(jù),打開(kāi)一個(gè)文本文件 建立一個(gè)新的文件
“a”(追加) 向文本文件尾添加數(shù)據(jù) 建立一個(gè)新的文件
“rb”(只讀) 為了輸入數(shù)據(jù),打開(kāi)一個(gè)二進(jìn)制文件 出錯(cuò)
“wb”(只寫) 為了輸出數(shù)據(jù),打開(kāi)一個(gè)二進(jìn)制文件 建立一個(gè)新的文件
“ab”(追加) 向一個(gè)二進(jìn)制文件尾添加數(shù)據(jù) 建立一個(gè)新的文件
“r+”(讀寫) 為了讀和寫,打開(kāi)一個(gè)文本文件 出錯(cuò)
“w+”(讀寫) 為了讀和寫,建議一個(gè)新的文件 建立一個(gè)新的文件
“a+”(讀寫) 打開(kāi)一個(gè)文件,在文件尾進(jìn)行讀寫 建立一個(gè)新的文件
“rb+”(讀寫) 為了讀和寫打開(kāi)一個(gè)二進(jìn)制文件 出錯(cuò)
“wb+”(讀寫) 為了讀和寫,新建一個(gè)新的二進(jìn)制文件 建立一個(gè)新的文件
“ab+”(讀寫) 打開(kāi)一個(gè)二進(jìn)制文件,在文件尾進(jìn)行讀和寫 建立一個(gè)新的文件

示例:

//相對(duì)路徑
FILE* pf = fopen("..\\Debug\\data.txt", "w");

//絕對(duì)路徑
//C:\Users\Administrator\Desktop\data.txt
FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt", "w");
#include <stdio.h>
int main()
{
    FILE* pFile;
    //打開(kāi)文件
    pFile = fopen("myfile.txt", "w");
    //文件操作
    if (pFile != NULL)
    {
        fputs("fopen example", pFile);
        //關(guān)閉文件
        fclose(pFile);
    }
    return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

4. 文件的順序讀寫

4.1 順序讀寫函數(shù)介紹

功能 函數(shù)名 適用于
字符輸入函數(shù) fgetc 所有輸入流
字符輸出函數(shù) fputc 所有輸出流
文本行輸入函數(shù) fgets 所有輸入流
文本行輸出函數(shù) fputs 所有輸出流
格式化輸入函數(shù) fscanf 所有輸入流
格式化輸出函數(shù) fprintf 所有輸出流
二進(jìn)制輸入 fread 文件
二進(jìn)制輸出 fwrite 文件

舉例:
fgetc

#include <stdio.h>
int main()
{

	//讀文件
	int ch = fgetc(stdin);
	printf("%c\n", ch);
	ch = fgetc(stdin);
	printf("%c\n", ch);
	ch = fgetc(stdin);
	printf("%c\n", ch);
	ch = fgetc(stdin);
	printf("%c\n", ch);

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
fputc

int main()
{
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//寫文件
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	int i = 0;
	for (i = 0; i < 26; i++)
	{
		fputc('a'+i, stdout);
	}

	//關(guān)閉文件
	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
fputs

int main()
{
	FILE* pf = fopen("data.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//寫文件 - 寫一行
	fputs("hello world\n", pf);
	fputs("hello vs2022\n", pf);

	//關(guān)閉文件
	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
fgets

#include <stdio.h>
int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//讀文件 - 讀一行
	char arr[30] = { 0 };
	fgets(arr, 30, pf);
	printf("%s", arr);
	fgets(arr, 30, pf);
	printf("%s", arr);

	//關(guān)閉文件
	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

下面我們對(duì)比
printf/fprintf/sprintf
scanf/fscanf/sscanf
分別有什么不同的作用
printf

int printf ( const char * format, ... );

將按格式指向的 C 字符串寫入標(biāo)準(zhǔn)輸出 (stdout)。如果 format 包含格式說(shuō)明符(以 % 開(kāi)頭的子序列),則格式后面的其他參數(shù)將被格式化并插入到生成的字符串中,替換其各自的說(shuō)明符。
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
返回值

成功后,將返回寫入的字符總數(shù)。

如果發(fā)生寫入錯(cuò)誤,則設(shè)置錯(cuò)誤指示器(ferror)并返回負(fù)數(shù)。

如果在寫入寬字符時(shí)發(fā)生多字節(jié)字符編碼錯(cuò)誤,errno 將設(shè)置為 EILSEQ 并返回負(fù)數(shù)

fprintf

int fprintf ( FILE * stream, const char * format, ... );

將按格式指向流的 C 字符串寫入流。如果 format 包含格式說(shuō)明符(以 % 開(kāi)頭的子序列),則格式后面的其他參數(shù)將被格式化并插入到生成的字符串中,替換其各自的說(shuō)明符。

在 format 參數(shù)之后,函數(shù)至少需要與格式指定的一樣多的其他參數(shù)。

返回值

成功后,將返回寫入的字符總數(shù)。

如果發(fā)生寫入錯(cuò)誤,則設(shè)置錯(cuò)誤指示器(ferror)并返回負(fù)數(shù)。

如果在寫入寬字符時(shí)發(fā)生多字節(jié)字符編碼錯(cuò)誤,errno 將設(shè)置為 EILSEQ 并返回負(fù)數(shù)。
示例:

struct S
{
	int a;
	float s;
};


int main()
{
	FILE* pf = fopen("data.txt", "w");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//寫文件
	struct S s = { 100, 3.14f };
	fprintf(pf, "%d %f", s.a, s.s);

	//關(guān)閉文件
	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
scanf

int scanf ( const char * format, ... );

從 stdin 讀取數(shù)據(jù),并根據(jù)參數(shù)格式將它們存儲(chǔ)到附加參數(shù)所指向的位置。

其他參數(shù)應(yīng)指向格式字符串中相應(yīng)格式說(shuō)明符指定的類型的已分配對(duì)象。
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
返回值

成功后,該函數(shù)返回成功填充的參數(shù)列表的項(xiàng)數(shù)。此計(jì)數(shù)可以與預(yù)期的項(xiàng)目數(shù)匹配,也可以由于匹配失敗、讀取錯(cuò)誤或文件末尾的到達(dá)而減少(甚至為零)。

如果發(fā)生讀取錯(cuò)誤或在讀取時(shí)到達(dá)文件末尾,則會(huì)設(shè)置正確的指示器(feof 或 ferror)。并且,如果在成功讀取任何數(shù)據(jù)之前發(fā)生任一情況,則返回 EOF。

如果在解釋寬字符時(shí)發(fā)生編碼錯(cuò)誤,該函數(shù)會(huì)將 errno 設(shè)置為 EILSEQ。
fscanf

int fscanf ( FILE * stream, const char * format, ... );

從流中讀取數(shù)據(jù),并根據(jù)參數(shù)格式將其存儲(chǔ)到附加參數(shù)指向的位置。

其他參數(shù)應(yīng)指向格式字符串中相應(yīng)格式說(shuō)明符指定的類型的已分配對(duì)象。

返回值

成功后,該函數(shù)返回成功填充的參數(shù)列表的項(xiàng)數(shù)。此計(jì)數(shù)可以與預(yù)期的項(xiàng)目數(shù)匹配,也可以由于匹配失敗、讀取錯(cuò)誤或文件末尾的到達(dá)而減少(甚至為零)。

如果發(fā)生讀取錯(cuò)誤或在讀取時(shí)到達(dá)文件末尾,則會(huì)設(shè)置正確的指示器(feof 或 ferror)。并且,如果在成功讀取任何數(shù)據(jù)之前發(fā)生任一情況,則返回 EOF。

如果在解釋寬字符時(shí)發(fā)生編碼錯(cuò)誤,該函數(shù)會(huì)將 errno 設(shè)置為 EILSEQ。

示例:

//文件是由上面的fprintf示例生成
struct S
{
	int a;
	float s;
};


int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//寫文件
	struct S s = {0};
	fscanf(pf, "%d %f", &(s.a), &(s.s));

	printf("%d %f", s.a, s.s);

	//關(guān)閉文件
	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

sprintf

int sprintf ( char * str, const char * format, ... );

使用與在 printf 上使用格式時(shí)打印的文本相同的文本組成字符串,但內(nèi)容不是打印,而是作為 C 字符串存儲(chǔ)在 str 指向的緩沖區(qū)中。

緩沖區(qū)的大小應(yīng)足夠大,以包含整個(gè)生成的字符串。

終止空字符會(huì)自動(dòng)追加到內(nèi)容之后。

在 format 參數(shù)之后,該函數(shù)至少需要與格式所需的其他參數(shù)一樣多。

返回值

成功后,將返回寫入的字符總數(shù)。此計(jì)數(shù)不包括自動(dòng)追加在字符串末尾的其他 null 字符。
失敗時(shí),返回負(fù)數(shù)。

sscanf

int sscanf ( const char * s, const char * format, ...);

從 s 讀取數(shù)據(jù)并根據(jù)參數(shù)格式將它們存儲(chǔ)到附加參數(shù)給出的位置,就像使用 scanf 一樣,但從 s 而不是標(biāo)準(zhǔn)輸入 (stdin) 讀取。

其他參數(shù)應(yīng)指向格式字符串中相應(yīng)格式說(shuō)明符指定的類型的已分配對(duì)象。

返回值

成功后,該函數(shù)返回參數(shù)列表中成功填充的項(xiàng)數(shù)。此計(jì)數(shù)可以與預(yù)期的項(xiàng)目數(shù)匹配,或者在匹配失敗的情況下更少(甚至為零)。
如果在成功解釋任何數(shù)據(jù)之前輸入失敗,則返回 EOF。

示例:

struct S
{
	int a;
	float s;
	char str[10];
};

int main()
{
	char arr[30] = { 0 };
	struct S s = { 100, 3.14f, "hehe" };
	struct S tmp = {0};

	sprintf(arr, "%d %f %s", s.a, s.s, s.str);

	sscanf(arr, "%d %f %s", &(tmp.a), &(tmp.s), tmp.str);

	printf("%d %f %s\n", tmp.a, tmp.s, tmp.str);

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

將計(jì)數(shù)元素?cái)?shù)組(每個(gè)元素的大小為字節(jié))從 ptr 指向的內(nèi)存塊寫入流中的當(dāng)前位置。

流的位置指示器按寫入的總字節(jié)數(shù)前進(jìn)。

在內(nèi)部,該函數(shù)解釋所指向的塊,就好像它是一個(gè)類型的元素?cái)?shù)組,并按順序?qū)懭胨鼈儯秃孟駷槊總€(gè)字節(jié)調(diào)用一樣。

返回值

返回成功寫入的元素總數(shù)。
如果此數(shù)字與 count 參數(shù)不同,則寫入錯(cuò)誤阻止函數(shù)完成。在這種情況下,將為流設(shè)置錯(cuò)誤指示器(ferror)。
如果大小或計(jì)數(shù)為零,則該函數(shù)返回零,錯(cuò)誤指示器保持不變。
size_t 是無(wú)符號(hào)整數(shù)類型。

示例:

struct S
{
	int a;
	float s;
	char str[10];
};

int main()
{
	struct S s = { 99, 6.18f, "bit" };

	FILE* pf = fopen("data.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//寫文件
	fwrite(&s, sizeof(struct S), 1, pf);

	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
因?yàn)槭且远M(jìn)制編碼形式存入,所以使用文本編輯器打開(kāi)是亂碼
我們可以將其添加到vs
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
這里每個(gè)字節(jié)的十六進(jìn)制對(duì)應(yīng)的ASCII碼值即為對(duì)應(yīng)字符。

fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

從流中讀取計(jì)數(shù)元素?cái)?shù)組,每個(gè)元素的大小為字節(jié),并將它們存儲(chǔ)在 ptr 指定的內(nèi)存塊中。

流的位置指示器按讀取的總字節(jié)數(shù)前進(jìn)。

如果成功,則讀取的總字節(jié)數(shù)為(大小*計(jì)數(shù))。

返回值

返回成功讀取的元素總數(shù)。
如果此數(shù)字與 count 參數(shù)不同,則表示讀取時(shí)發(fā)生讀取錯(cuò)誤或到達(dá)文件末尾。在這兩種情況下,都會(huì)設(shè)置正確的指標(biāo),可以分別用 ferror 和 feof 進(jìn)行檢查。
如果大小或計(jì)數(shù)為零,則該函數(shù)返回零,并且流狀態(tài)和 ptr 指向的內(nèi)容保持不變。
size_t 是無(wú)符號(hào)整數(shù)類型。

示例:

struct S
{
	int a;
	float s;
	char str[10];
};

int main()
{
	struct S s = { 0 };

	FILE* pf = fopen("data.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//讀文件
	fread(&s, sizeof(struct S), 1, pf);
	printf("%d %f %s\n", s.a, s.s, s.str);

	fclose(pf);
	pf = NULL;

	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

5. 文件的隨機(jī)讀寫

5.1 fseek

根據(jù)文件指針的位置和偏移量來(lái)定位文件指針。

int fseek ( FILE * stream, long int offset, int origin );

將與流關(guān)聯(lián)的位置指示器設(shè)置為新位置。

對(duì)于以二進(jìn)制模式打開(kāi)的流,新位置是通過(guò)向源指定的參考位置添加偏移量來(lái)定義的。

對(duì)于以文本模式打開(kāi)的流,偏移量應(yīng)為零或先前調(diào)用 ftel 返回的值,并且源必須SEEK_SET。

如果使用這些參數(shù)的其他值調(diào)用函數(shù),則支持取決于特定的系統(tǒng)和庫(kù)實(shí)現(xiàn)(不可移植)。

成功調(diào)用此函數(shù)后,流的文件結(jié)束內(nèi)部指示器將被清除,并且之前對(duì)此流的 ungetc 調(diào)用的所有效果都將被刪除。

在開(kāi)放進(jìn)行更新(讀+寫)的流上,對(duì) fseek 的調(diào)用允許在讀取和寫入之間切換。

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

示例:

int main()
{
	FILE* pFile;
	pFile = fopen("example.txt", "wb");
	fputs("This is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);
	fputs(" sam", pFile);
	fclose(pFile);
	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

int main()
{
	FILE* pf = fopen("example.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//讀文件
	//定位文件指針到pf
	int ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);


	fseek(pf, -3, SEEK_CUR);
	ch = fgetc(pf);
	printf("%c\n", ch);

	fclose(pf);
	pf = NULL;
	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

5.2 ftell

返回文件指針相對(duì)于起始位置的偏移量

long int ftell ( FILE * stream );

返回流的位置指示器的當(dāng)前值。

對(duì)于二進(jìn)制流,這是從文件開(kāi)頭開(kāi)始的字節(jié)數(shù)。

對(duì)于文本流,數(shù)值可能沒(méi)有意義,但仍可用于稍后使用 fseek 將位置恢復(fù)到相同位置(如果有使用 ungetc 放回的字符仍在等待讀取,則行為未定義)。

返回值

成功后,返回倉(cāng)位指標(biāo)的當(dāng)前值。
失敗時(shí),返回 -1L,并將 errno 設(shè)置為特定于系統(tǒng)的正值。

示例:

int main()
{
	FILE* pf = fopen("example.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//讀文件
	//定位文件指針到pf
	int ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);


	int pos = ftell(pf);
	printf("%d\n", pos);

	fclose(pf);
	pf = NULL;
	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

5.3 rewind

讓文件指針的位置回到文件的起始位置

void rewind ( FILE * stream );

將與流關(guān)聯(lián)的位置指示器設(shè)置為文件的開(kāi)頭。

成功調(diào)用此函數(shù)后,將清除與流關(guān)聯(lián)的文件結(jié)束和錯(cuò)誤內(nèi)部指示器,并且將丟棄以前對(duì)此流上 ungetc 的調(diào)用的所有效果。

在打開(kāi)進(jìn)行更新(讀+寫)的流上,對(duì)倒帶的調(diào)用允許在讀取和寫入之間切換。

示例:

int main()
{
	FILE* pf = fopen("example.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//讀文件
	//定位文件指針到pf
	int ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);


	rewind(pf);
	
	ch = fgetc(pf);
	printf("%c\n", ch);

	fclose(pf);
	pf = NULL;
	return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

6. 文本文件和二進(jìn)制文件

根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件被稱為文本文件或者二進(jìn)制文件。
數(shù)據(jù)在內(nèi)存中以二進(jìn)制的形式存儲(chǔ),如果不加轉(zhuǎn)換的輸出到外存,就是二進(jìn)制文件。
如果要求在外存上以ASCII碼的形式存儲(chǔ),則需要在存儲(chǔ)前轉(zhuǎn)換。以ASCII字符的形式存儲(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è)字節(jié)),而二進(jìn)制形式輸出,則在磁盤上只占4個(gè)字節(jié)(VS2022測(cè)試)。

7. 文件讀取結(jié)束的判定

7.1 被錯(cuò)誤使用的feof

牢記:在文件讀取過(guò)程中,不能用feof函數(shù)的返回值直接來(lái)判斷文件的是否結(jié)束。

feof 的作用是:當(dāng)文件讀取結(jié)束的時(shí)候,判斷是讀取結(jié)束的原因是否是:遇到文件尾結(jié)束。

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

正確使用示例:
文本文件:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int c; // 注意:int,非char,要求處理EOF
    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);

    return 0;
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
二進(jìn)制文件:

#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{
    double a[SIZE] = { 1.,2.,3.,4.,5. };
    FILE* fp = fopen("test.bin", "wb"); // 必須用二進(jìn)制模式
    fwrite(a, sizeof * a, SIZE, fp); // 寫 double 的數(shù)組
    fclose(fp);
    double b[SIZE];
    fp = fopen("test.bin", "rb");
    size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 讀 double 的數(shù)組
    if (ret_code == SIZE) {
        puts("Array read successfully, contents: ");
        for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
        putchar('\n');
    }
    else { // error handling
        if (feof(fp))
            printf("Error reading test.bin: unexpected end of file\n");
        else if (ferror(fp)) {
            perror("Error reading test.bin");
        }
    }
    fclose(fp);
}

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

8. 文件緩沖區(qū)

ANSIC 標(biāo)準(zhǔn)采用“緩沖文件系統(tǒng)”處理的數(shù)據(jù)文件的,所謂緩沖文件系統(tǒng)是指系統(tǒng)自動(dòng)地在內(nèi)存中為程序中每一個(gè)正在使用的文件開(kāi)辟一塊“文件緩沖區(qū)”。從內(nèi)存向磁盤輸出數(shù)據(jù)會(huì)先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才一起送到磁盤上。如果從磁盤向計(jì)算機(jī)讀入數(shù)據(jù),則從磁盤文件中讀取數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再?gòu)木彌_區(qū)逐個(gè)地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(程序變量等)。緩沖區(qū)的大小根據(jù)C編譯系統(tǒng)決定的。

C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

#include <windows.h>
//VS2022 WIN11環(huán)境測(cè)試
int main()
{
 FILE*pf = fopen("test.txt", "w");
 fputs("abcdef", pf);//先將代碼放在輸出緩沖區(qū)
 printf("睡眠10秒-已經(jīng)寫數(shù)據(jù)了,打開(kāi)test.txt文件,發(fā)現(xiàn)文件沒(méi)有內(nèi)容\n");
 Sleep(10000);
 printf("刷新緩沖區(qū)\n");
 fflush(pf);//刷新緩沖區(qū)時(shí),才將輸出緩沖區(qū)的數(shù)據(jù)寫到文件(磁盤)
 //注:fflush 在高版本的VS上不能使用了
 printf("再睡眠10秒-此時(shí),再次打開(kāi)test.txt文件,文件有內(nèi)容了\n");
 Sleep(10000);
 fclose(pf);
 //注:fclose在關(guān)閉文件的時(shí)候,也會(huì)刷新緩沖區(qū)
 pf = NULL;
 return 0;
}

這里可以得出一個(gè)結(jié)論:
因?yàn)橛芯彌_區(qū)的存在,C語(yǔ)言在操作文件的時(shí)候,需要做刷新緩沖區(qū)或者在文件操作結(jié)束的時(shí)候關(guān)閉文件。
如果不做,可能導(dǎo)致讀寫文件的問(wèn)題。

9.通訊錄改造

我們之前的文章寫道動(dòng)態(tài)版的通訊錄,但是在程序退出時(shí),隨著程序的終止,通訊錄數(shù)據(jù)也隨著清除了,那么我們根據(jù)這一章節(jié)的文件操作知識(shí),是否有辦法將我們的文件保存下來(lái)呢,在重新進(jìn)入文件時(shí),又能否讀取保存的通訊錄呢,下面我們就開(kāi)始改造通訊錄吧!

9.1 保存通訊錄到本地

首先我們?cè)黾雍瘮?shù)SaveCon到頭文件聲明,并在contact.c文件中定義

void SaveCon(Con* cont)
{
	FILE* pf = fopen("contact.dat", "wb");
	if (pf == NULL)
	{
		perror("fopen");
	}
	int i = 0;
	for (i = 0; i < cont->sz; i++)
	{
		fwrite(cont->data + i, sizeof(peo), 1, pf);
	}
	fclose(pf);
	pf = NULL;
}

首先這里是打開(kāi)condact.dat文件進(jìn)行讀寫,判斷是否成功,成功后逐字符進(jìn)行寫入,最后關(guān)閉文件,指針置空。
主函數(shù)switch語(yǔ)句中EXIT選項(xiàng)調(diào)用
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
示例:
我們添加4個(gè)聯(lián)系人
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

9.2 讀取本地通訊錄

我們只需在初始化函數(shù)InitCon最后調(diào)用一個(gè)讀取函數(shù)LoadCon即可,接下來(lái)我們編寫LoadCon函數(shù)

int CheckCapacity(Con* cont);
void LoadCon(Con* cont)
{
	FILE* pf = fopen("contact.dat", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	peo tmp = { 0 };
	while (fread(&tmp, sizeof(peo), 1, pf))
	{
		if (0 == CheckCapacity(cont))
			return;
		cont->data[cont->sz] = tmp;
		cont->sz++;
	}
	fclose(pf);
	pf = NULL;
}

首先我們打開(kāi)保存的文件,建立臨時(shí)的peo,逐個(gè)讀取文件內(nèi)容,逐個(gè)復(fù)制到cont->data內(nèi),最后關(guān)閉文件,指針置空,需要注意的是,這里我們使用了CheckCapacity函數(shù),所以要在前面加上聲明,否則他會(huì)找不到此函數(shù)。
C語(yǔ)言進(jìn)階之文件操作及改造通訊錄,C語(yǔ)言進(jìn)階,c語(yǔ)言,開(kāi)發(fā)語(yǔ)言,編輯器

9.3 通訊錄最終版全部代碼

contact.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
#define NAME_MAX 10
#define SEX_MAX 6
#define ADDR_MAX 20
#define TELE_MAX 12
#define N 3
#define INC 2

typedef struct people
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char addr[ADDR_MAX];

}peo;

typedef struct Contact
{
	peo* data;
	int capacity;
	int sz;
}Con;

enum
{
	EXIT,
	ADD,
	DEL,
	MOD,
	SEARCH,
	SHOW,
	DISTORY,
	QSORT
};

void InitCon(Con* cont);

void add(Con* cont);

void show(const Con* cont);

int FindName(const Con* cont, const char* name);

void del(Con* cont);

void mod(Con* cont);

void sel(const Con* cont);

void Distory(Con* cont);

int cmp_stu_by_name(const void* p1, const void* p2);

void DistoryCon(Con* cont);

void SaveCon(Con* cont);

contact.c

#include "contact.h"
int CheckCapacity(Con* cont);
void LoadCon(Con* cont)
{
	FILE* pf = fopen("contact.dat", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	peo tmp = { 0 };
	while (fread(&tmp, sizeof(peo), 1, pf))
	{
		if (0 == CheckCapacity(cont))
			return;
		cont->data[cont->sz] = tmp;
		cont->sz++;
	}
	fclose(pf);
	pf = NULL;
}

void InitCon(Con* cont)
{
	assert(cont);
	cont->data = (peo*)malloc(N * sizeof(peo));
	if (cont->data == NULL)
	{
		perror("malloc");
		return;
	}
	cont->sz = 0;
	cont->capacity = N;

	LoadCon(cont);
}


int CheckCapacity(Con* cont)
{
	if (cont->sz == cont->capacity)
	{
		peo* tmp = (peo*)realloc(cont->data, (cont->capacity + INC) * sizeof(peo));
		if (tmp == NULL)
		{
			perror("relloc");
			return 0;
		}
		else
		{
			cont->data = tmp;
			cont->capacity += INC;
			printf("增容成功");
			return 1;
		}
	}
	return 1;
}

void add(Con* cont)
{
	assert(cont);
	if (0 == CheckCapacity(cont))
		return;
		
	printf("請(qǐng)輸入要添加聯(lián)系人的信息:\n");
	printf("請(qǐng)輸入姓名:");
	scanf("%s", cont->data[cont->sz].name);
	printf("請(qǐng)輸入性別:");
	scanf("%s", cont->data[cont->sz].sex);
	printf("請(qǐng)輸入年齡:");
	scanf("%d", &cont->data[cont->sz].age);
	printf("請(qǐng)輸入電話:");
	scanf("%s", cont->data[cont->sz].tele);
	printf("請(qǐng)輸入地址:");
	scanf("%s", cont->data[cont->sz].addr);
	cont->sz++;
	printf("添加成功\n");
}


void show(const Con* cont)
{
	assert(cont);
	int i = 0;
	printf("				通訊錄\n");
	printf("	+---------------------------------------------------------------+\n");
	printf("	|姓名		性別	年齡	電話		地址		|\n");
	for (i = 0; i < cont->sz; i++)
	{
		printf("	|%-10s	%-5s	%-5d	%-11s	%-15s |\n", cont->data[i].name, cont->data[i].sex, cont->data[i].age, cont->data[i].tele, cont->data[i].addr);
	}
	printf("	+---------------------------------------------------------------+\n");
}


int FindName(const Con* cont, const char* name)//查找人函數(shù)
{
	assert(cont && name);//防止傳入空指針
	int i = 0;
	for (i = 0; i < cont->sz; i++)
	{
		if (!strcmp(cont->data[i].name, name))//查找通訊錄是否有這個(gè)名字
		{
			return i;//有就返回下標(biāo)
		}
	}
	return -1;//沒(méi)有返回一個(gè)負(fù)數(shù).
}

void del(Con* cont)//刪除聯(lián)系人函數(shù)
{
	assert(cont);//防止傳入空指針
	int i = 0;
	char name[NAME_MAX];
	printf("請(qǐng)輸入需要?jiǎng)h除的聯(lián)系人的姓名:\n");
	scanf("%s", name);
	i = FindName(cont, name);
	if (i == -1)
	{
		printf("通訊錄中沒(méi)有該聯(lián)系人,刪除失敗\n");
		return;
	}
	for (; i < cont->sz - 1; i++)//注意這里sz要-1,因?yàn)橄旅嬗玫搅薸+1下標(biāo)
	{
		cont->data[i] = cont->data[i + 1];
	}
	cont->sz--;
	printf("刪除成功,姓名為%s的聯(lián)系人已刪除\n", name);
}


void mod(Con* cont)//修改聯(lián)系人函數(shù)
{
	assert(cont);//防止傳入空指針
	int ret = 0;
	char name[NAME_MAX];
	printf("請(qǐng)輸入要修改的聯(lián)系人的姓名:\n");
	scanf("%s", name);
	ret = FindName(cont, name);
	if (ret == -1)
	{
		printf("通訊錄中沒(méi)有該聯(lián)系人,修改失敗\n");
		return;
	}
	printf("請(qǐng)輸入修改后聯(lián)系人的信息:\n");
	printf("請(qǐng)輸入姓名:");
	scanf("%s", cont->data[ret].name);
	printf("請(qǐng)輸入性別:");
	scanf("%s", cont->data[ret].sex);
	printf("請(qǐng)輸入年齡:");
	scanf("%d", &cont->data[ret].age);
	printf("請(qǐng)輸入電話:");
	scanf("%s", cont->data[ret].tele);
	printf("請(qǐng)輸入地址:");
	scanf("%s", cont->data[ret].addr);
	printf("修改成功.\n");
}


void sel(const Con* cont)//查詢聯(lián)系人函數(shù)
{

	char name[NAME_MAX];
	printf("請(qǐng)輸入要查詢的聯(lián)系人的名字:\n");
	scanf("%s", name);
	int ret = FindName(cont, name);
	if (ret == -1)
	{
		printf("通訊錄中沒(méi)有該聯(lián)系人,查詢失敗.\n");
		return;
	}
	printf("查詢成功,該聯(lián)系信息如下:\n");
	printf("	+---------------------------------------------------------------+\n");
	printf("	|姓名		性別	年齡	電話		地址		|\n");
	printf("	|%-10s	%-5s	%-5d	%-11s	%-15s |\n", cont->data[ret].name, cont->data[ret].sex, cont->data[ret].age, cont->data[ret].tele, cont->data[ret].addr);
	printf("	+---------------------------------------------------------------+\n");
}

void Distory(Con* cont)
{
	assert(cont);
	cont->sz = 0;
	printf("全部聯(lián)系人刪除成功!\n");
}

int cmp_stu_by_name(const void* p1, const void* p2)
{
	return strcmp(((peo*)p1)->name, ((peo*)p2)->name);
}

void DistoryCon(Con* cont)
{
	free(cont->data);
	cont->data = NULL;
	cont->capacity = 0;
	cont->sz = 0;
}

void SaveCon(Con* cont)
{
	FILE* pf = fopen("contact.dat", "wb");
	if (pf == NULL)
	{
		perror("fopen");
	}
	int i = 0;
	for (i = 0; i < cont->sz; i++)
	{
		fwrite(cont->data + i, sizeof(peo), 1, pf);
	}
	fclose(pf);
	pf = NULL;
}

main.c

#include"contact.h"

void menu()
{
	printf("\n				歡迎使用通訊錄:\n");
	printf("	+-------------------------------------------------------------+\n");
	printf("	|	1.添加聯(lián)系人			2.刪除聯(lián)系人	      |\n");
	printf("	|	3.修改聯(lián)系人			4.查詢聯(lián)系人	      |\n");
	printf("	|	5.展示通訊錄			6.刪除全部聯(lián)系人      |\n");
	printf("	|	7.排序聯(lián)系人		        0.退出通訊錄	      |\n");
	printf("	+-------------------------------------------------------------+\n");
	printf("請(qǐng)選擇:");
}
int main()
{
	int input = 0;
	Con cont;
	InitCon(&cont);
	while (1) {
		do
		{
			menu();

			scanf("%d", &input);
			switch (input)
			{
			case EXIT:
				SaveCon(&cont);
				DistoryCon(&cont);
				printf("退出通訊錄");
				break;
			case ADD:
				add(&cont);
				break;
			case DEL:
				del(&cont);
				break;
			case MOD:
				mod(&cont);
				break;
			case SEARCH:
				sel(&cont);
				break;
			case SHOW:
				show(&cont);
				break;
			case DISTORY:
				Distory(&cont);
				break;
			case QSORT:
				qsort(cont.data, cont.sz, sizeof(peo), cmp_stu_by_name);
				printf("排序成功\n");
				break;
			default:
				printf("輸入錯(cuò)誤");
				break;
			}
		} while (input);
		break;
	}
	
	return 0;
}


結(jié)語(yǔ)

有興趣的小伙伴可以關(guān)注作者,如果覺(jué)得內(nèi)容不錯(cuò),請(qǐng)給個(gè)一鍵三連吧,蟹蟹你喲?。?!
制作不易,如有不正之處敬請(qǐng)指出
感謝大家的來(lái)訪,UU們的觀看是我堅(jiān)持下去的動(dòng)力
在時(shí)間的催化劑下,讓我們彼此都成為更優(yōu)秀的人吧??!!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-568702.html

到了這里,關(guān)于C語(yǔ)言進(jìn)階之文件操作及改造通訊錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【進(jìn)階C語(yǔ)言】靜態(tài)版通訊錄的實(shí)現(xiàn)(詳細(xì)講解+全部源碼)

    【進(jìn)階C語(yǔ)言】靜態(tài)版通訊錄的實(shí)現(xiàn)(詳細(xì)講解+全部源碼)

    前言 ??作者簡(jiǎn)介: 熱愛(ài)跑步的恒川 ,正在學(xué)習(xí)C/C++、Java、Python等。 ??本文收錄于 C語(yǔ)言進(jìn)階 系列,本專欄主要內(nèi)容為數(shù)據(jù)的存儲(chǔ)、指針的進(jìn)階、字符串和內(nèi)存函數(shù)的介紹、自定義類型結(jié)構(gòu)、動(dòng)態(tài)內(nèi)存管理、文件操作等,持續(xù)更新! ??相關(guān)專欄Python,Java等正在發(fā)展,拭目

    2023年04月25日
    瀏覽(31)
  • 【進(jìn)階C語(yǔ)言】動(dòng)態(tài)版通訊錄的實(shí)現(xiàn)(詳細(xì)講解+全部碼源)

    【進(jìn)階C語(yǔ)言】動(dòng)態(tài)版通訊錄的實(shí)現(xiàn)(詳細(xì)講解+全部碼源)

    前言 ??作者簡(jiǎn)介: 熱愛(ài)跑步的恒川 ,致力于 C/C++、Java、Python 等多編程語(yǔ)言,熱愛(ài)跑步,喜愛(ài)音樂(lè)的一位博主。 ??本文收錄于 C語(yǔ)言進(jìn)階 系列,本專欄主要內(nèi)容為數(shù)據(jù)的存儲(chǔ)、指針的進(jìn)階、字符串和內(nèi)存函數(shù)的介紹、自定義類型結(jié)構(gòu)、動(dòng)態(tài)內(nèi)存管理、文件操作等,持續(xù)更

    2024年02月01日
    瀏覽(22)
  • 【C語(yǔ)言】通訊錄(文件) -- 詳解

    【C語(yǔ)言】通訊錄(文件) -- 詳解

    前面介紹了 【C語(yǔ)言】靜態(tài)通訊錄 -- 詳解_炫酷的伊莉娜的博客-CSDN博客 和 【C語(yǔ)言】動(dòng)態(tài)通訊錄 -- 詳解_炫酷的伊莉娜的博客-CSDN博客 。當(dāng)通訊錄運(yùn)行起來(lái)時(shí),可以對(duì)通訊錄中的數(shù)據(jù)進(jìn)行增加、刪除或修改等。此時(shí)數(shù)據(jù)是存放在內(nèi)存中,當(dāng)程序退出時(shí),通訊錄中的數(shù)據(jù)自然就

    2024年02月12日
    瀏覽(20)
  • 【C語(yǔ)言】實(shí)現(xiàn)通訊錄(動(dòng)態(tài)+文件)

    【C語(yǔ)言】實(shí)現(xiàn)通訊錄(動(dòng)態(tài)+文件)

    在之前三子棋和掃雷的基礎(chǔ)上,本篇文章博主將給大家逐步分析實(shí)現(xiàn)通訊錄,介紹通訊錄的每個(gè)功能( 動(dòng)態(tài)增長(zhǎng)和文件保存 )。 —————————————————————— test.c - 測(cè)試通訊錄 Contact.c - 函數(shù)的實(shí)現(xiàn) Contact.h - 函數(shù)和類型的聲明 以多文件的形式分模塊寫的

    2024年02月13日
    瀏覽(78)
  • C語(yǔ)言實(shí)現(xiàn)通訊錄(文件版)

    C語(yǔ)言實(shí)現(xiàn)通訊錄(文件版)

    學(xué)習(xí)完C語(yǔ)言的文件讀寫,我們又可以將通訊錄增加以下功能: 1.當(dāng)退出通訊錄的時(shí)候,把已增加的聯(lián)系人信息寫到文件中。 2.當(dāng)通訊錄初始化的時(shí)候,加載(讀取)文件里的信息到通訊錄 ——(直接使用打印函數(shù)可以顯示在屏幕上) 分析: 當(dāng)我們退出通訊錄的時(shí)候要實(shí)現(xiàn)通訊錄

    2024年02月01日
    瀏覽(21)
  • C語(yǔ)言——通訊錄詳解(文件版)

    C語(yǔ)言——通訊錄詳解(文件版)

    我們已經(jīng)掌握了通訊錄的靜態(tài)版和動(dòng)態(tài)版,下面我們將學(xué)習(xí)通訊錄的文件版。學(xué)習(xí)了文件版,我們就不用擔(dān)心退出程序后,已經(jīng)添加的聯(lián)系人清空了。在以前的通訊錄(通訊錄靜態(tài)版、通訊錄動(dòng)態(tài)版)基礎(chǔ)上,我們?cè)谕瓿蓛蓚€(gè)目標(biāo)就可以實(shí)現(xiàn)通訊錄文件版。 目標(biāo): 通訊錄退

    2024年02月09日
    瀏覽(23)
  • c語(yǔ)言:通訊錄管理系統(tǒng)(文件版本)

    c語(yǔ)言:通訊錄管理系統(tǒng)(文件版本)

    前言: 本通訊錄管理系統(tǒng)一共三個(gè)版本,除此文章以外還有如下倆個(gè)版本,大家可以根據(jù)需求自?。?基礎(chǔ)增刪查改功能版本 :c語(yǔ)言:通訊錄管理系統(tǒng)(增刪查改)-CSDN博客 動(dòng)態(tài)分配內(nèi)存版本 :c語(yǔ)言:通訊錄管理系統(tǒng)(動(dòng)態(tài)分配內(nèi)存版)-CSDN博客 ? ? ? ? 本文是在基礎(chǔ)的通

    2024年02月07日
    瀏覽(90)
  • 【C語(yǔ)言】——通訊錄(靜態(tài)-動(dòng)態(tài)增長(zhǎng)-文件儲(chǔ)存)

    【C語(yǔ)言】——通訊錄(靜態(tài)-動(dòng)態(tài)增長(zhǎng)-文件儲(chǔ)存)

    ? 目錄 前言: 一:整體框架 關(guān)于通訊錄結(jié)構(gòu)體的創(chuàng)建? 二:通訊錄的功能實(shí)現(xiàn)(靜態(tài)) 2.1初始化通訊錄 2.2增加聯(lián)系人 2.3打印通訊錄 2.4刪除聯(lián)系人 ?2.5?查找聯(lián)系人 2.6修改聯(lián)系人? 2.7排序聯(lián)系人 三:通訊錄優(yōu)化——?jiǎng)討B(tài)內(nèi)存 ?3.1通訊錄的創(chuàng)建 3.2初始化通訊錄? 3.3增加聯(lián)系

    2024年02月07日
    瀏覽(20)
  • 【C語(yǔ)言】通訊錄3.0 (文件存儲(chǔ)版)

    【C語(yǔ)言】通訊錄3.0 (文件存儲(chǔ)版)

    通訊錄是一種記錄聯(lián)系人信息的工具,包括姓名、電話號(hào)碼、電子郵件地址、住址等。 文章的一二三章均于上一篇相同,可以直接看第四章改造內(nèi)容。 此通訊錄是基于通訊錄2.0(動(dòng)態(tài)增長(zhǎng)版)的基礎(chǔ)上進(jìn)行增加文件操作功能,請(qǐng)先看系列文章第二篇,再看本篇博客。 ******

    2024年02月14日
    瀏覽(20)
  • C語(yǔ)言小項(xiàng)目——通訊錄高階(文件管理版)

    C語(yǔ)言小項(xiàng)目——通訊錄高階(文件管理版)

    通訊錄初階: 點(diǎn)這里 通訊錄中階: 點(diǎn)這里 contact.c test.c contact.c contact.h

    2024年02月17日
    瀏覽(21)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包