C语言实现建立手机通讯录(顺序结构)

简介: C语言实现建立手机通讯录(顺序结构)

一.题目要求

今天来和大家分享一个简易通讯录(C语言实现)


首先要介绍一下通讯录的基本功能


添加联系人信息

删除指定联系人信息

查找指定联系人信息

修改指定联系人信息

显示所有联系人信息

二.思路分析

1. 首先需要定义通讯录的数据结构,可以使用结构体来表示每个联系人的信息,包括姓名、电话号码、地址等。


2. 接着需要定义一个数组来存储所有联系人的信息,数组的大小可以根据实际需求进行调整。


3. 编写程序菜单,包括添加联系人、删除联系人、查找联系人、显示所有联系人等功能。


4. 在添加联系人功能中,需要让用户输入联系人的信息,并将其存储到数组中。


5. 在删除联系人功能中,需要让用户输入要删除的联系人姓名,并在数组中查找并删除该联系人的信息。


6. 在查找联系人功能中,需要让用户输入要查找的联系人姓名,并在数组中查找并显示该联系人的信息。


7. 在显示所有联系人功能中,需要遍历数组并逐个显示每个联系人的信息。


8. 最后,可以使用文件读写功能将通讯录数据保存到文件中,以便下次启动程序时可以读取之前保存的数据。

总结,考虑到数据结构中的顺序表和单链表,我们可以采用这两种结构来实现。本文选择使用顺序表来实现,下一章可以通过单链表来实现。


三.各部分功能实现

1.定义通讯录结构

      在声明线性表的顺序存储类型时,定义一个data数组来存储线性表中的所有元素,定义一个整型变量length来存储线性表的实际长度,并采用结构体类型SqList表示。

//定义通讯录结构表
typedef struct {
  char name[20];
  char tel[15];
} Elemtype;
//声明顺序表
typedef struct {
  Elemtype  data[MaxSize];           //存放线性表中的元素是Elemtype所指代的通讯录结构体
  int length;                        //存放线性表的长度
} SqList;                             //表示本次实验使用顺序表类型来完成通讯录的建立

2.初始化以及销毁线性表

  • 初始化线性表:该运算的功能是构造一个空的线性表L,实际上只需要分配线性表的存储空间并将 Length 域设置为0即可。
  • 销毁线性表:释放线性表L所占的内存空间。
//初始化线性表
void InitList(SqList *&L) {
  /*如果不方便理解,可以把L作为一个结构体指针,则下面操作可以理解为首先把分配的
    一个结构体SqList一样大小的空间的首地址赋给L,L所指向的结构体中数据元素个数为0*/
  L = (SqList * )malloc(sizeof(SqList));
  L->length = 0;
}
//撤销(销毁)线性表
void DestroyList(SqList *&L) {
  free(L);                 //释放指针L指向的顺序表空间
}

3.插入数据元素

       该运算在顺序表L的第 i (1≤i≤n+1)个位置上插人新元素e。如果 i 值不正确,返回false;否则将顺序表原来的第i个元素及以后的元素均后移一个位置,并从最后一个元素an开始移动起。腾出一个空位置插入新元素,最后顺序表的长度增1并返回true。算法如下:


//插入数据元素
bool ListInsert(SqList *&L, int i, Elemtype e) {
  /*在顺序表L的第i个位置上插入新元素e*/
  int j;
  //参数i不正确时,返回false
  if (i < 1 || i > L->length + 1 || L->length == MaxSize)
    return false;
  i--;                //将顺序表逻辑序号转化为物理序号
  //参数i正确时,将data[i]及后面的元素后移一个位置
  for (j = L->length; j > i; j--) {
    L->data[j] = L->data[j - 1];
  }
  L->data[i] = e;      //插入元素e
  L->length++;         //顺序表长度加1
  return true;
}

4.删除数据元素

      该运算删除顺序表L的第 i (1≤i≤n)个元素。如果i值不正确,返回false;否则线性表第 i 个元素以后的元素均向前移动一个位置,并从元素a(i+1)开始移动起,这样覆盖了原来的第 i个元素,达到了删除该元素的目的,最后顺序表的长度减1并返回true。算法如下:

//删除数据元素
bool ListDelate (SqList *&L, int i, Elemtype &e) {
  /*删除顺序表中的第i个元素,其值为e*/
  int j;
  if (i < 1 || i > L->length)
    return false;
  i--;              //将顺序表逻辑序号转化为物理序号
  e = L->data[i];
  //参数正确时,将data[i]之后的元素前移一个位置
  for (j = i; j < L->length - 1; j++)
    L->data[j] = L->data[j + 1];
  L->length--;     //顺序表的长度减1
  return true;
}

5.输出线性表

  • 依次显示L中各元素的值
//输出线性表
void DispList(SqList *L) {
  if (L->length == 0)
    printf("线性表为空");
  //扫描顺序表,输出各元素
  for (int i = 0; i < L->length; i++) {
    printf("%s    %s", L->data[i].name, L->data[i].tel);
    printf("\n");
  }
  printf("\n");
}

6.求某个数据元素值

  • 该运算用应用型参数e返回L中第i个元素的值
//求某个数据元素值
bool GetElem(SqList *L, int i, Elemtype &e) {
  if (i < 1 || i > L->length)
    return false;         //参数i错误时,返回false
  e = L->data[i - 1];      //取元素值
  return true;
}

7.元素查找

  • 该运算顺序查找第一个值域与e相等的元素的逻辑序号(找到后返回一个大于0的值),若这样的元素不存在,则返回值为0。
//元素查找
int LocateElem(SqList *L, Elemtype e) {
  /*顺序查找第一个值域与e相等的元素逻辑序号(根据e找i)*/
  int i = 0;
  //while循环查找e
  while (i < L->length && strcmp(L->data[i].name, e.name) != 0)
    i++;
  if (i >= L->length)
    return 0;                      //未找到返回0
  else
    printf("%s   %s\n",L->data[i].name,L->data[i].tel);
    return i + 1;                 //找到后返回其逻辑序号
}

四. 完整代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MaxSize 50
//定义通讯录结构表
typedef struct {
  char name[20];
  char tel[15];
} Elemtype;
//声明顺序表
typedef struct {
  Elemtype  data[MaxSize];           //存放线性表中的元素是Elemtype所指代的通讯录结构体
  int length;                        //存放线性表的长度
} SqList;                             //表示本次实验使用顺序表类型来完成通讯录的建立
/*我们这里可以有两种思路来完成顺序表的建立,
第一(整体创建):由数组元素a[0···n-1]创建顺序表L,即将数组a中的每个元素依次放入顺序表中,并将n赋给顺序表的长度域。
    前提是已经有一个数组存在,把它作为建立顺序表函数的参数进行传入。
第二(添加创建):先初始化一个空的顺序表,然后通过顺序表的添加元素函数进行补充,从而构建一个完整的顺序表。
 */
//初始化线性表
void InitList(SqList *&L) {
  /*如果不方便理解,可以把L作为一个结构体指针,则下面操作可以理解为首先把分配的
    一个结构体SqList一样大小的空间的首地址赋给L,L所指向的结构体中数据元素个数为0*/
  L = (SqList * )malloc(sizeof(SqList));
  L->length = 0;
}
//撤销(销毁)线性表
void DestroyList(SqList *&L) {
  free(L);                 //释放指针L指向的顺序表空间
}
//插入数据元素
bool ListInsert(SqList *&L, int i, Elemtype e) {
  /*在顺序表L的第i个位置上插入新元素e*/
  int j;
  //参数i不正确时,返回false
  if (i < 1 || i > L->length + 1 || L->length == MaxSize)
    return false;
  i--;                //将顺序表逻辑序号转化为物理序号
  //参数i正确时,将data[i]及后面的元素后移一个位置
  for (j = L->length; j > i; j--) {
    L->data[j] = L->data[j - 1];
  }
  L->data[i] = e;      //插入元素e
  L->length++;         //顺序表长度加1
  return true;
}
//删除数据元素
bool ListDelate (SqList *&L, int i, Elemtype &e) {
  /*删除顺序表中的第i个元素,其值为e*/
  int j;
  if (i < 1 || i > L->length)
    return false;
  i--;              //将顺序表逻辑序号转化为物理序号
  e = L->data[i];
  //参数正确时,将data[i]之后的元素前移一个位置
  for (j = i; j < L->length - 1; j++)
    L->data[j] = L->data[j + 1];
  L->length--;     //顺序表的长度减1
  return true;
}
//输出线性表
void DispList(SqList *L) {
  if (L->length == 0)
    printf("线性表为空");
  //扫描顺序表,输出各元素
  for (int i = 0; i < L->length; i++) {
    printf("%s    %s", L->data[i].name, L->data[i].tel);
    printf("\n");
  }
  printf("\n");
}
//求某个数据元素值
bool GetElem(SqList *L, int i, Elemtype &e) {
  if (i < 1 || i > L->length)
    return false;         //参数i错误时,返回false
  e = L->data[i - 1];      //取元素值
  return true;
}
//元素查找
int LocateElem(SqList *L, Elemtype e) {
  /*顺序查找第一个值域与e相等的元素逻辑序号(根据e找i)*/
  int i = 0;
  //while循环查找e
  while (i < L->length && strcmp(L->data[i].name, e.name) != 0)
    i++;
  if (i >= L->length)
    return 0;                      //未找到返回0
  else
    printf("%s   %s\n",L->data[i].name,L->data[i].tel);
    return i + 1;                 //找到后返回其逻辑序号
}
//菜单实现
void menu() {
  printf("   -------------------------------\n");
  printf("   通讯录的应用:\n");
  printf("   -------------------------------\n");
  printf("      1.建立(初始化)通讯录\n");
  printf("      2.显示联系人信息\n");
  printf("      3.增加联系人信息\n");
  printf("      4.删除联系人信息\n");
  printf("      5.查找联系人信息\n");
  printf("      6.退出程序!!!\n");
  printf("   -------------------------------\n");
}
int main() {
  SqList *L;
  int flag = 1;   //定义循环体条件
  int i, j;         //存放用户输入的选项
  Elemtype a[4] = {"张三", "15671580583", "李四", "13387592396", "王五", "15994272725", "赵六", "15972200598"};
  Elemtype e;
  menu();
  printf("初始化顺序表并插入开始元素:\n");
  InitList(L);         //这时是一个空表,接下来通过插入元素函数完成初始化
  for (int i = 0; i < 4; i++)
    ListInsert(L, i + 1, a[i]);
  DispList(L);
  while (flag == 1) {
    printf("请输入你的选择:\n");
    scanf("%d", &j);
    switch (j) {
      case 1:
        printf("已经完成初始化\n");
        break;
      case 2:
        DispList(L);
        break;
      case 3:
        printf("请输入联系人姓名与电话:");
        scanf("%s   %s", e.name, e.tel);
        printf("请输入插入数据的位置:");
        scanf("%d", &i);
        printf("\n");
        ListInsert(L, i, e);
        break;
      case 4:
        printf("请输入删除数据的位置:");
        scanf("%d", &i);
        ListDelate(L, i, e);
        break;
      case 5:
        printf("请输入联系人姓名:");
        scanf("%s", &e.name);
        LocateElem(L, e);
        break;
      case 6:
        flag = 0;
        printf("退出程序\n");
        break;
    }
  }
  return 0;
}

五.实验截图

55ba5c0c0abd492e85868859603520e6.png

补充:完整源代码在我上传的资源里有。

相关文章
|
5天前
|
网络协议 编译器 Linux
【C语言】结构体内存对齐:热门面试话题
【C语言】结构体内存对齐:热门面试话题
|
4月前
|
C语言
【C语言基础篇】结构控制(中)循环结构
【C语言基础篇】结构控制(中)循环结构
|
4天前
|
存储 C语言
手把手教你用C语言实现通讯录管理系统
手把手教你用C语言实现通讯录管理系统
|
1月前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
49 10
|
1月前
|
C语言
C语言程序设计核心详解 第四章&&第五章 选择结构程序设计&&循环结构程序设计
本章节介绍了C语言中的选择结构,包括关系表达式、逻辑表达式及其运算符的优先级,并通过示例详细解释了 `if` 语句的不同形式和 `switch` 语句的使用方法。此外,还概述了循环结构,包括 `while`、`do-while` 和 `for` 循环,并解释了 `break` 和 `continue` 控制语句的功能。最后,提供了两道例题以加深理解。
|
1月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
1月前
|
C语言
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
本章介绍顺序结构的基本框架及C语言的标准输入输出。程序从`main()`开始依次执行,框架包括输入、计算和输出三部分。重点讲解了`printf()`与`scanf()`函数:`printf()`用于格式化输出,支持多种占位符;`scanf()`用于格式化输入,需注意普通字符与占位符的区别。此外还介绍了`putchar()`和`getchar()`函数,分别用于输出和接收单个字符。
|
1月前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
2月前
|
C语言
C语言------选择结构
这篇文章是C语言选择结构的入门实训,包括多个练习题及其源代码,旨在帮助读者熟练掌握条件语句和选择结构程序设计方法,并熟悉switch语句和程序调试过程。
C语言------选择结构
|
2月前
|
存储 搜索推荐 算法
【C语言】C语言—通讯录管理系统(源码)【独一无二】
【C语言】C语言—通讯录管理系统(源码)【独一无二】