【C语言】通讯录的实现(静态, 动态, 文件)

简介: 【C语言】通讯录的实现(静态, 动态, 文件)

整体思路

本文将会用c语言实现一个通讯录的系统,并且存储若干人的信息,每个人的信息包括:姓名,性别,年龄,电话号码,住址。此通讯录系统的功能包括: 1.增加联系人 2.删除对应的联系人 3.查找联系人 4.修改联系人的信息 5.排序此通讯录 6.打印出通讯录每个人的信息


  1. 设置每一个联系人的结构体,里面存的是联系人的基本信息
  2. 然后我们想到联系人不止一个,这样就要开辟一个结构体类型的数组,然后还要有一个数字来存里面已经有了几个联系人,所以还要将这个结构体数组和数字再用一个结构体来存起来
  3. 最后就是各个细节的实现,注意:结构体传参是传址调用,这样少了重新开辟内存的一步,可以节省很多的时间。

主要函数功能:

  1. 初始化,构造出结构体数组
  2. 实现添加联系人的函数
  3. 实现删除联系人的函数
  4. 实现查找联系人的函数
  5. 实现修改联系人的函数
  6. 实现展示联系人的函数
  7. 实现排序联系人的函数


删除的思路:


删除联系人前,我们需要先判断用户输入的联系人是否存在,如果存在删除,不存在提示用户没有要删除的联系人

因此我们可以把检测联系人是否存在封装成一个函数中,如果存在,返回联系人在通讯录中的位置,不存在返回-1


添加的思路:

考虑是否需要添加容量的问题,如果需要就动态的添加内存

排序的思路:

排序就是根据我们前面学习的qsort函数来实现。

静态

直接上代码:

#define _CRT_SECURE_NO_WARNINGS
#define MAX 100
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct PeoInfo {
  char name[20];
  char sex[5];
  char tele[12];
  int age;
  char addr[30];
};
struct Contact {
  struct PeoInfo data[MAX];
  int sz;
};
//初始化
void initContact(struct Contact* pc) {
  pc->sz = 0;
  memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
}
// 添加
void AddContact(struct Contact* pc) {
  if (pc->sz == MAX) {
    printf("通讯录已满,无法添加!\n");
    return;
  }
  else {
    printf("请输入名字>\n");
    scanf("%s", pc->data[pc->sz].name);
    printf("请输入性别>\n");
    scanf("%s", pc->data[pc->sz].sex);
    printf("请输入年龄>\n");
    scanf("%d", &pc->data[pc->sz].age);
    printf("请输入电话>\n");
    scanf("%s", pc->data[pc->sz].tele);
    printf("请输入家庭地址\n");
    scanf("%s", pc->data[pc->sz].addr);
    pc->sz++;
    printf("成功添加联系人\n");
  }
}
//显示
void ShowContact(struct Contact* pc) {
  for (int i = 0; i < pc->sz; i++) {
    printf("%s %s %d %s %s\n", pc->data[i].name,
      pc->data[i].sex,
      pc->data[i].age,
      pc->data[i].tele,
      pc->data[i].addr);
  }
}
static int FindByName(struct Contact* pc, char name[]) {
  for (int i = 0; i < pc->sz; i++) {
    if (strcmp(pc->data[i].name, name) == 0) {
      return i;
    }
  }
  return -1;
}
//删除
void DelContact(struct Contact* pc) {
  char name[20];
  printf("请输入要删除人的名字\n");
  scanf("%s", name);
  int ret = FindByName(pc, name);
  if (ret == -1) {
    printf("要删除的人不存在\n");
  }
  else {
    for (int i = ret; i < pc->sz - 1; i++) {
      pc->data[i] = pc->data[i + 1];
    }
    pc->sz--;
    printf("成功删除指定联系人\n");
  }
}
//查找
void SearchContact(struct Contact* pc) {
  char name[20];
  printf("请输入要查找人的名字\n");
  scanf("%s", name);
  int ret = FindByName(pc, name);
  if (ret == -1) {
    printf("联系人不存在\n");
  }
  else {
    printf("%s %s %d %s %s\n", pc->data[ret].name,
      pc->data[ret].sex,
      pc->data[ret].age,
      pc->data[ret].tele,
      pc->data[ret].addr);
  }
}
//修改
void ModifyContact(struct Contact* pc) {
  char name[20];
  printf("请输入要修改人的名字\n");
  scanf("%s", name);
  int ret = FindByName(pc, name);
  if (ret == -1) {
    printf("要修改的人不存在\n");
  }
  else {
    printf("请输入名字>\n");
    scanf("%s", pc->data[ret].name);
    printf("请输入性别>\n");
    scanf("%s", pc->data[ret].sex);
    printf("请输入年龄>\n");
    scanf("%d", &pc->data[ret].age);
    printf("请输入电话>\n");
    scanf("%s", pc->data[ret].tele);
    printf("请输入家庭地址\n");
    scanf("%s", pc->data[ret].addr);
    printf("修改成功\n");
  }
}
int cmp(const void* e1, const void* e2) {
  return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//排序
void SortContact(struct Contact* pc) {
  qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp);
}
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");
}
int main() {
  int input = 0;
  struct Contact con;
  initContact(&con);
  do {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input) {
    case 1:
      AddContact(&con);
      break;
    case 2:
      DelContact(&con);
      break;
    case 3:
      SearchContact(&con);
      break;
    case 4:
      ModifyContact(&con);
      break;
    case 5:
      ShowContact(&con);
      break;
    case 6:
      SortContact(&con);
      break;
    case 0:
      printf("退出通讯录\n");
      break;
    default :
      printf("选择错误\n");
      break;
    }
  } while (input);
}

这里的结构体传参,就像上篇文章提到的一样,传的是地址。

动态

#define _CRT_SECURE_NO_WARNINGS
#define MAX 100
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct PeoInfo {
  char name[20];
  char sex[5];
  char tele[12];
  int age;
  char addr[30];
};
struct Contact {
  struct PeoInfo* data;
  int sz;
  int capacity;
};
//初始化
void initContact(struct Contact* pc) {
  pc->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));
  if (pc == NULL) {
    printf("开辟失败\n");
  }
  pc->sz = 0;
  pc->capacity = 3;
}
// 添加
void AddContact(struct Contact* pc) {
  if (pc->sz == pc->capacity) {
    //增加容量
    struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo));
    if (ptr != NULL) {
      pc->data = ptr;
      pc->capacity += 2;
      printf("增容成功\n");
    }
    else {
      printf("调整失败\n");
      return;
    }
  }
  printf("请输入名字>\n");
  scanf("%s", pc->data[pc->sz].name);
  printf("请输入性别>\n");
  scanf("%s", pc->data[pc->sz].sex);
  printf("请输入年龄>\n");
  scanf("%d", &pc->data[pc->sz].age);
  printf("请输入电话>\n");
  scanf("%s", pc->data[pc->sz].tele);
  printf("请输入家庭地址\n");
  scanf("%s", pc->data[pc->sz].addr);
  pc->sz++;
  printf("成功添加联系人\n");
}
//显示
void ShowContact(struct Contact* pc) {
  for (int i = 0; i < pc->sz; i++) {
    printf("%s %s %d %s %s\n", pc->data[i].name,
      pc->data[i].sex,
      pc->data[i].age,
      pc->data[i].tele,
      pc->data[i].addr);
  }
}
static int FindByName(struct Contact* pc, char name[]) {
  for (int i = 0; i < pc->sz; i++) {
    if (strcmp(pc->data[i].name, name) == 0) {
      return i;
    }
  }
  return -1;
}
//删除
void DelContact(struct Contact* pc) {
  char name[20];
  printf("请输入要删除人的名字\n");
  scanf("%s", name);
  int ret = FindByName(pc, name);
  if (ret == -1) {
    printf("要删除的人不存在\n");
  }
  else {
    for (int i = ret; i < pc->sz - 1; i++) {
      pc->data[i] = pc->data[i + 1];
    }
    pc->sz--;
    printf("成功删除指定联系人\n");
  }
}
//查找
void SearchContact(struct Contact* pc) {
  char name[20];
  printf("请输入要查找人的名字\n");
  scanf("%s", name);
  int ret = FindByName(pc, name);
  if (ret == -1) {
    printf("联系人不存在\n");
  }
  else {
    printf("%s %s %d %s %s\n", pc->data[ret].name,
      pc->data[ret].sex,
      pc->data[ret].age,
      pc->data[ret].tele,
      pc->data[ret].addr);
  }
}
//修改
void ModifyContact(struct Contact* pc) {
  char name[20];
  printf("请输入要修改人的名字\n");
  scanf("%s", name);
  int ret = FindByName(pc, name);
  if (ret == -1) {
    printf("要修改的人不存在\n");
  }
  else {
    printf("请输入名字>\n");
    scanf("%s", pc->data[ret].name);
    printf("请输入性别>\n");
    scanf("%s", pc->data[ret].sex);
    printf("请输入年龄>\n");
    scanf("%d", &pc->data[ret].age);
    printf("请输入电话>\n");
    scanf("%s", pc->data[ret].tele);
    printf("请输入家庭地址\n");
    scanf("%s", pc->data[ret].addr);
    printf("修改成功\n");
  }
}
int cmp(const void* e1, const void* e2) {
  return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//排序
void SortContact(struct Contact* pc) {
  qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp);
}
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");
}
int main() {
  int input = 0;
  struct Contact con;
  initContact(&con);
  do {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input) {
    case 1:
      AddContact(&con);
      break;
    case 2:
      DelContact(&con);
      break;
    case 3:
      SearchContact(&con);
      break;
    case 4:
      ModifyContact(&con);
      break;
    case 5:
      ShowContact(&con);
      break;
    case 6:
      SortContact(&con);
      break;
    case 0:
      free((&con)->data);
      (&con)->data = NULL;
      (&con)->capacity = 0;
      (&con)->sz = 0; 
      printf("退出通讯录\n");
      break;
    default:
      printf("选择错误\n");
      break;
    }
  } while (input);
}

这个思路是通讯录那个结构体里面多添加了一个变量,来表示容量,当通讯录里面的个数和容量相等是就要考虑增容。就用之前文章提到的malloc,realloc函数来实现。

文件

需求:

通讯录退出后,之前保存的不能丢,当下一次重新运行通讯录的时候,还能看到上次保存的信息。

具体分析:

退出的时候,把数据保存到文件中,当下一次运行的时候,再从文件中加载信息就可以了

#define _CRT_SECURE_NO_WARNINGS
#define MAX 100
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct PeoInfo {
   char name[20];
   char sex[5];
   char tele[12];
   int age;
   char addr[30];
};
struct Contact {
   struct PeoInfo* data;
   int sz;
   int capacity;
};
void LoadContact(struct Contact* pc) {
   FILE* pf = fopen("data.txt", "rb");
   if (pf == NULL) {
    perror("LoadContact::fopen");
    return;
   }
   struct PeoInfo tmp = { 0 };
   while (fread(&tmp, sizeof(struct PeoInfo), 1, pf)) {
    //考虑增容量的问题
    if (pc->sz == pc->capacity) {
      struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo));
      if (ptr != NULL) {
        pc->data = ptr;
        pc->capacity += 2;
        printf("增容成功\n");
      }
      else {
        printf("调整失败\n");
        return;
      }
    }
    pc->data[pc->sz] = tmp;
    pc->sz++;
   }
   fclose(pf);
   pf = NULL;
}
//初始化
void initContact(struct Contact* pc) {
   pc->data = (struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));
   if (pc == NULL) {
    printf("开辟失败\n");
   }
   pc->sz = 0;
   pc->capacity = 3;
   //加载文件中的信息到通讯录
   LoadContact(pc);
}
// 添加
void AddContact(struct Contact* pc) {
   if (pc->sz == pc->capacity) {
    //增加容量
    struct PeoInfo* ptr = (struct PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(struct PeoInfo));
    if (ptr != NULL) {
      pc->data = ptr;
      pc->capacity += 2;
      printf("增容成功\n");
    }
    else {
      printf("调整失败\n");
      return;
    }
   }
   printf("请输入名字>\n");
   scanf("%s", pc->data[pc->sz].name);
   printf("请输入性别>\n");
   scanf("%s", pc->data[pc->sz].sex);
   printf("请输入年龄>\n");
   scanf("%d", &pc->data[pc->sz].age);
   printf("请输入电话>\n");
   scanf("%s", pc->data[pc->sz].tele);
   printf("请输入家庭地址\n");
   scanf("%s", pc->data[pc->sz].addr);
   pc->sz++;
   printf("成功添加联系人\n");
}
//显示
void ShowContact(struct Contact* pc) {
   for (int i = 0; i < pc->sz; i++) {
    printf("%s %s %d %s %s\n", pc->data[i].name,
      pc->data[i].sex,
      pc->data[i].age,
      pc->data[i].tele,
      pc->data[i].addr);
   }
}
static int FindByName(struct Contact* pc, char name[]) {
   for (int i = 0; i < pc->sz; i++) {
    if (strcmp(pc->data[i].name, name) == 0) {
      return i;
    }
   }
   return -1;
}
//删除
void DelContact(struct Contact* pc) {
   char name[20];
   printf("请输入要删除人的名字\n");
   scanf("%s", name);
   int ret = FindByName(pc, name);
   if (ret == -1) {
    printf("要删除的人不存在\n");
   }
   else {
    for (int i = ret; i < pc->sz - 1; i++) {
      pc->data[i] = pc->data[i + 1];
    }
    pc->sz--;
    printf("成功删除指定联系人\n");
   }
}
//查找
void SearchContact(struct Contact* pc) {
   char name[20];
   printf("请输入要查找人的名字\n");
   scanf("%s", name);
   int ret = FindByName(pc, name);
   if (ret == -1) {
    printf("联系人不存在\n");
   }
   else {
    printf("%s %s %d %s %s\n", pc->data[ret].name,
      pc->data[ret].sex,
      pc->data[ret].age,
      pc->data[ret].tele,
      pc->data[ret].addr);
   }
}
//修改
void ModifyContact(struct Contact* pc) {
   char name[20];
   printf("请输入要修改人的名字\n");
   scanf("%s", name);
   int ret = FindByName(pc, name);
   if (ret == -1) {
    printf("要修改的人不存在\n");
   }
   else {
    printf("请输入名字>\n");
    scanf("%s", pc->data[ret].name);
    printf("请输入性别>\n");
    scanf("%s", pc->data[ret].sex);
    printf("请输入年龄>\n");
    scanf("%d", &pc->data[ret].age);
    printf("请输入电话>\n");
    scanf("%s", pc->data[ret].tele);
    printf("请输入家庭地址\n");
    scanf("%s", pc->data[ret].addr);
    printf("修改成功\n");
   }
}
int cmp(const void* e1, const void* e2) {
   return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//排序
void SortContact(struct Contact* pc) {
   qsort(pc->data, pc->sz, sizeof(struct PeoInfo), cmp);
}
void SaveContact(struct Contact* pc) {
   FILE* pf = fopen("data.txt", "wb");
   if (pf == NULL) {
    perror("SaveContact::fopen");
    return;
   }
   for (int i = 0; i < pc->sz; i++) {
    fwrite(pc->data + i, sizeof(struct PeoInfo), 1, pf);
   }
   fclose(pf);
   pf = NULL;
} 
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");
}
int main() {
   int input = 0;
   struct Contact con;
   initContact(&con);
   do {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input) {
    case 1:
      AddContact(&con);
      break;
    case 2:
      DelContact(&con);
      break;
    case 3:
      SearchContact(&con);
      break;
    case 4:
      ModifyContact(&con);
      break;
    case 5:
      ShowContact(&con);
      break;
    case 6:
      SortContact(&con);
      break;
    case 0:
      SaveContact(&con);
      free((&con)->data);
      (&con)->data = NULL;
      (&con)->capacity = 0;
      (&con)->sz = 0;
      printf("退出通讯录\n");
      break;
    default:
      printf("选择错误\n");
      break;
    }
   } while (input);
}

文件操作终于学了,这篇文章也到了真正收尾的时候啦

相关文章
|
1月前
|
Linux C语言
C语言获取文件长度
C语言获取文件长度
|
1月前
|
编译器 开发工具 C语言
【C语言】第一回(源(.c)文件怎么生成可执程序(.exe)文件)
【C语言】第一回(源(.c)文件怎么生成可执程序(.exe)文件)
|
2月前
|
安全 算法 程序员
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
49 0
|
2月前
|
C语言
用c语言实现一个通讯录
用c语言实现一个通讯录
11 0
|
2月前
|
存储 C语言
C语言详解【通讯录的实现】
C语言详解【通讯录的实现】
|
2月前
|
C语言
C语言对文件的输入输出
C语言对文件的输入输出
18 0
|
4天前
|
存储 C语言 C++
【C语言】文件与文件操作
前言:我们通过学习的技术可以完成计算与字符串处理,但程序结束之后就都消失了,这样岂不可惜。我们通过文件与数据持久化保存相关的基础知识。
8 0
|
12天前
|
存储 C语言
C语言进阶第十课 --------文件的操作-2
C语言进阶第十课 --------文件的操作
|
12天前
|
存储 编译器 C语言
C语言进阶第十课 --------文件的操作-1
C语言进阶第十课 --------文件的操作
|
13天前
|
C语言
C语言进阶第八课 --------通讯录的实现
C语言进阶第八课 --------通讯录的实现