【C语言】以通讯录为例理解宿舍管理系统,图书管理系统完成C语言期末作业。源代码见文章末尾

学完结构体来尝试写一个通讯录吧,以通讯录为例带你理解图书管理系统,宿舍管理系统解决C语言期末作业,需要基础的结构体与指针知识,基础的动态内存知识以及基础的文件操作知识。
源代码见文章末尾
在这里插入图片描述

1.理清思路

1.首先一个通讯录需要由联系人信息和联系人数量组成而联系人信息则由姓名,性别,电话号码,住址等组成

2.通讯录的功能需要实现增删查改,即增加联系人,删除联系人,更改联系人信息,展示通讯录列表,查询联系人

3.我们需要在程序结束之后将我们内存中的内容存储到硬盘之中,在程序开始运行之后先将之前存储的内容加载到内存之中

2. 通讯录

1.联系人信息

通讯录中存储的是联系人信息和联系人数量以及通讯录当前容量,
而联系人存储的是联系人信息所以它们是两个结构体

为了通过通讯录能够找到联系人信息我们通讯录结构体中放的是指向联系人信息的指针

typedef struct information
{
	char name[10];
	int age;
	char sex[16];
	char phone[20];
	char address[10];
}infor;
typedef struct contactnumber
{
	int count;
	int sz;
	infor* con;
}contact;

2.通讯录的功能

我们首先想好我们要实现通讯录需要实现的功能,留好接口方便后边的实现

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct information
{
	char name[10];
	int age;
	char sex[16];
	char phone[20];
	char address[10];
}infor;
typedef struct contactnumber
{
	int capacity;
	int sz;
	infor* con;
}contact;
void init_contact(contact* pt);//初始化通讯录
void add_contact(contact* pt);//添加联系人
void print_contact(contact* pt);//显示联系人
void dilat_contact(contact* pt);//通讯录扩容
void find_contact(contact* pt);//查找方式选择
int select(const char* test, contact* pt);//查找联系人
void del_contact(contact* pt);//删除联系人
void change_contact(contact* pt);//更改联系人信息
void destory_contact(contact* pt);

3.初始化通讯录

初始化通讯录时我们需要先创建一个通讯录当然这个在主函数中创建

int mian()
{
  	contact ptr;
	init_contact(&ptr);
}

初始化通讯录函数

void init_contact(contact* pt)
{
	assert(pt);
	pt->sz = 3;
	pt->con = (infor*)calloc(pt->sz, sizeof(infor));
	assert(pt->con);
	pt->count = 0;
}

用calloc开辟的空间会初始化为0

4.扩容

注意这里我让他每增加一个人就扩容一次,这样扩容是十分不合理的,在实际编写过程中扩容是存在很大的损耗的
所以每次扩容一般会选择扩容一定合理的数量或者直接扩容原本的二倍。

void dilat_contact(contact* pt)
{
	pt->sz++;
	infor* ptc = (infor*)realloc(pt->con, sizeof(infor) * pt->sz);
	assert(ptc);
	pt->con = ptc;
	printf("扩容成功\n");
}

4.检查是否已满

写一个函数检查通讯录是否已满已满则进行扩容,每次增加之后都需要进行检查

void check_capacity(contact* ptr)
{
    if(ptyr->sz==ptr->capacity)
    {
        dilat_contact(contact* ptr);
    }
}

在这次程序编写中我将检查直接放在了增加联系人函数之中实现,并没有封装函数。

5.添加联系人

void add_contact(contact* pt)
{
	assert(pt);
	printf("请输入姓名:");
	scanf("%s", pt->con[pt->count].name);
	printf("请输入年龄:");
	scanf("%d", &pt->con[pt->count].age);
	printf("请输入性别:");
	scanf("%s", pt->con[pt->count].sex);
	printf("请输入电话号码:");
	scanf("%s", pt->con[pt->count].phone);
	printf("请输入地址:");
	scanf("%s", pt->con[pt->count].address);
	pt->count++;
	printf("添加成功\n");
	if (pt->capacity == pt->sz)
		dilat_contact(pt);
}

这里我将检查是否已满放在了这个函数末尾,并没有单独封装函数,这样写要注意当剩余空间为1时就要进行扩容。

6.显示所有联系人

void print_contact(contact* pt)
{
	if (pt == NULL)
	{
		perror("pt");
		return;
	}
	printf("%-5s   %-10s   %-5s   %-10s   %-20s   %-5s\n","编号", "姓名", "年龄", "性别", "电话号码", "地址");
	int i = 0;
	for (i = 0; i < pt->count; i++)
	{
		printf("%-5d  %-10s   %-5d   %-10s   %-20s   %-5s\n",i+1,
			pt->con[i].name,
			pt->con[i].age,
			pt->con[i].sex,
			pt->con[i].phone,
			pt->con[i].address);
	}
}

7.查找联系人

我们可以通过名字,住址或者手机号这些内容来进行查找

int select(const char* test, contact* pt)
{
	char na[20] = { 0 };
	int sun = 0;
	int i = 0;
	scanf("%s", &na);
	for (i = 0; i < pt->count; i++)
	{
		if (strcmp(&test[i], na) == 0)
		{
			sun++;
			printf("%-5s   %-10s   %-5s   %-10s   %-20s   %-5s\n", "编号", "姓名", "年龄", "性别", "电话号码", "地址");
			printf("编号%d: %-10s   %-5d   %-10s   %-20s   %-5s\n", i + 1
				, pt->con[i].name,
				pt->con[i].age,
				pt->con[i].sex,
				pt->con[i].phone,
				pt->con->address);
		}
	}
	printf("查找到%d位联系人\n", sun);
	return sun;
}
void find_contact(contact* pt)
{
	int sdd = 0;
	int sum = 0;
	int i = 0;
	printf("|  1.findname     2.findphone     3.findaddress  |\n");
	printf("请选择查找方式  1.姓名 2.手机号  3.住址>:");
	scanf("%d", &sdd);
	switch (sdd)
	{
	case 0:
		return;
	case 1:
		printf("请输入要查找的姓名:");
		sum = select(pt->con->name, pt);
		break;
	case 2:
		printf("输入要查找的电话号码:");
		sum = select(pt->con->phone, pt);
		break;
	case 3:
		printf("请输入要查找的住址:");
		sum = select(pt->con->address, pt);
		break;
	default:
		printf("请选择正确的选项\n");
		break;
	}
}

8.删除联系人

注意我们的通讯录中联系人是连续存放的,所以我们在删除一个联系人之后要将后面的全部往前挪一位
所以我们要删除哪一位直接将这一位往后的全部前挪一位,覆盖即可。

void del_contact(contact* pt)
{
	assert(pt);
	int a = 0;
	int i = 0;
	printf("请输入要删除的联系人编号,或输入0退出\n");
	scanf("%d", &a);
	if (a == 0)
		return;
	else if (a > pt->capacity)
		printf("编号不存在\n");
	for (i = a - 1; i < pt->count; i++)
	{
		pt->con[i] = pt->con[i + 1];
	}
	pt->capacity--;
	printf("删除成功\n");
}

9.更改联系人信息

void change_contact(contact* pt)
{
	int sc = 0;
	int sd = 0;
	int se = 0;
	char ch[20] = { 0 };
	printf("请输入要更改的联系人编号,或输入0退出");
	scanf("%d", &sc);
	if (sc == 0)
		return;
	printf("请输入要更改的内容|0.退出 1.姓名  2.年龄  3.性别?  4.电话号码   5.地址:	`");
	scanf("%d", &sd);
	printf("请输入更改后的信息\n");
	switch (sd)
	{
	case 0:
		break;
		case 1:
			scanf("%s",ch);
			strcpy(pt->con[sc-1].name, ch);
			printf("更改成功\n");
			break;
		case 2:
			scanf("%d", &se);
			pt->con->age = se;
			break;
		case 3:
			scanf("%s", ch);
			strcpy(pt->con[sc - 1].sex, ch);
			printf("更改成功\n");
			break;		
		case 4:
				scanf("%s", ch);
				strcpy(pt->con[sc - 1].phone, ch);
				printf("更改成功\n");
				break;		
		case 5:
					scanf("%s", ch);
					strcpy(pt->con[sc - 1].address, ch);
					printf("更改成功\n");
					break;
		default:
			printf("选择错误\n");
			break;
	}
}

10.通讯录的文件存储
当程序结束之后我们需要将存放在内存中数据存储到硬盘之中,存储之后我们将动态申请的内存释放

void destory_contact(contact* pt)
{
	int i = 0;
	FILE* fpt = fopen("contact.dat", "wb");
	assert(fpt);
	for (i = 0; i < pt->count; i++)
	{
		fwrite(&pt->con[i], sizeof(infor), 1, fpt);
	}
	fclose(fpt);
	free(pt->con);
	pt->con = NULL;
}

注意我们既然存储了数据就需要在初始化将存储的数据,写入到内存之中

void destory_contact(contact* pt)
{
	int i = 0;
	FILE* fpt = fopen("contact.dat", "wb");
	assert(fpt);
	for (i = 0; i < pt->count; i++)
	{
		fwrite(&pt->con[i], sizeof(infor), 1, fpt);
	}
	fclose(fpt);
	free(pt->con);
	pt->con = NULL;
}

将这个函数添加到初始化函数末尾即可
当我们将这些函数写完之后测试没有问题,我们可以写一个简易的菜单来方便我们测试和使用

类比联想图书管理系统和宿舍管理系统

宿舍管理系统中我们可以想到宿舍分为,宿舍楼,寝室这些内容
我们只需要创建一个结构体存放存放寝室人数,和信息即可

typedef struct personal_intformation//宿舍人员信息
{
	char name[10];//名字
	char specialty[20];//专业
}perinfor;
typedef struct dorm_num//宿舍成员信息
{
	int dorm_serial;//宿舍编号
	int sz;//人数
	perinfor* pf;//信息
}dorm_num;
int main()
{
	dorm_num dm[508];
}

注意宿舍数量比较固定的内容可以开辟静态的空间,而对宿舍人数这种可以静态开辟也可以动态开辟
当然这是针对一栋宿舍楼的情况,如果是针对全部宿舍楼可以再添加一个结构体

typedef struct personal_intformation//宿舍人员信息
{
	char name[10];//名字
	char specialty[20];//专业
}perinfor;
typedef struct dorm_num//宿舍成员信息
{
	int dorm_serial;//宿舍编号
	int sz;//人数
	perinfor pf[6];//信息
}dorm_num;
typedef struct dorm_bu
{
	int num_bu;//宿舍楼栋号
	int kz;//宿舍房间数量
	dorm_num dum[10];
}dorm_bu;
int main()
{
	dorm_bu dobu[19];//开辟一个可以存储19栋楼信息的空间
}

初始时注意宿舍数量这种内容一般比较固定我们可以开辟一个静态的空间来进行记录

当然在此处我仅仅是提供一个思路,具体的需求你应该根据具体的需要进行选择。
图书管理系统思路同上。

test.c文件

#include "contact.h"
void mean()
{
	printf("########################\n");
	printf("#   1.add      2.del   #\n");
	printf("#   3.find     4.print #\n");
	printf("#   5.change           #\n");
	printf("#                      #\n");
	printf("#                      #\n");
	printf("#   0.exit             #\n");
	printf("#                      #\n");
	printf("########################\n");
}
int main()
{
	int state = 0;
	contact ptr;
	init_contact(&ptr);
	int input = 0;
	do {
		mean();
		scanf("%d", &input);
		switch (input)
		{
		case 0:
			destory_contact(&ptr);
			break;
		case 1:
			add_contact(&ptr);
			break;
		case 2:
		{
			find_contact(&ptr);
			del_contact(&ptr);
			break;
		}
		case 3:
			find_contact(&ptr);
			break;
		case 4:
			print_contact(&ptr);
			break;
		case 5:
			find_contact(&ptr);
			change_contact(&ptr);
			break;
		default:
			printf("选择错误请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

contact.c文件

#include "contact.h"
void Load_contact(contact* pt)
{
	FILE* fpt = fopen("contact.dat", "rb");
	assert(fpt);
	infor tem = { 0 };

	//读取文件,存放到通讯录中
	while (fread(&tem, sizeof(infor), 1, fpt)==1)
	{
		if (pt->count == pt->sz)
		{
			dilat_contact(pt);
		}
		pt->con[pt->count] = tem;
		pt->count++;
	}

	fclose(fpt);
	fpt = NULL;
}
void init_contact(contact* pt)
{
	assert(pt);
	pt->sz = 3;
	pt->con = (infor*)calloc(pt->sz, sizeof(infor));
	assert(pt->con);
	pt->count = 0;
	Load_contact(pt);
}
void add_contact(contact* pt)
{
	assert(pt);
	printf("请输入姓名:");
	scanf("%s", pt->con[pt->count].name);
	printf("请输入年龄:");
	scanf("%d", &pt->con[pt->count].age);
	printf("请输入性别:");
	scanf("%s", pt->con[pt->count].sex);
	printf("请输入电话号码:");
	scanf("%s", pt->con[pt->count].phone);
	printf("请输入地址:");
	scanf("%s", pt->con[pt->count].address);
	pt->count++;
	printf("添加成功\n");
	if (pt->count == pt->sz)
		dilat_contact(pt);
}
void print_contact(contact* pt)
{
	if (pt == NULL)
	{
		perror("pt");
		return;
	}
	printf("%-5s   %-10s   %-5s   %-10s   %-20s   %-5s\n","编号", "姓名", "年龄", "性别", "电话号码", "地址");
	int i = 0;
	for (i = 0; i < pt->count; i++)
	{
		printf("%-5d  %-10s   %-5d   %-10s   %-20s   %-5s\n",i+1,
			pt->con[i].name,
			pt->con[i].age,
			pt->con[i].sex,
			pt->con[i].phone,
			pt->con[i].address);
	}
}
void dilat_contact(contact* pt)
{
	pt->sz++;
	infor* ptc = (infor*)realloc(pt->con, sizeof(infor) * pt->sz);
	assert(ptc);
	pt->con = ptc;
	printf("扩容成功\n");
}
int select(const char* test, contact* pt)
{
	char na[20] = { 0 };
	int sun = 0;
	int i = 0;
	scanf("%s", &na);
	for (i = 0; i < pt->count; i++)
	{
		if (strcmp(&test[i], na) == 0)
		{
			sun++;
			printf("%-5s   %-10s   %-5s   %-10s   %-20s   %-5s\n", "编号", "姓名", "年龄", "性别", "电话号码", "地址");
			printf("编号%d: %-10s   %-5d   %-10s   %-20s   %-5s\n", i + 1
				, pt->con[i].name,
				pt->con[i].age,
				pt->con[i].sex,
				pt->con[i].phone,
				pt->con->address);
		}
	}
	printf("查找到%d位联系人\n", sun);
	return sun;
}
void find_contact(contact* pt)
{
	int sdd = 0;
	int sum = 0;
	int i = 0;
	printf("|  1.findname     2.findphone     3.findaddress  |\n");
	printf("请选择查找方式  1.姓名 2.手机号  3.住址>:");
	scanf("%d", &sdd);
	switch (sdd)
	{
	case 0:
		return;
	case 1:
		printf("请输入要查找的姓名:");
		sum = select(pt->con->name, pt);
		break;
	case 2:
		printf("输入要查找的电话号码:");
		sum = select(pt->con->phone, pt);
		break;
	case 3:
		printf("请输入要查找的住址:");
		sum = select(pt->con->address, pt);
		break;
	default:
		printf("请选择正确的选项\n");
		break;
	}
}
void del_contact(contact* pt)
{
	assert(pt);
	int a = 0;
	int i = 0;
	printf("请输入要删除的联系人编号,或输入0退出\n");
	scanf("%d", &a);
	if (a == 0)
		return;
	else if (a > pt->count)
		printf("编号不存在\n");
	for (i = a - 1; i < pt->count; i++)
	{
		pt->con[i] = pt->con[i + 1];
	}
	pt->count--;
	printf("删除成功\n");
}

void change_contact(contact* pt)
{
	int sc = 0;
	int sd = 0;
	int se = 0;
	char ch[20] = { 0 };
	printf("请输入要更改的联系人编号,或输入0退出");
	scanf("%d", &sc);
	if (sc == 0)
		return;
	printf("请输入要更改的内容|0.退出 1.姓名  2.年龄  3.性别?  4.电话号码   5.地址:	`");
	scanf("%d", &sd);
	printf("请输入更改后的信息\n");
	switch (sd)
	{
	case 0:
		break;
		case 1:
			scanf("%s",ch);
			strcpy(pt->con[sc-1].name, ch);
			printf("更改成功\n");
			break;
		case 2:
			scanf("%d", &se);
			pt->con->age = se;
			break;
		case 3:
			scanf("%s", ch);
			strcpy(pt->con[sc - 1].sex, ch);
			printf("更改成功\n");
			break;		
		case 4:
				scanf("%s", ch);
				strcpy(pt->con[sc - 1].phone, ch);
				printf("更改成功\n");
				break;		
		case 5:
					scanf("%s", ch);
					strcpy(pt->con[sc - 1].address, ch);
					printf("更改成功\n");
					break;
		default:
			printf("选择错误\n");
			break;
	}
}
void destory_contact(contact* pt)
{
	int i = 0;
	FILE* fpt = fopen("contact.dat", "wb");
	assert(fpt);
	for (i = 0; i < pt->count; i++)
	{
		fwrite(&pt->con[i], sizeof(infor), 1, fpt);
	}
	fclose(fpt);
	free(pt->con);
	pt->con = NULL;
}

头文件

contact.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct information
{
	char name[10];
	int age;
	char sex[16];
	char phone[20];
	char address[10];
}infor;
typedef struct contactnumber
{
	int count;
	int sz;
	infor* con;
}contact;
void init_contact(contact* pt);//初始化通讯录
void add_contact(contact* pt);//添加联系人
void print_contact(contact* pt);//显示联系人
void dilat_contact(contact* pt);//通讯录扩容
void find_contact(contact* pt);//查找方式选择
int select(const char* test, contact* pt);//查找联系人
void del_contact(contact* pt);//删除联系人
void change_contact(contact* pt);//更改联系人信息
void destory_contact(contact* pt);
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值