C语言实验-动态顺序表实现简易通讯录(二)

简介: 在这个C语言实验中,你将实现一个简单的通讯录,它使用动态顺序表来存储联系人信息。

C语言实验-动态顺序表实现简易通讯录(一)+ https://developer.aliyun.com/article/1519323?spm=a2c6h.13148508.setting.14.25634f0etWq3TD


6.按姓名查找联系人


toFindName是我们要查找的联系人姓名,由用户输入。将用户输入的待查找姓名与通讯录中的所有联系人姓名挨个比较,若查找到了,就返回该联系人在通讯录中的下标,若没有找到,返回-1。


代码如下:


//3-查找 按姓名
int searchContact(Contact *con,const char *toFindName)
{
  assert(con);
 
  for (int i = 0; i < con->size; i++)
  {
    if (strcmp(con->arr[i].name, toFindName) == 0)
    {
      return i;
    }
  }
  return -1;
}


7.删除联系人


删除联系人的函数中,先对通讯录进行了判空,以保证在执行运行操作时候通讯录非空。


调用了查找函数,来判断要删除的联系人在表中是否存在。若存在,则执行删除操作:与顺序表的删除一样,将该联系人后面的所有联系人(从第i+1到第n)依次向前移动1位,将要删除的联系人信息覆盖删除。


在删除完毕后必须将个数size减1.


代码如下:


//2-按姓名删除
void delContact(Contact* con,const char *toDelName)
{
  assert(con);
  if (con->size == 0)
  {
    printf("通讯录为空!删除失败!\n");
    return;
  }
 
  if (searchContact(con, toDelName) != -1)
  {
    for (int i = searchContact(con, toDelName); i < con->size-1; i++)
    {
      con->arr[i] = con->arr[i + 1];
    }
    con->size--;
    printf("删除成功!\n");
  }
  else
  {
    printf("该联系人不存在,删除失败!\n");
  }
}


8.修改指定联系人的指定信息


通过姓名检索指定的要更改其信息的联系人,仍然调用查找函数实现检索。


在找到目标联系人的信息后,我们通过相应的选择来决定要更改该联系人的哪一信息(姓名/性别/电话/住址)。注意,此处联系人信息均应输入字符串,对字符串的赋值不能直接用等号,而应用strcpy()。


代码如下:

//4-修改 按姓名
void modifyContact(Contact* con)
{
  assert(con);
  if (con->size == 0)
  {
    printf("通讯录为空!修改失败!\n");
    return;
  }
 
  char toModifyName[20] = { 0 };
  printf("请输入要更改的联系人的姓名:");
  scanf(" %s", toModifyName);
 
  int modifyI = searchContact(con, toModifyName);
  if (modifyI != -1)
  {
    printf("请输入您要修改的信息项:\n");
    printf("0.姓名:\n");
    printf("1.性别:\n");
    printf("2.电话:\n");
    printf("3.住址:\n");
    
    int input = 0;
    scanf(" %d", &input);
 
    printf("请输入修改后的信息:");
    char tmp[50] = { 0 };
    scanf(" %s", tmp);
 
    switch (input)
    {
    case 0:
      strcpy(con->arr[modifyI].name, tmp);
      break;
    case 1:
      strcpy(con->arr[modifyI].sex, tmp);
      break;
    case 2:
      strcpy(con->arr[modifyI].tel, tmp);
      break;
    case 3:
      strcpy(con->arr[modifyI].addr, tmp);
      break;
    }   
    printf("修改成功!\n");
  }
  else
  {
    printf("修改失败!联系人不存在!\n");
  }
}


9.查看所有联系人


注意打印格式,%-20s 的含义为打印一个字符串,该字符串左对齐(-号)并占20个比特位(若不足20个比特位则右侧补空格)。


代码如下:


//5-展示
void showContact(Contact *con)
{
  printf("%-20s", "姓名");
  printf("%-20s", "性别");
  printf("%-20s", "电话");
  printf("%-20s", "住址");
  printf("\n");
  
  for(int i = 0; i < con->size; i++)
  {
    printf("%-20s", con->arr[i].name);
    printf("%-20s", con->arr[i].sex);
    printf("%-20s", con->arr[i].tel);
    printf("%-20s", con->arr[i].addr);
    printf("\n");
  }
}


打印后的对齐效果如下:



10.按指定关键字对联系人进行排序


实现思路与修改指定联系人的指定信息类似。在排序时我们可以采用c库函数qsort()

注意qsort实现结构体排序时,比较函数cmp的书写。需先将e1和e2强制类型转换为结构体指针(People*),再通过结构体指针访问联系人信息关键字。


//比较函数
static int cmp_name(const void* e1, const void* e2)
{
  //本质是字符串比较->使用strcmp函数
  return strcmp(((People*)e1)->name, ((People*)e2)->name);
}
 
static int cmp_sex(const void* e1, const void* e2)
{
  return strcmp(((People*)e1)->sex, ((People*)e2)->sex);
 
}
 
static int cmp_tel(const void* e1, const void* e2)
{
  return strcmp(((People*)e1)->tel, ((People*)e2)->tel);
}
 
static int cmp_addr(const void* e1, const void* e2)
{
  return strcmp(((People*)e1)->addr, ((People*)e2)->addr);
}
 
 
 
//6-排序
void sortContact(Contact *con)
{
  assert(con);
 
  printf("要按哪一项排序?\n");
  printf("0.姓名:\n");
  printf("1.性别:\n");
  printf("2.电话:\n");
  printf("3.住址:\n");
 
  int input = 0;
  scanf(" %d", &input);
  switch (input)
  {
  case 0:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_name);
    break;
  case 1:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_sex);
    break;
  case 2:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_tel);
    break;
  case 3:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_addr);
    break;
  }
  printf("排序成功!\n");
}


三、完整代码


Contact.cpp


1.
#define _CRT_SECURE_NO_WARNINGS 1
 
#include"Contact.h"
 
//初始化
void Init(Contact* con)
{
  con->arr = NULL;
  con->size = con->capacity = 0;
}
 
//判断增容
static void CheckCapacity(Contact* con)
{
  assert(con);
 
  if (con->capacity == con->size)
  {
    int newCapacity = con->capacity == 0 ? 4 : 2 * con->capacity;
    People* tmp = (People*)realloc(con->arr, sizeof(People) * newCapacity);
    if (tmp == NULL)
    {
      perror("CheckCapacity");
      exit(-1);
    }
    else
    {
      con->arr = tmp;
      con->capacity = newCapacity;
    }
  }
}
 
//1-添加
void addContact(Contact *con)
{
  //判断增容
  CheckCapacity(con);
 
  //添加内容
  printf("姓名:");
  scanf(" %s", con->arr[con->size].name);
  printf("性别:");
  scanf(" %s", con->arr[con->size].sex);
  printf("电话:");
  scanf(" %s", con->arr[con->size].tel);
  printf("住址:");
  scanf(" %s", con->arr[con->size].addr);
 
  con->size++;
  printf("添加联系人成功!\n");
}
 
//2-按姓名删除
void delContact(Contact* con,const char *toDelName)
{
  assert(con);
  if (con->size == 0)
  {
    printf("通讯录为空!删除失败!\n");
    return;
  }
 
  if (searchContact(con, toDelName) != -1)
  {
    for (int i = searchContact(con, toDelName); i < con->size-1; i++)
    {
      con->arr[i] = con->arr[i + 1];
    }
    con->size--;
    printf("删除成功!\n");
  }
  else
  {
    printf("该联系人不存在,删除失败!\n");
  }
}
 
//3-查找 按姓名
int searchContact(Contact *con,const char *toFindName)
{
  assert(con);
 
  for (int i = 0; i < con->size; i++)
  {
    if (strcmp(con->arr[i].name, toFindName) == 0)
    {
      return i;
    }
  }
  return -1;
}
 
//4-修改 按姓名
void modifyContact(Contact* con)
{
  assert(con);
  if (con->size == 0)
  {
    printf("通讯录为空!修改失败!\n");
    return;
  }
 
  char toModifyName[20] = { 0 };
  printf("请输入要更改的联系人的姓名:");
  scanf(" %s", toModifyName);
 
  int modifyI = searchContact(con, toModifyName);
  if (modifyI != -1)
  {
    printf("请输入您要修改的信息项:\n");
    printf("0.姓名:\n");
    printf("1.性别:\n");
    printf("2.电话:\n");
    printf("3.住址:\n");
    
    int input = 0;
    scanf(" %d", &input);
 
    printf("请输入修改后的信息:");
    char tmp[50] = { 0 };
    scanf(" %s", tmp);
 
    switch (input)
    {
    case 0:
      strcpy(con->arr[modifyI].name, tmp);
      break;
    case 1:
      strcpy(con->arr[modifyI].sex, tmp);
      break;
    case 2:
      strcpy(con->arr[modifyI].tel, tmp);
      break;
    case 3:
      strcpy(con->arr[modifyI].addr, tmp);
      break;
    }   
    printf("修改成功!\n");
  }
  else
  {
    printf("修改失败!联系人不存在!\n");
  }
}
 
//5-展示
void showContact(Contact *con)
{
  printf("%-20s", "姓名");
  printf("%-20s", "性别");
  printf("%-20s", "电话");
  printf("%-20s", "住址");
  printf("\n");
  
  for(int i = 0; i < con->size; i++)
  {
    printf("%-20s", con->arr[i].name);
    printf("%-20s", con->arr[i].sex);
    printf("%-20s", con->arr[i].tel);
    printf("%-20s", con->arr[i].addr);
    printf("\n");
  }
}
 
 
static int cmp_name(const void* e1, const void* e2)
{
  //本质是字符串比较->使用strcmp函数
  return strcmp(((People*)e1)->name, ((People*)e2)->name);
}
 
static int cmp_sex(const void* e1, const void* e2)
{
  return strcmp(((People*)e1)->sex, ((People*)e2)->sex);
 
}
 
static int cmp_tel(const void* e1, const void* e2)
{
  return strcmp(((People*)e1)->tel, ((People*)e2)->tel);
}
 
static int cmp_addr(const void* e1, const void* e2)
{
  return strcmp(((People*)e1)->addr, ((People*)e2)->addr);
}
 
//6-排序
void sortContact(Contact *con)
{
  assert(con);
 
  printf("要按哪一项排序?\n");
  printf("0.姓名:\n");
  printf("1.性别:\n");
  printf("2.电话:\n");
  printf("3.住址:\n");
 
  int input = 0;
  scanf(" %d", &input);
  switch (input)
  {
  case 0:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_name);
    break;
  case 1:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_sex);
    break;
  case 2:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_tel);
    break;
  case 3:
    qsort(con->arr, con->size, sizeof(con->arr[0]), cmp_addr);
    break;
  }
  printf("排序成功!\n");
}
 
//7-销毁
void destroyContact(Contact *con)
{
  assert(con);
  free(con->arr);
  con->arr = NULL;
  con->size = con->capacity = 0;
  printf("销毁成功!\n");
}


Contact.h


#define _CRT_SECURE_NO_WARNINGS 1
 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
 
 
enum Choice
{
  texit,
  add,
  del,
  search,
  modify,
  show,
  sort
};
 
typedef struct People
{
  char name[20];  //姓名
  char sex[6];  //性别
  char tel[15]; //电话
  char addr[50];  //住址
}People;
 
typedef struct Contact 
{
  People* arr;
  int size;
  int capacity;
}Contact;
 
//初始化
void Init(Contact* con);
 
//1-添加
void addContact(Contact* con);
 
//5-展示
void showContact(Contact* con);
 
//2-按姓名删除
void delContact(Contact* con, const char* toDelName);
 
//3-查找 按姓名
int searchContact(Contact* con, const char* toFindName);
 
//4-修改 按姓名
void modifyContact(Contact* con);
 
//6-排序
void sortContact(Contact* con);
 
//7-销毁
void destroyContact(Contact* con);


Test.cpp


#define _CRT_SECURE_NO_WARNINGS 1
 
#include"Contact.h"
 
void menu()
{
  printf("**************************************\n");
  printf("*****   1. add      2. del       *****\n");
  printf("*****   3. search   4. modify    *****\n");
  printf("*****   5. show     6. sort      *****\n");
  printf("*****   0. exit                  *****\n");
  printf("**************************************\n");
  printf("\n");
}
 
int main()
{
  Contact contact;
  Init(&contact);
  int input = 0;
  printf("通讯录初始化成功!\n");
 
  do
  {
    menu();
    printf("请输入选项:>");
    scanf(" %d", &input);
 
    switch (input)
    {
    case add:
    {
      addContact(&contact);
      break;
    }
    case del:
    {
      printf("请输入要删除的联系人姓名:>");
      char name[20] = { 0 };
      scanf(" %s", name);
      delContact(&contact, name);
      break;
    }
    case search:
    {
      printf("请输入要查找的联系人姓名:>");
      char name[20] = { 0 };
      scanf(" %s", name);
      searchContact(&contact, name);
      break;
    }
    case modify:
      modifyContact(&contact);
      break;
    case show:
      showContact(&contact);
      break;
    case sort:
      sortContact(&contact);
      break;
    case texit:
      printf("退出程序!通讯录销毁!\n");
      destroyContact(&contact);    //注意要销毁
      break;
    default:
      printf("请输入正确的选项!\n");
      break;
    }
    fflush(stdin);
    printf("\n");
  } while (input);
  
  return 0;
}
相关文章
|
17天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
46 3
|
1月前
|
C语言
大学生期末C语言实验(学生成绩和鞍点)
大学生期末C语言实验(学生成绩和鞍点)
148 0
大学生期末C语言实验(学生成绩和鞍点)
|
1月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
19 2
|
1月前
|
C语言
链式顺序表实现(C语言描述)
本文介绍了如何在C语言中实现链式顺序表,包括数据结构的定义、节点的创建、数据的插入和删除以及链表的打印和销毁。
38 2
|
1月前
|
C语言
顺序表数组法构建(C语言描述)
如何使用C语言通过数组方法构建有序顺序表,包括顺序表的创建、插入、删除和打印等。
18 2
|
1月前
|
存储 C语言
手把手教你用C语言实现通讯录管理系统
手把手教你用C语言实现通讯录管理系统
|
2月前
|
存储 C语言 C++
数据结构基础详解(C语言) 顺序表:顺序表静态分配和动态分配增删改查基本操作的基本介绍及c语言代码实现
本文介绍了顺序表的定义及其在C/C++中的实现方法。顺序表通过连续存储空间实现线性表,使逻辑上相邻的元素在物理位置上也相邻。文章详细描述了静态分配与动态分配两种方式下的顺序表定义、初始化、插入、删除、查找等基本操作,并提供了具体代码示例。静态分配方式下顺序表的长度固定,而动态分配则可根据需求调整大小。此外,还总结了顺序表的优点,如随机访问效率高、存储密度大,以及缺点,如扩展不便和插入删除操作成本高等特点。
190 5
|
2月前
|
存储 算法 C语言
C语言手撕数据结构代码_顺序表_静态存储_动态存储
本文介绍了基于静态和动态存储的顺序表操作实现,涵盖创建、删除、插入、合并、求交集与差集、逆置及循环移动等常见操作。通过详细的C语言代码示例,展示了如何高效地处理顺序表数据结构的各种问题。
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
33 3
|
6天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
21 6