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

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

相关文章
|
6天前
|
存储 安全 C语言
【C语言程序设计——选择结构程序设计】预测你的身高(头歌实践教学平台习题)【合集】
分支的语句,这可能不是预期的行为,这种现象被称为“case穿透”,在某些特定情况下可以利用这一特性来简化代码,但在大多数情况下,需要谨慎使用。编写一个程序,该程序需输入个人数据,进而预测其成年后的身高。根据提示,在右侧编辑器补充代码,计算并输出最终预测的身高。分支下的语句,提示用户输入无效。常量的值必须是唯一的,且在同一个。语句的作用至关重要,如果遗漏。开始你的任务吧,祝你成功!,程序将会继续执行下一个。常量都不匹配,就会执行。来确保程序的正确性。
29 10
|
6天前
|
小程序 C语言
【C语言程序设计——基础】顺序结构程序设计(头歌实践教学平台习题)【合集】
目录 任务描述 相关知识 编程要求 测试说明 我的通关代码: 测试结果: 任务描述 相关知识 编程编写一个程序,从键盘输入3个变量的值,例如a=5,b=6,c=7,然后将3个变量的值进行交换,使得a=6,b=7,c=5。面积=sqrt(s(s−a)(s−b)(s−c)),s=(a+b+c)/2。使用输入函数获取半径,格式指示符与数据类型一致,实验一下,不一致会如何。根据提示,在右侧编辑器补充代码,计算并输出圆的周长和面积。
27 10
|
3月前
|
网络协议 编译器 Linux
【C语言】结构体内存对齐:热门面试话题
【C语言】结构体内存对齐:热门面试话题
132 0
|
6天前
|
存储 编译器 C语言
【C语言程序设计——选择结构程序设计】求一元二次方程的根(头歌实践教学平台习题)【合集】
本任务要求根据求根公式计算并输出一元二次方程的两个实根,精确到小数点后两位。若方程无实根,则输出提示信息。主要内容包括: - **任务描述**:使用求根公式计算一元二次方程的实根。 - **相关知识**:掌握 `sqrt()` 函数的基本使用方法,判断方程是否有实根。 - **编程要求**:根据输入的系数,计算并输出方程的根或提示无实根。 - **测试说明**:提供两组测试数据及预期输出,确保代码正确性。 - **通关代码**:包含完整的 C 语言代码示例,实现上述功能。 通过本任务,你将学会如何处理一元二次方程的求解问题,并熟悉 `sqrt()` 函数的使用。
18 5
|
6天前
|
存储 算法 安全
【C语言程序设计——选择结构程序设计】按从小到大排序三个数(头歌实践教学平台习题)【合集】
本任务要求从键盘输入三个数,并按从小到大的顺序排序后输出。主要内容包括: - **任务描述**:实现三个数的排序并输出。 - **编程要求**:根据提示在编辑器中补充代码。 - **相关知识**: - 选择结构(if、if-else、switch) - 主要语句类型(条件语句) - 比较操作与交换操作 - **测试说明**:提供两组测试数据及预期输出。 - **通关代码**:完整代码示例。 - **测试结果**:展示测试通过的结果。 通过本任务,你将掌握基本的选择结构和排序算法的应用。祝你成功!
25 4
|
6天前
|
存储 算法 安全
【C语言程序设计——选择结构程序设计】求阶跃函数的值(头歌实践教学平台习题)【合集】
本任务要求输入x的值,计算并输出特定阶跃函数的结果。主要内容包括: 1. **选择结构基本概念**:介绍if、if-else、switch语句。 2. **主要语句类型**:详细解释if、if-else、switch语句的使用方法。 3. **跃迁函数中变量的取值范围**:说明如何根据条件判断变量范围。 4. **计算阶跃函数的值**:通过示例展示如何根据给定条件计算函数值。 编程要求:在右侧编辑器Begin-End之间补充代码,实现阶跃函数的计算和输出。测试说明提供了多个输入及其预期输出,确保代码正确性。最后提供通关代码和测试结果,帮助理解整个过程。
19 0
|
6天前
|
存储 算法 安全
【C语言程序设计——选择结构程序设计】判断一个数是不是5和7的倍数(头歌实践教学平台习题)【合集】
本任务要求输入一个正整数,判断其是否同时是5和7的倍数,若是输出&quot;Yes&quot;,否则输出&quot;No&quot;。内容涵盖选择结构的基本概念、主要语句类型(if、if-else、switch)及条件判断逻辑,帮助理解编程中的分支执行与条件表达式。测试用例包括正数、负数及非倍数情况,确保代码逻辑严谨。通关代码示例如下: ```cpp #include &quot;stdio.h&quot; int main(){ int a; scanf(&quot;%d&quot;, &a); if (a &lt;= 0){ printf(&quo
23 0
|
6天前
|
编译器 C语言 C++
【C语言程序设计——选择结构程序设计】求输入的日期是该年的第几天(头歌实践教学平台习题)【合集】
本任务要求编写程序,根据用户输入的年月日(以空格或回车分隔),计算并输出该天是该年的第几天,需注意判断闰年。主要内容包括: 1. **任务描述**:实现从键盘输入年月日,计算该天是当年的第几天。 2. **相关知识**: - `switch` 结构的基本语法及使用注意事项。 - 判断闰年的条件:能被4整除但不能被100整除,或能被400整除的年份为闰年。 3. **编程要求**:根据提示补充代码,确保程序正确处理输入并输出结果。 4. **测试说 示例代码展示了如何使用 `switch` 语句和闰年判断逻辑来完成任务。通过此练习,掌握 `switch` 语句的应用及闰年判断方法。
19 0
|
2月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
119 16
|
3月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
48 2