C实现通讯录(静态版+动态版)(一)

简介: C实现通讯录(静态版+动态版)

一、静态版


1.大体思路


我们知道基本的通讯录应该可以记录一个人的基本信息,比如:姓名、性别、年龄、电话号码、住址等,这个通讯录应该有大小上限的,我们就先在头文件中定义个结构体,里面包含了每个人的基本信息。如下:


struct Information
{
  char name[20];
  char sex[6];
  int age;
  char tele[12];   //电话
  char addr[30];   //住址
};


这是一个人的基本信息,假设我们要存储100人,那么我们怎么办呢?

我们可以再定义一个结构体,这个结构体包含了一个上面结构体的数组,还包含了一个计数元素 sz ,如下:


struct contacts
{
  struct Information data[100];      //定义一个数组,该数组可以存放100人信息
  int sz;                            //当我们添加或删减数据时,sz 相应的++--,sz 应该从零开始记录下一个要添加元素的下标(后面初始化置零)
};


联系人存放问题解决了,接下来应该让通讯录初始化,也就是将其数据清零,方便我们存储,再然后就是增加、删减、查找联系人了。大体思路就这样。


2.主程序


在主程序中,我们要实现菜单的打印,及一个do while循环,我们知道添加联系人这个程序最少要执行一次,根据需求可多次执行,do while循环就正好可以。

代码:


void menu()
{     //菜单显示 1.增加、2.删减、3.查找、4.修改、5.显示、6.排序、0.退出
  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");
}
int main()
{
  int input = 0;
  struct contacts con;   //定义一个结构体变量 con
  do
  {
  menu();
  printf("请输入:>");
  scanf("%d", &input);
  switch (input)         //根据 input 对应值来跳转到相应语句
  {
  case 1:
    break;
  case 2:
    break;
  case 3:
    break;
  case 4:
    break;
  case 5:
    break;
  case 6:
    break;
  case 0:
    break;
  default:      //输入数字不在0~6范围内
    break;
  }
  } while (input);     //若 input 为0,也就是退出程序,while 循环也会退出
  return 0;
}


我们看这个 case 后面是数字不够直观,那么有什么办法呢?

我们之前讲过枚举,我们可以用枚举来解决这个问题,如下:


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");
}
enum Option
{
  EXIT,   //0
  ADD,    //1
  DEL,    //2
  SEARCH,
  MODIFY,
  SHOW,
  SORT
};
int main()
{
  int input = 0;
  struct contacts con;
  do
  {
  menu();
  printf("请输入:>");
  scanf("%d", &input);
  switch (input)
  {
  case ADD:
    break;
  case DEL:
    break;
  case SEARCH:
    break;
  case MODIFY:
    break;
  case SHOW:
    break;
  case SORT:
    break;
  case EXIT:
    break;
  default:
    break;
  }
  } while (input);
  return 0;
}

我们知道存放数据之前应该初始化一下,将 con 的数据清零,我们应该设计一个初始化函数,那应该传con的地址呢,还是直接传con?因为我们要对其进行修改,所以传地址。

我们下面的函数也应该的传con的地址。

main函数如下:


int main()
{
  int input = 0;
  struct contacts con;
  chu_shi(&con);    //初始化
  do
  {
  menu();
  printf("请输入:>");
  scanf("%d", &input);
  switch (input)
  {            //每个模块都有对应函数实现
  case ADD:
    Add(&con);
    break;
  case DEL:
    Del(&con);
    break;
  case SEARCH:
    Search(&con);
    break;
  case MODIFY:
    Modify(&con);
    break;
  case SHOW:
    Show(&con);
    break;
  case SORT:
    Sort(&con);
    break;
  case EXIT:
    break;
  default:
    printf("输入错误\n");      //提示一下
    break;
  }
  } while (input);
  return 0;
}


3.函数实现


3.1初始化函数

我们可以所以 memset 函数来实现:


void chu_shi(struct contacts* pc)
{      
  assert(pc);   //避免pc为空指针,加个断言,需添加头文件:assert.h
  memset(pc->data, 0, 100 * sizeof(struct Information));    //使用memset函数需包含头文件:string.h
  pc->sz = 0;
}


初始化如下:


2fa6e0b3800148caa602614713acdd41.png


3.2增加函数(Add)

void Add(struct contacts* pc)
{
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[pc->sz].name);   //输入字符串时,数组名即是首元素地址
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[pc->sz].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[pc->sz].age));      //输入整数时要取地址
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[pc->sz].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[pc->sz].addr);
  printf("添加成功\n");
  pc->sz++;         //每次添加,sz 便 +1
}

3.3删除函数(Del)

要实现删减联系人,首先我们要找到这个联系人吧,我们写一个函数来专门查找联系人:


int cha_zhao(const struct contacts* pc, char* name)  //通过名字查找
{
  int i = 0;
  for (i; i < pc->sz; i++)
  {
  if (strcmp(pc->data[i].name, name) == 0)
    return i;
  }
  return -1;      //找到返回对应下标,否则返回-1
}


有了返回值,我们就好写出以下代码:


void Del(struct contacts* pc)
{
  char name[20];
  printf("请输入要删除的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);     // m 接收返回值
  if (m != -1)
  {
  pc->data[m] = pc->data[pc->sz-1];    //将最后的元素覆盖到 m 下标的元素处,实现删除
  pc->sz--;                    // sz 对应减一
  printf("删除成功\n");
  }
  else
  printf("没有该联系人\n");
}


除了将最后一个数据往前覆盖,我们还能将后面的数据整体向前移一位来实现删除,还可以用memmove函数来向前平移一个单位长度。


3.4查找函数(Search)

跟删除函数类似:


void Search(const struct contacts* pc)   
{            //无需对数据进行修改,所以加上const进行修饰,防止对其进行修改
  char name[20];
  printf("请输入要查看的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {       // %-20s里的-20是左对齐20个字符的意思,换成20则是右对齐,\t是水平制表符
  printf("%-20s\t%-6s\t%-4s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "住址");
  printf("%-20s\t%-6s\t%-4d\t%-12s\t%-30s\n", pc->data[m].name, 
    pc->data[m].sex, pc->data[m].age, 
    pc->data[m].tele, pc->data[m].addr);
  }
  else
  printf("没有该联系人\n");
}

看看实际效果:


338cd780f9ed49dfb004ea34b3608396.png


3.5修改函数(Modify)

void Modify(struct contacts* pc)
{
  char name[20];
  printf("请输入要修改的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[m].name);
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[m].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[m].age));
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[m].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[m].addr);
  printf("添加成功\n");
  }
  else
  printf("没有该联系人\n");
}


3.6显示函数(Show)

void Show(const struct contacts* pc)
{
  int i = 0;
  printf("%-20s\t%-6s\t%-4s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "住址");
  for (i; i < pc->sz; i++)
  {
  printf("%-20s\t%-6s\t%-4d\t%-12s\t%-30s\n", pc->data[i].name,
    pc->data[i].sex, pc->data[i].age,
    pc->data[i].tele, pc->data[i].addr);
  }
}


3.7排序函数(Sort)

排序我们可以用名字排,也可以用年龄、电话等来排序,我们就用名字排序吧。


int bi_jiao(const void* e1, const void* e2)
{
  return strcmp(((struct Information*)e1)->name, ((struct Information*)e2)->name);
}
void Sort(struct contacts* pc)
{
  qsort(pc->data, pc->sz, sizeof(struct Information), bi_jiao);
}

qsort函数在指针进阶(续)里有讲过,这里就不多介绍了。


4.总代码


4.1 test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contacts.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");
}
enum Option
{
  EXIT,
  ADD,
  DEL,
  SEARCH,
  MODIFY,
  SHOW,
  SORT
};
int main()
{
  int input = 0;
  struct contacts con;
  chu_shi(&con);
  do
  {
  menu();
  printf("请输入:>");
  scanf("%d", &input);
  switch (input)
  {
  case ADD:
    Add(&con);
    break;
  case DEL:
    Del(&con);
    break;
  case SEARCH:
    Search(&con);
    break;
  case MODIFY:
    Modify(&con);
    break;
  case SHOW:
    Show(&con);
    break;
  case SORT:
    Sort(&con);
    break;
  case EXIT:
    break;
  default:
    printf("输入错误\n");
    break;
  }
  } while (input);
  return 0;
}


4.2 contacts.h

为了方便我们修改名字、性别等字符串长度,我们可以用#define来定义一下,便于后期修改。


#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
struct Information
{
  char name[MAX_NAME];
  char sex[MAX_SEX];
  int age;
  char tele[MAX_TELE];
  char addr[MAX_ADDR];
};
struct contacts
{
  struct Information data[MAX];
  int sz;
};
//初始化通讯录
void chu_shi(struct contacts* pc);
//增加联系人
void Add(struct contacts* pc);
//删除联系人
void Del(struct contacts* pc);
//查找联系人
void Search(const struct contacts* pc);
//修改联系人
void Modify(struct contacts* pc);
//显示联系人
void Show(const struct contacts* pc);
//名字排序
void Sort(struct contacts* pc);


4.3 contacts.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"contacts.h"
void chu_shi(struct contacts* pc)
{
  assert(pc);
  memset(pc->data, 0, MAX * sizeof(struct Information));
  pc->sz = 0;
}
void Add(struct contacts* pc)
{
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[pc->sz].name);
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[pc->sz].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[pc->sz].age));
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[pc->sz].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[pc->sz].addr);
  printf("添加成功\n");
  pc->sz++;
}
int cha_zhao(const struct contacts* pc, char* name)
{
  int i = 0;
  for (i; i < pc->sz; i++)
  {
  if (strcmp(pc->data[i].name, name) == 0)
    return i;
  }
  return -1;
}
void Del(struct contacts* pc)
{
  char name[20];
  printf("请输入要删除的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  pc->data[m] = pc->data[pc->sz-1];
  pc->sz--;
  printf("删除成功\n");
  }
  else
  printf("没有该联系人\n");
}
void Search(const struct contacts* pc)
{
  char name[20];
  printf("请输入要查看的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  printf("%-20s\t%-6s\t%-4s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "住址");
  printf("%-20s\t%-6s\t%-4d\t%-12s\t%-30s\n", pc->data[m].name, 
    pc->data[m].sex, pc->data[m].age, 
    pc->data[m].tele, pc->data[m].addr);
  }
  else
  printf("没有该联系人\n");
}
void Modify(struct contacts* pc)
{
  char name[20];
  printf("请输入要修改的联系人:>");
  scanf("%s", name);
  int m = cha_zhao(pc, name);
  if (m != -1)
  {
  printf("请输入联系人姓名:>");
  scanf("%s", pc->data[m].name);
  printf("请输入联系人性别:>");
  scanf("%s", pc->data[m].sex);
  printf("请输入联系人年龄:>");
  scanf("%d", &(pc->data[m].age));
  printf("请输入联系人电话:>");
  scanf("%s", pc->data[m].tele);
  printf("请输入联系人住址:>");
  scanf("%s", pc->data[m].addr);
  printf("添加成功\n");
  }
  else
  printf("没有该联系人\n");
}
void Show(const struct contacts* pc)
{
  int i = 0;
  printf("%-20s\t%-6s\t%-4s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "住址");
  for (i; i < pc->sz; i++)
  {
  printf("%-20s\t%-6s\t%-4d\t%-12s\t%-30s\n", pc->data[i].name,
    pc->data[i].sex, pc->data[i].age,
    pc->data[i].tele, pc->data[i].addr);
  }
}
int bi_jiao(const void* e1, const void* e2)
{
  return strcmp(((struct Information*)e1)->name, ((struct Information*)e2)->name);
}
void Sort(struct contacts* pc)
{
  qsort(pc->data, pc->sz, sizeof(struct Information), bi_jiao);
}


效果图:

138b9accb0a24940a3fa9b28d75c50ea.png


相关文章
|
6月前
【C进阶】通讯录的实现(静态+动态)(上)
【C进阶】通讯录的实现(静态+动态)(上)
|
4月前
|
存储 编译器 C语言
通讯录详解(静态版,动态版,文件版)
通讯录详解(静态版,动态版,文件版)
21 0
|
6月前
【C进阶】通讯录的实现(静态+动态)(中)
【C进阶】通讯录的实现(静态+动态)(中)
|
6月前
【C进阶】通讯录的实现(静态+动态)(下)
【C进阶】通讯录的实现(静态+动态)(下)
|
6月前
|
存储
【静态通讯录】
【静态通讯录】
12 0
|
8月前
C实现通讯录(静态版+动态版)(二)
C实现通讯录(静态版+动态版)
20 0
|
8月前
|
存储
通讯录(静态版)
通讯录(静态版)
|
9月前
|
C语言
C/【静态通讯录】
C/【静态通讯录】
|
10月前
|
C语言
静态通讯录
C语言学习——教你学会静态通讯录的实现(保姆级教程哦~)
|
10月前
通讯录(静态版)(二)
大家好,有好久没有带大家一起搞实战的编程了,今天就给大家带来一个简单的通讯录小系统
46 0