【c】在C语言中使用顺序表了实现一个通讯录,实现对联系人信息的增删改查(主要用到动态开辟内存,文件读写,结构体指针)

头文件

#pragma once
enum menu
{
	EXIT,
	ADD,
	DEL,
	MODIFY,
	SEARCH,
	SORT,
	EMPTY,
	SHOW
};
#define NAME_SIZE 30
#define SEX_SIZE 5
#define ADDR_SIZE 100
#define TEL_SIZE 20
#define MAX 3
typedef struct student
{
	char name[NAME_SIZE];
	char sex[SEX_SIZE];
	int age;
	char addr[ADDR_SIZE];
	char tel[TEL_SIZE];
}Student;
typedef struct MailList
{
	//Student data[MAX];
	Student *data;//在通信录里建立一个指向一条信息的结构体指针
	int capacity;//当前最大容量决定是多少就赋值多少
	int size;//对data指针进行地址偏移
}MailList;//指针引用指针是->,指针引用变量是.
int IncCapacity(MailList *ml);//传指针
void LoadData(MailList *ml);
void InitMailList(MailList *ml);
void AddInfo(MailList *ml);
void ShowInfo(MailList *ml);
void SortInfo(MailList *ml);
void SaveMailList(MailList *ml);
void DestoryMaillist(MailList *ml);
void SearchInfo(MailList *ml, char* find);
void SearchInfo(MailList* ml, char* find);
void DelInfo(MailList* ml);
void ModifyInfo(MailList* ml);
void showsearchdata(MailList* ml);

源文件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include "maillist.h"
//maillist.c
void menu()
{
	printf("******************************\n");
	printf("**** 1.add      2.del     ****\n");
	printf("**** 3.modify   4.search  ****\n");
	printf("**** 5.sort     6.empty   ****\n");
	printf("**** 7.show     0.exit    ****\n");
	printf("******************************\n");

}


void Test()

{
	int input = 0;
	MailList ml;//定义一个通讯录
	char find[20]="0";
	InitMailList(&ml);//传地址,对它直接进行操作
	while (1)
	{
		menu();
		printf("请输入要实现的功能\n");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT:
			DestoryMaillist(&ml);
			printf("退出!\n");
			return;
		case ADD:
			AddInfo(&ml);
			break;
		case DEL:
			DelInfo(&ml);
			//删除
			break;
		case MODIFY:
			ModifyInfo(&ml);
			//修改
			break;
		case SEARCH:
			printf("请输入要查找的字符串或者字符串\n");
			scanf("%s", &find);
			SearchInfo(&ml,find);
			break;
		case SORT:
			SortInfo(&ml);
			break;
		case EMPTY:
			//EmptyInfo(&ml);
			break;
		case SHOW:
			ShowInfo(&ml);
			break;
		default:
			printf("输入分支不存在,请重新输入\n");
		}
	}
}
int main()
{
	Test();
	system("pause");
	return 0;
}
#include "maillist.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
//func.c
int save[100] = { 0 };
int IncCapacity(MailList *ml)//ml指向的是通讯录,通讯录里有消息
{
	
	//给通讯录开内存
	assert(ml != NULL);
	Student *temp = NULL;//这是一条信息

	ml->capacity = ml->capacity + MAX;
	temp = (Student*)realloc(ml->data, sizeof(Student)*ml->capacity);
	/*data是消息的指针
	有一个Student的结构体,我们的通讯录指针data指向这个结构体,一个Student结构体在内存中
	所占的空间是确定的,所以就可以用取偏移量的方式进行访问,来改变data的指向*/
	if (temp != NULL)
	{
		ml->data = temp;
		return 0;
	}
	return 1;
}
void LoadData(MailList *ml)
{
	//加载信息
	//int i = 0;
	FILE *rp = fopen("F:\\bite learn\\MailList.txt", "rb");

	while (fread(&ml->data[ml->size], sizeof(Student), 1, rp))
	{
		ml->size++;
		if (ml->size >= ml->capacity)
		{
			IncCapacity(ml);
		}

	}
	fclose(rp);
	rp = NULL;
}
void InitMailList(MailList *ml)
{
	assert(ml != NULL);
	ml->capacity = MAX;
	ml->size = 0;
	ml->data = (Student*)malloc(sizeof(Student)*ml->capacity);
	memset(ml->data, 0, MAX * sizeof(Student));//mi.data是一个 指针
	LoadData(ml);

}

void AddInfo(MailList *ml)
{
	assert(ml != NULL);
	/*if (ml->size >= MAX)
	{
		printf("通讯录已满不能插入\n");
		return;
	}*/
	if (ml->size >= ml->capacity && IncCapacity(ml))
	{
		//这个地方判断的优先级高于逻辑与,而且与运算是短路求值问题
		//第一个是0后第二个表达式就不计算,所以不会每次都开辟空间 
		//只有当前面是1的时候才会开辟空间
		printf("通讯录已满不能插入\n");
		return;
	}
	printf("请输入姓名 性别 年龄 住址 电话\n");
	scanf("%s", ml->data[ml->size].name);//是一个数组,名字就是地址
	scanf("%s", ml->data[ml->size].sex);
	scanf("%d", &ml->data[ml->size].age);
	scanf("%s", ml->data[ml->size].tel);
	scanf("%s", ml->data[ml->size].addr);

	++ml->size;
}
void ShowInfo(MailList *ml)
{
	assert(ml != NULL);
	printf("%3s %9s %11s %10s %9s %14s", "编号","姓名", "性别", "年龄", "电话", "住址\n");
	int i = 0;
	for (i = 0; i < ml->size; ++i)
	{
		printf("%d ", i);
	     printf("%12s", ml->data[i].name);
	     printf("%12s", ml->data[i].sex);
	     printf("%9d", ml->data[i].age);
	     printf("%12s", ml->data[i].tel);
	     printf("%12s\n", ml->data[i].addr);
	}
}
void SortInfo(MailList *ml)
{
	assert(ml != NULL);

	int i = 0;
	int j = 0;
	Student tmp;
	for (i = 0; i < ml->size; ++i)
	{
		for (j = 0; j < ml->size - i - 1; ++j)
		{
			if (strcmp(ml->data[j].name, ml->data[j + 1].name) > 0)//strcmp的对比方式是两个的第一个字符开始对比
				//直到找到不同大的字符返回
			{
				tmp = ml->data[j];
				ml->data[j] = ml->data[j + 1];
				ml->data[j + 1] = tmp;
			}
		}
	}
}
void SaveMailList(MailList *ml)
{
	int i = 0;
	FILE *fp = fopen("F:\\bite learn\\MailList.txt", "wb");
	for (i = 0; i < ml->size; ++i)
	{
		fwrite(&ml->data[i], sizeof(Student), 1, fp);
	}
	//data是指向student结构体的指针啊哈哈

	fclose(fp);
	fp = NULL;
}
void DestoryMaillist(MailList *ml)
{
	assert(ml != NULL);
	SaveMailList(ml);
	free(ml->data);
	ml->data = NULL;
	ml->capacity = ml->size = NULL;

}
void showsearchdata(MailList* ml)
{
	if (save[0])
	{
		printf("共找到%d条信息\n", save[0]);
		printf("%3s %10s %9s %5s %10s %12s", "编号","姓名", "性别", "年龄", "电话", "住址\n");
		int i = 0;
		for (i = 1; i <= save[0]; ++i)
		{
			printf("%d ", save[i]);
			printf("%15s", ml->data[save[i]].name);
			printf("%5s", ml->data[save[i]].sex);
			printf("%7d", ml->data[save[i]].age);
			printf("%10s", ml->data[save[i]].tel);
			printf("%12s\n", ml->data[save[i]].addr);
		}
	}
	else
	{
		printf("找到0条信息\n");
	}

}
void SearchInfo(MailList* ml,char* find)
{
	
	char *ret;
	char age[4] = "0";
	//sprintf(age,"%d",g_allMsg[i].age);返回值是strlen()
	//scanf()的用法
	//sprintf()和ctrcpy有什么区别?
	int i=0;
	int j = 1;
	int flag = 0;
	int count = 0;
	/*for (;j<100;++j)
	{
		save[j] = 0;
	}*/
	for (i = 0; i < ml->size; ++i)
	{
		/*printf("%d", ml->size);
		printf("%s", find);*/
		flag = 1;
		do
		{
			ret = strstr(ml->data[i].name, find);
			if (ret)
			{
				++count;
				break;
			}
			ret = strstr(ml->data[i].addr, find);
			if (ret)
			{
				++count;
				break;
			}
			ret = strstr(ml->data[i].sex, find);
			if (ret)
			{
				++count;
				break;
			}
			sprintf(age, "%d", ml->data[i].age);//把数字转化成字符串了
			ret = strstr(age, find);
			if (ret)
			{
				++count;
				break;
			}
			ret = strstr(ml->data[i].tel, find);
			if (ret)
			{ 
				++count;
				break;
			}
			flag = 0;
		} while (0);//goto的解决方案do while(0)
		if (flag)
		{
			 
			save[j] = i;
			++j;
		}
	}
	if (count)
	{
		 
		save[0] = count;
	}
	/*else
	{
		printf("找到0条信息\n");
	}*/

	showsearchdata(ml);
	
}
 
void DelInfo(MailList* ml)
{
	int i = 0;
	char del[25] = "0";
	int bianhao = 0;
	printf("请输入要删除的信息\n");
	scanf("%s", &del);
	SearchInfo(ml, del);
	while (1)
	{
		printf("请选择删除的联系人编号\n");
		scanf("%d", &bianhao);
		if (bianhao > ml->size)
		{
			printf("请重新输入\n");
		}
		else
		{
			break;
		}

	}
	
    for (i=bianhao;i<ml->size;++i)
    {
    	ml->data[i] = ml->data[i+1];
    }
	ml->size--;
	printf("删除成功\n");
}
//void ModifyoneInfo(MailList* ml, int bianhao, int leixing)
//{
//
//}
void ModifyInfo(MailList* ml)
{
	int leixing = 0;
	char del[25] = "0";
	int bianhao = 0;
	ShowInfo(ml);
	printf("请选择要修改的信息对应的编号\n");
	scanf("%d", &bianhao);
	printf("请输入要修改的信息类型\n");
	printf("1.姓名 2.电话 3.住址\n");
	scanf("%d", &leixing);
	printf("请输入要更新的信息\n");
	scanf("%s", &del);
	/*printf("请输入\n");
	scanf("%s", &del);*/
	//SearchInfo(ml, del);
	
if (1==leixing)
{
	strcpy(ml->data[bianhao].name, del);
} 
else if(2== leixing)
{
	strcpy(ml->data[bianhao].tel, del);
}
else if(3== leixing)
{
	strcpy(ml->data[bianhao].addr, del);
}
printf("修改成功\n");
}

在这里笔者分享一点做一个小小的项目的心得:首先应该清楚要实现的功能有哪些,将它们分解成单个函数去实现。

再次应该尽可能的做到一个函数只做一件事,这样可以大大增强代码的复用性。最后应该学会分文件去写代码,这样可以很方便的找到你想要找的内容,伴随着项目功能越来越多这样做的优势会更加明显。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值