零基础入门C语言之C语言实现数据结构之顺序表应用

在阅读本文之前,建议读者先阅读本专栏内前面的文章


前言

本文主要应用之前讲解过的顺序表部分的知识,来进行应用,进而实现一个通讯录。


我们之前学习过了顺序表部分的相关知识,它至少应该能够存储100个人的通讯信息,并且能够保存用户的一些基本信息,比如名字、性别、年龄、电话、地址等。除此之外,针对联系人的信息,我们要能够实现简单的增删查改以及显示。在实现过程中,我们需要思考该如何用静态顺序表和动态顺序表分别实现呢?以及如何保证程序结束之后,历史通讯录信息不会丢失。

我将主要的代码展示出来,供读者进行参考。

contact.h:

cpp 复制代码
#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10 
#define TEL_MAX 20
#define ADDR_MAX 100
//定义联系人数据 结构
//姓名 性别 年龄 电话 地址
typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}peoInfo;


//要用到顺序表相关的方法,对通讯录的操作实际就是对顺序表进行操作
//给顺序表改个名字,叫做通讯录
typedef struct SeqList Contact; //sl
//通讯录相关的方法

//通讯录的加载
void ContactLoad(Contact* con);
//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDesTroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);
//通讯录的保存
void ContactSave(Contact* con);

contact.c

cpp 复制代码
#include"Contact.h"
#include"SeqList.h"

//通讯录的加载
void ContactLoad(Contact* con) 
{
	FILE * pf = fopen("contact.txt", "rb");
	if (pf == NULL) {
		perror("fopen error!\n");
		return;
	}
	//循环读取⽂件数据
	peoInfo info;
	while (fread(&info, sizeof(peoInfo), 1, pf))
		{
		SLPushBack(con, info);
		}
	printf("历史数据加载通讯录成功!\n");
}

//通讯录的初始化
void ContactInit(Contact* con)//sl
{
	//实际上要进行的是顺序表的初始化
	//顺序表的初始化已经实现好了
	SLInit(con);
	ContactLoad(con);
}
//通讯录的销毁
void ContactDesTroy(Contact* con)
{
	ContactSave(con);
	SLDestroy(con);
}
//通讯录添加数据
void ContactAdd(Contact* con)
{
	//获取用户输入的内容:姓名+性别+年龄+电话+地址
	peoInfo info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s", info.name);

	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);

	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);

	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);

	printf("请输入要添加的联系人住址:\n");
	scanf("%s", info.addr);

	//往通讯录中添加联系人数据
	SLPushBack(con, info);
}

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(con->arr[i].name, name))
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}

//通讯录删除数据
void ContactDel(Contact* con)
{
	//要删除的数据必须要存在,才能执行删除操作
	//查找
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人数据不存在!\n");
		return;
	}
	//要删除的联系人数据存在--->知道了要删除的联系人数据对应的下标
	SLErase(con, find);
	printf("删除成功!\n");
}
//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头:姓名  性别 年龄 电话  地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	//遍历通讯录,按照格式打印每个联系人数据
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %3s %3d %3s %3s\n", //手动调整一下格式
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr
		);
	}
}
//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的联系人数据存在
	char name[NAME_MAX];
	printf("请输入要修改的用户姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人数据不存在!\n");
		return;
	}
	//直接修改
	printf("请输入新的姓名:\n");
	scanf("%s", con->arr[find].name);

	printf("请输入新的性别:\n");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的年龄:\n");
	scanf("%d", &con->arr[find].age);

	printf("请输入新的电话:\n");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的住址:\n");
	scanf("%s", con->arr[find].addr);

	printf("修改成功!\n");
}
//通讯录查找
void ContactFind(Contact* con)
{
	//11

	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人数据不存在!\n");
		return;
	}
	// 姓名 性别 年龄 电话  地址
	// 11   11   11   11   11
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%3s %3s %3d %3s %3s\n", //手动调整一下格式
		con->arr[find].name,
		con->arr[find].gender,
		con->arr[find].age,
		con->arr[find].tel,
		con->arr[find].addr
	);
}

//通讯录的保存
void ContactSave(Contact* con) {
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL) {
		perror("fopen error!\n");
		return;
	}
	//将通讯录数据写⼊⽂件
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr + i, sizeof(peoInfo), 1, pf);
	}
	printf("通讯录数据保存成功!\n");
}

seqlist.h:

cpp 复制代码
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include "Contact.h"

//定义顺序表结构

#define N 100

//静态顺序表
//struct SeqList
//{
//	int arr[N]; //定长数组
//	int size; //空间大小
//};


//typedef int SLDataType;
typedef peoInfo SLDataType;

//动态顺序表
typedef struct SeqList
{
	SLDataType* arr;
	int size;//有效数据的个数
	int capacity;//空间大小
}SL;

//初始化顺序表
void SLInit(SL* ps);
//销毁顺序表
void SLDestroy(SL* ps);
//检测顺序表空间
void SLCheckCapacity(SL* ps);
//顺序表元素打印
void SLPrint(SL* ps);
//顺序表尾部插入
void SLPushBack(SL * ps, SLDataType x);
//顺序表尾部删除
void SLPopBack(SL * ps);
//顺序表头部插⼊
void SLPushFront(SL * ps, SLDataType x);
//顺序表头部删除
void SLPopFront(SL * ps);
//指定位置之前插⼊数据
void SLInsert(SL * ps, int pos, SLDataType x);
//指定位置删除数据
void SLErase(SL* ps, int pos);
//查找元素位置
int SLFind(SL* ps, SLDataType x);

test.c:

cpp 复制代码
#include "SeqList.h"

//void SLTest01() {
//    SL sl;
//    SLInit(&sl);
//    SLPushBack(&sl, 1);
//    SLPushBack(&sl, 2);
//    SLPushBack(&sl, 3);
//    SLPushBack(&sl, 4);
//    SLPushBack(&sl, 5);
//    SLPrint(&sl);
//
//    SLPushFront(&sl, 0);
//    SLPushFront(&sl, -1);
//    SLPushFront(&sl, -2);
//    SLPushFront(&sl, -3);
//    SLPushFront(&sl, -4);
//    SLPrint(&sl);
//
//    SLPopBack(&sl);
//    SLPopBack(&sl);
//    SLPrint(&sl);
//
//    SLPopFront(&sl);
//    SLPopFront(&sl);
//    SLPrint(&sl);
//    
//    SLDestroy(&sl);
//}

//void SLTest02() {
//    SL sl;
//    SLInit(&sl);
//    SLPushBack(&sl, 1);
//    SLPushBack(&sl, 2);
//    SLPushBack(&sl, 3);
//    SLPushBack(&sl, 4);
//    SLPushBack(&sl, 5);
//    SLPrint(&sl);
//
//	SLInsert(&sl, 2, 100);
//	SLPrint(&sl);
//    SLInsert(&sl, 0, 200);
//	SLPrint(&sl);
//
//    SLErase(&sl, 0);
//	SLPrint(&sl);
//    SLErase(&sl, 2);
//	SLPrint(&sl);
//
//    printf("%d\n", SLFind(&sl, 3));
//    printf("%d\n", SLFind(&sl, 100));
//}

void menu()
{
	printf("******************通讯录******************\n");
	printf("*******1.增加联系人   2.删除联系人********\n");
	printf("*******3.修改联系人   4.查找联系人********\n");
	printf("*******5.展示联系人   0.   退出  *********\n");
	printf("******************************************\n");
}

int main() {
    //SLTest01();
	//SLTest02();
	int op = -1;
	Contact con;
	ContactInit(&con);

	do {
		menu();
		printf("请选择您的操作:\n");
		scanf("%d", &op);

		//要根据对应的op执行不同的操作
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("退出通讯录....\n");
			break;
		default:
			printf("输入错误,请重新选择您的操作!\n");
			break;
		}
	} while (op != 0);

	ContactDesTroy(&con);
    return 0;
}

总结

本文基于顺序表知识实现了一个通讯录系统,能够存储至少100个联系人的基本信息(姓名、性别、年龄、电话、地址)。系统提供了完整的增删查改功能,并通过文件读写实现数据持久化。主要实现包括:定义联系人数据结构;封装顺序表操作作为通讯录基础功能;实现加载、保存功能确保数据不丢失;提供交互式菜单界面。代码展示了静态/动态顺序表两种实现思路,通过模块化设计将通讯录功能与底层数据结构分离。系统结束时自动保存数据,再次启动时可恢复历史记录。

相关推荐
lkbhua莱克瓦242 小时前
Java基础——常用算法3
java·数据结构·笔记·算法·github·排序算法·学习方法
小白程序员成长日记2 小时前
2025.11.07 力扣每日一题
数据结构·算法·leetcode
·白小白2 小时前
力扣(LeetCode) ——209. 长度最小的子数组(C++)
c++·算法·leetcode
小猪咪piggy2 小时前
【算法】day16 动态规划
算法·动态规划
ohnoooo92 小时前
251106 算法
数据结构·c++·算法
uesowys2 小时前
华为OD算法开发指导-简易内存池
java·算法·华为od
Greedy Alg3 小时前
LeetCode 155. 最小栈
算法
雾岛听蓝3 小时前
算法复杂度解析:时间与空间的衡量
c语言·数据结构·经验分享·笔记
小白程序员成长日记3 小时前
2025.11.08 力扣每日一题
算法·leetcode·职场和发展