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

C語言實(shí)現(xiàn)靜態(tài)版通訊錄的示例代碼

 更新時(shí)間:2022年08月11日 15:45:43   作者:摸魚王胖嘟嘟  
這篇文章主要為大家詳細(xì)介紹了如何利用C語言實(shí)現(xiàn)一個(gè)簡單的靜態(tài)版通訊錄,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下

前言

大家好~今天要實(shí)現(xiàn)一個(gè)非常有意思的東西–通訊錄。

通訊錄需求分析

為了實(shí)現(xiàn)通訊錄管理系統(tǒng),為此,要保證實(shí)現(xiàn)以下的功能:

能夠存放1000個(gè)聯(lián)系人的信息、每個(gè)人的信息包含:名字、年齡、性別、電話、地址、除此之外,還是實(shí)現(xiàn):增加人的信息、刪除人的信息、修改指定人的信息、查找指定人的信息、清空聯(lián)系人的信息、顯示聯(lián)系人的信息、排序通訊錄的信息.

功能介紹

1.增加聯(lián)系人信息

2.刪除聯(lián)系人信息

3.查找聯(lián)系人信息

4.修改聯(lián)系人信息

5.顯示聯(lián)系人信息

6.排序聯(lián)系人信息

7.清空聯(lián)系人信息

實(shí)現(xiàn)思路

靜態(tài)版本的通訊錄首先聲明一個(gè)結(jié)構(gòu)體類型(struct PeoInfo)用來描述一個(gè)人的聯(lián)系人的各種信息;

然后再聲明一個(gè)結(jié)構(gòu)體類型(struct Contact)用來描述通訊錄,成員使用數(shù)組開辟1000個(gè)聯(lián)系人的內(nèi)存空間實(shí)現(xiàn)通訊錄,數(shù)組的類型為struct PeoInfo
最后就是對存放聯(lián)系人信息數(shù)組的一系列訪問操作,封裝各個(gè)函數(shù)實(shí)現(xiàn)各部分功能!

代碼實(shí)現(xiàn)

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

void menu()
{
	printf("*******************************\n");
	printf("***** 1.add      2.del    *****\n");
	printf("***** 3.search   4.modify *****\n");
	printf("***** 5.sort     6.print  *****\n");
	printf("***** 7.clear    0.exit   *****\n");
	printf("*******************************\n");
}

enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT,
	CLEAR
};

int main()
{
	int input = 0;
	//創(chuàng)建通訊錄,結(jié)構(gòu)體類型在頭文件中定義的,所以要引頭文件,MAX的定義在頭文件或者該源文件內(nèi)定義都是可以的,因?yàn)榘祟^文件
	//但是如果把數(shù)組和數(shù)組元素個(gè)數(shù)sz定義成一個(gè)結(jié)構(gòu)體,就要去頭文件中定義,那邊就需要MAX,如果MAX在test.c中定義的話,contact.h中就會報(bào)錯(cuò)
	//既然這樣,就直接把MAX定義在contact.h中去,即可。
	
	//PeoInfo data[MAX] = { 0 };//不完全初始化
	//通訊錄中當(dāng)前有幾個(gè)元素:
	//int sz = 0;

	//創(chuàng)建通訊錄
	Contact con;
	//con就是通訊錄,也可以直接進(jìn)行初始化,但是為了更好的體現(xiàn)模塊化,就對初始化通訊錄封裝一個(gè)函數(shù)。
   //如果想把其中的一部分初始化為0,就必須使用函數(shù)來做了。	
   //初始化通訊錄
	InitContact(&con);
	//初始化通訊錄的時(shí)候要對通訊錄中的內(nèi)容進(jìn)行修改,如果傳值調(diào)用的話,不會修改實(shí)參中的內(nèi)容,而且效率低,所以要傳址調(diào)用。

	do
	{
		menu();
		printf("請選擇:>");
		scanf("%d", &input);
		switch (input)
		{
			case ADD:
				//增加聯(lián)系人信息
				AddContact(&con);
				//要把數(shù)組和數(shù)組元素個(gè)數(shù)都進(jìn)行傳參,會比較麻煩,把兩者定義成一個(gè)新的結(jié)構(gòu)體
				break;
			case DEL:
				//刪除聯(lián)系人信息
				DelContact(&con);
				break;
			case SEARCH:
				//查找聯(lián)系人信息
				SearchContact(&con);
				break;
			case MODIFY:
				//修改聯(lián)系人信息
				ModifyContact(&con);
				break;
			case SORT:
				//排序聯(lián)系人信息
				SortContact(&con);
				break;
			case PRINT:
				//雖然只是打印信息,不會改變實(shí)參的信息,但是考慮的效率的話,還是使用傳址調(diào)用比較好,結(jié)構(gòu)體傳參最好傳地址。
				PrintContact(&con);
				break;
			case CLEAR:
				//清空所有聯(lián)系人信息
				ClearContact(&con);
				break;
			case EXIT:
				printf("退出通訊錄\n");
				break;
			default:
				printf("選擇錯(cuò)誤,請重新選擇:>");
				break;
		}
	} while (input);
	//如果有同名的,一律操作第一個(gè)出現(xiàn)該名字的那個(gè)成員,因?yàn)楸闅v是從前往后遍歷的,在這里不考慮同名的情況。
	return 0;
}

contact.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"

//初始化通訊錄
void InitContact(Contact* pc)
{
	assert(pc);
	//內(nèi)存設(shè)置函數(shù) — memset() - 內(nèi)存設(shè)置
	(pc->sz) = 0;
	memset(pc->data, 0, sizeof(pc->data));
	//pc->data 就相當(dāng)于找到了整個(gè)數(shù)組,而整個(gè)數(shù)組可以使用數(shù)組名來表示,所以可以使用data來表示整個(gè)數(shù)組
	//即:pc->data  ===  data   ,,,數(shù)組名在第一個(gè)參數(shù)中沒有&和sizeof,代表的是數(shù)組首元素的地址,第二個(gè)參數(shù)是把
	//每一個(gè)字節(jié)都設(shè)置成0,十進(jìn)制的0,轉(zhuǎn)為十六進(jìn)制表示形式就是0x 00,,pc->data === data,數(shù)組名單獨(dú)放在
	//sizeof中,代表的是整個(gè)數(shù)組,計(jì)算的是整個(gè)數(shù)組的大小,單位是字節(jié)也可以寫成:MAX * sizeof(Contact)
}

//增加聯(lián)系人
void AddContact(Contact* pc) 
{
	assert(pc);
	if (pc->sz == MAX)
	{
		printf("通訊錄已滿、無法添加新的聯(lián)系人\n");
		return; //返回類型是void,也可以寫return,但是不能帶出去返回值。
	}
	//通訊錄未滿,可以添加新成員,增加一個(gè)人的信息
	printf("請輸入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("請輸入年齡:>");
	scanf("%d", &(pc->data[pc->sz].age)); 
	printf("請輸入性別:>");
	scanf("%s", pc->data[pc->sz].sex); 
	printf("請輸入電話:>");
	scanf("%s", pc->data[pc->sz].tele); 
	printf("請輸入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	pc->sz++;
	printf("增加聯(lián)系人成功\n");
	//在這里,[ ]的優(yōu)先級等于->,,但是,data和[ ]是不可以先進(jìn)行結(jié)合的,因?yàn)?,這是在一個(gè)調(diào)用函數(shù)中,形參那部分接受到的只有指針變量pc
	//也就是說,如果后兩者進(jìn)行結(jié)合的話,系統(tǒng)根本就不知道data是什么東西,所以它結(jié)合出來是錯(cuò)誤的,即,即使[ ]的優(yōu)先級等于->,但是后兩者不能
	//進(jìn)行結(jié)合會出錯(cuò),又因結(jié)合性從左到右所以,還是先讓data和->進(jìn)行結(jié)合,即先進(jìn)行pc->data的操作,所以在結(jié)構(gòu)體成員變量中找到了整個(gè)數(shù)組data
	//而整個(gè)數(shù)組可以使用數(shù)組名進(jìn)行表示,知道了數(shù)組名就可以再通過下標(biāo)對數(shù)組元素進(jìn)行訪問了。

}

//顯示聯(lián)系人信息
void PrintContact(const Contact* pc)
{
	assert(pc);
	//打印出所有人的信息,即sz個(gè)人的信息。
	int i = 0;
	//打印標(biāo)題
	printf("%-10s\t%-5s\t%-5s\t%-12s\t%-50s\n", "名字", "年齡", "性別", "電話", "地址");// \t === tab
	//打印數(shù)據(jù)
	for (i = 0; i < (pc->sz); i++)
	{
		printf("%-10s\t%-5d\t%-5s\t%-12s\t%-50s\n", pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
	}

	//通過pc->data[i]找到數(shù)組data中下標(biāo)為i的元素,即找到了一個(gè)變量,再通過點(diǎn)來訪問該人的姓名等,,由于姓名是一個(gè)數(shù)組,找到的就是整個(gè)數(shù)組,整個(gè)
	//數(shù)組又可以使用數(shù)組名來表示,即:pc->data[i].name === name ,沒有sizeof和&,代表數(shù)組首元素的地址,再通過%s進(jìn)行打印字符串,除了年齡是一個(gè)變量,其他的都是數(shù)組,和name同理。

}


//因?yàn)樵摵瘮?shù)只是為了滿足刪除,查找,修改功能的需要,而這三個(gè)功能對應(yīng)的函數(shù)的實(shí)現(xiàn)都會在該 .c 文件內(nèi)進(jìn)行實(shí)現(xiàn),所以,對于這個(gè)函數(shù)
//只需要在該 .c 文件內(nèi)執(zhí)行即可,不許要暴露給別人,,所以,在前面加上static,就固定了該函數(shù)只在目前所在的 .c 文件內(nèi)進(jìn)行工作即可。
//static 修飾函數(shù),本質(zhì)上是改變了函數(shù)的鏈接屬性。
static int Find_By_Name(const Contact* pc, char name[])//數(shù)組形式接收,數(shù)組形式接受的話就不考慮const的使用了。
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)//相等
	//第一個(gè)參數(shù)先找到整個(gè)數(shù)組,可以使用數(shù)組名來表示,不是特例,即代表數(shù)組首元素的地址,第二個(gè)參數(shù)也不是特例,也是數(shù)組首元素的地址。
		{
			return i;
		}
	}
	return -1;
}
//刪除聯(lián)系人信息
void DelContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	if (pc->sz == 0)
	{
		printf("通訊錄為空、不可以再進(jìn)行刪除操作\n");
		return;
	}
	//刪除某個(gè)人的信息
	printf("請輸入要?jiǎng)h除人員的姓名:>");
	scanf("%s", name);
	//1、查找要?jiǎng)h除的人
	//不管是刪除還是查找還是修改,都需要使用到查找這個(gè)功能,所以就單獨(dú)把該功能拿出來封裝一個(gè)函數(shù);
	int pos = Find_By_Name(pc, name);//一級指針傳參和數(shù)組名傳參
	//不存在該人
	if (pos == -1)
	{
		printf("要?jiǎng)h除的人員不存在\n");
		return;
	}
	//2、存在該人員,要進(jìn)行刪除,把數(shù)組該位置上的人員刪除之后,數(shù)組后面的人員依次往前移動一個(gè)位置。
	int i = 0;
	for (i = pos; i < (pc->sz - 1); i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	//pc->sz -= 1;
	pc->sz--;
	//如果想刪除最后一個(gè),是刪除不掉的,因?yàn)?,如?0個(gè)元素,最后一個(gè)下標(biāo)為9,判斷條件是<9,,所以不進(jìn)入循環(huán),但是
	//循環(huán)后面還有pc->sz--,,成員個(gè)數(shù)少了1,再顯示人員信息的時(shí)候,訪問不到最后一個(gè)人員了,,即使沒刪掉,也訪問不掉,
	//最后的結(jié)果和刪掉最后一個(gè)人員的效果是一樣的。
	//假設(shè)MAX=3,把最后一個(gè)元素刪除,本質(zhì)上并沒有從數(shù)組中刪除掉,而是因?yàn)閟z減1,打印的時(shí)候不訪問最后一個(gè)元素,看起來和刪除的效果是一樣的,現(xiàn)在由于
	//看起來刪了,本質(zhì)上沒刪去,如果再添加新元素會怎么樣呢?
	//因?yàn)閯h除完之后,元素個(gè)數(shù)就會減去1,由原來的3變成了2,,再添加新元素的時(shí)候,就會直接把新元素的內(nèi)容放在下標(biāo)為2的位置上,這樣的話,即使之前的最后一個(gè)元素
	//沒刪去,也會被新的元素覆蓋掉,添加完之后元素個(gè)數(shù)加1,再打印出來就是添加成員后的信息,是對的。
	printf("刪除聯(lián)系人員成功\n");
}

//查找聯(lián)系人信息
void SearchContact(const Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	//查找某個(gè)人的信息
	printf("請輸入要查找人員的姓名:>");
	scanf("%s", name);
	int pos = Find_By_Name(pc, name);
	//要查找的人員不存在
	if (pos == -1)
	{
		printf("要查找的人員不存在\n");
		return;
	}
	
	//2、存在該人員,找出之后并打印出該成員的信息
	//打印標(biāo)題
	printf("%-10s\t%-5s\t%-5s\t%-12s\t%-50s\n", "名字", "年齡", "性別", "電話", "地址");// \t === tab
	//打印數(shù)據(jù)
	printf("%-10s\t%-5d\t%-5s\t%-12s\t%-50s\n",
		pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);

}

//修改指定聯(lián)系人的信息
void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	//修改某個(gè)人的信息
	printf("請輸入要修改人員的姓名:>");
	scanf("%s", name);
	int pos = Find_By_Name(pc, name);
	//要修改的人員不存在
	if (pos == -1)
	{
		printf("要修改的人員不存在\n");
		return;
	}
	else
	{
		printf("請輸入修改后人員的名字:>");
		scanf("%s", pc->data[pos].name);
		printf("請輸入修改后人員的年齡:>");
		scanf("%d", &(pc->data[pos].age));
		printf("請輸入修改后人員的性別:>");
		scanf("%s", pc->data[pos].sex);
		printf("請輸入修改后人員的地址:>");
		scanf("%s", pc->data[pos].addr);
		printf("請輸入修改后人員的電話:>");
		scanf("%s", pc->data[pos].tele);
		printf("修改聯(lián)系人員信息成功\n");
	}
}


int cmp_Per_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}


void SortContact(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_Per_by_name);
	PrintContact(pc);
}


void ClearContact(Contact* pc)
{
	assert(pc);
	InitContact(pc);
	printf("清空成功\n");
}

contact.h

#pragma once


//類型的定義、通訊錄中要放1000個(gè)人的信息,
//每個(gè)人的信息要包括名字、年齡、性別、電話、地址等,
//所以要定義成一個(gè)結(jié)構(gòu)體,而該結(jié)構(gòu)體要在兩個(gè)源文件中使用,
//所以最好定義在頭文件中,這樣只需要包含一下頭文件就可以頻繁的使用了

//頭文件的包含
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>

//定義結(jié)構(gòu)體類型
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
#define MAX 1000

typedef struct PeoInfo
{
	//char name[20];
	//直接寫成固定值就寫死了,不方便后期的修改,
	//所以使用#define 來定義一個(gè)常量,后期直接改變#define中的內(nèi)容即可。
	char name[MAX_NAME];
	char sex[MAX_SEX];
	int age;
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;//使用typedef對結(jié)構(gòu)體類型重命名為:PeoInfo


//結(jié)構(gòu)體嵌套
//通訊錄
typedef struct Contact//重命名
{
	PeoInfo data[MAX];//存放添加進(jìn)去的聯(lián)系人的信息
	int sz;//記錄當(dāng)前通訊錄中有效信息的個(gè)數(shù)
}Contact;

//初始化通訊錄
void InitContact(Contact* pc);

//增加聯(lián)系人
void AddContact(Contact* pc);

//打印信息
void PrintContact(const Contact* pc);

//刪除聯(lián)系人信息
void DelContact(Contact* pc);

//查找聯(lián)系人信息
void SearchContact(const Contact* pc);

//修改指定聯(lián)系人的信息
void ModifyContact(Contact* pc);

//排序聯(lián)系人的信息
void SortContact(Contact* pc);

//清空所有聯(lián)系人的信息
void ClearContact(Contact* pc);

效果圖

以上就是C語言實(shí)現(xiàn)靜態(tài)版通訊錄的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于C語言靜態(tài)通訊錄的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • c語言中exit和return的區(qū)別點(diǎn)總結(jié)

    c語言中exit和return的區(qū)別點(diǎn)總結(jié)

    小編今天給大家整理了關(guān)于c語言中exit和return的不同點(diǎn)及相關(guān)基礎(chǔ)知識點(diǎn),有興趣的朋友們可以跟著學(xué)習(xí)下。
    2021-10-10
  • C語言實(shí)現(xiàn)魔方比賽管理系統(tǒng)

    C語言實(shí)現(xiàn)魔方比賽管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)魔方比賽管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C語言中send()函數(shù)和sendto()函數(shù)的使用方法

    C語言中send()函數(shù)和sendto()函數(shù)的使用方法

    這篇文章主要介紹了C語言中send()函數(shù)和sendto()函數(shù)的使用方法,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C++ QgraphicsScene類案例詳解

    C++ QgraphicsScene類案例詳解

    這篇文章主要介紹了C++ QgraphicsScene類案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C語言實(shí)現(xiàn)字符串操作函數(shù)的實(shí)例

    C語言實(shí)現(xiàn)字符串操作函數(shù)的實(shí)例

    這篇文章主要介紹了C語言實(shí)現(xiàn)字符串操作函數(shù)的實(shí)例的相關(guān)資料,開發(fā)程序的時(shí)候經(jīng)常使用到一些字符串函數(shù),例如求字符串長度,拷貝字符串……,需要的朋友可以參考下
    2017-08-08
  • C語言中的結(jié)構(gòu)體的入門學(xué)習(xí)教程

    C語言中的結(jié)構(gòu)體的入門學(xué)習(xí)教程

    這篇文章主要介紹了C語言中的結(jié)構(gòu)體的入門學(xué)習(xí)教程,以struct語句定義的結(jié)構(gòu)體是C語言編程中的重要基礎(chǔ),需要的朋友可以參考下
    2015-12-12
  • 使用c語言輕松實(shí)現(xiàn)動態(tài)內(nèi)存管

    使用c語言輕松實(shí)現(xiàn)動態(tài)內(nèi)存管

    這篇文章主要介紹了使用c語言輕松實(shí)現(xiàn)動態(tài)內(nèi)存管,本文章內(nèi)容詳細(xì),具有很好的參考價(jià)值,希望對大家有所幫助,需要的朋友可以參考下
    2023-01-01
  • C語言中printf的兩種輸出對齊方式

    C語言中printf的兩種輸出對齊方式

    C語言中左對齊是C語言的默認(rèn)輸出方式,右對齊是一種特殊的輸出方式,左對齊和右對齊都對應(yīng)著一個(gè)已知的輸出寬度,輸出的字符串根據(jù)字符串的長度在寬度上進(jìn)行補(bǔ)充,補(bǔ)充字符是空格,在使用printf函數(shù)輸出時(shí),需要在格式字符串中使用%-*s和%*s的格式來分別表示
    2024-02-02
  • windows系統(tǒng)下C++調(diào)用matlab程序的方法詳解

    windows系統(tǒng)下C++調(diào)用matlab程序的方法詳解

    這篇文章主要給大家介紹了關(guān)于在windows系統(tǒng)下C++調(diào)用matlab程序的方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08
  • 基于C語言實(shí)現(xiàn)簡單的五子棋游戲

    基于C語言實(shí)現(xiàn)簡單的五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了基于C語言實(shí)現(xiàn)簡單的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評論