C语言实现多功能通讯录

功能

  • 添加联系人(Addcontacts)
    • 载入联系人信息(Loadcontacts)
  • 查找联系人(Searchtacts)
    • 通过姓名关键字查找
    • 通过手机号码关键字查找
  • 修改联系人(Modifytacts)
  • 排序联系人(Sortcontacts)
  • 删除联系人(Deletecontacts)
  • 显示联系人(Showcontacts)
  • 保存并退出(Savecontacts)
  • 回收站(TRASH)

思路和关键模块介绍

思路
用C语言实现通讯录,那么最先知道每个联系人得信息:

  1. 姓名
  2. 性别
  3. 年龄
  4. 电话

所以我们需要先定义一个结构体struct Peinfo来存储每个联系人得基本信息,再通过结构体数组得方式把联系人信息存储起来.在操作结束得时候,通过fwirte函数将有效得联系人信息写入到文件里,再次打开得时候通过fread函数将联系人信息导入,实现了基本通讯录得搭建流程。

关键模块介绍
为了不让空间浪费,我们不能直接通过指定结构体数组得方式来进行定义,为了解决这个问题,通过callocralloc函数来动态开辟存储联系人信息。所以,在我们需要再次定义一个结构体,用于记录当前通讯录得各种基本状态。

#define FILENAME "r.dat"
#define NAME_MAX 20
#define SEX_LEN 6
#define TEL_LEN 11
#define DEFAU_SIZE 3
#define UP_SUCCESS 1
#define UP_FAIL -1
typedef struct Peinfo
{
    char name[NAME_MAX];
    int age;
    char sex[SEX_LEN];
    char tel[TEL_LEN];
    int flag;
}Peinfo;
typedef struct contact
{
    Peinfo* data;//用于存储联系人信息得结构体指针。
    int count;//当前联系人个数
    int cap;//扩容边界
    int trash;//回收站信息计数。
}

void Trash(pCTT p) 回收站功能
对于顺序表结构,删除元素十分麻烦。既然要实现通讯录得删除联系人功能并且具有回收站,那么只需要在联系人信息得结构体里定义个删除标记,即FLAG,当要删除联系人时,直接将flag置1,在通过trash来记录即可。当要彻底删除时,使用qsort以每个联系得flag来进行排序,那么有删除标记的联系人就将在最后,讲count减去trash最后写出count个进入文件,即实现了回收站的功能。

void Trash(pCTT p)
{
    if (0 == p->count || p->trash == 0)
    {
        printf("Nothing here.\n");
    }

    else
    {
        printf("contacts in Trash->%d \n", p->trash);
        printf("\n******\n");
        int i = 0;
        int choose = 0;
        for (i = 0; i < p->count; i++)//打印信息
        {
            if (1 == p->data[i].flag)
            {
                printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
                printf("\n******\n");
            }
        }
        printf("1. remove all \n2. recover all ");
        scanf("%d", &choose);
        switch (choose)
        {
        case 1:
            move(p);
            break;
        case 2:
            recover(p);
            break;
        default:
            printf("IPUT ERROR");
            break;
        }
    }
}
int cmptrash(const void* str1, const void* str2)
{
    return ((Peinfo*)str1)->flag - ((Peinfo*)str2)->flag;
}
void move(pCTT p)
{
    qsort(p->data, p->count, sizeof(Peinfo), cmptrash);//将有删除标记得放在最后
    p->count -= p->trash;
    p->trash = 0;
    printf("Trash has been cleaned up");
}

void recover(pCTT p)
{
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        if (1 == p->data[i].flag)
        {
            p->data[i].flag = 0;
            p->trash--;
        }
    }
    printf("Recover done");
}

void Searchcontact(pCTT p);·搜索联系人
对于搜索而言,部分关键字查找既方便又可以实现多个预览。使用strstr函数来进行关键字查找

void Searchcontact(pCTT p)
{
    if (0 == p->count)
    {
        printf("There have no contact\n ");
    }
    else
    {
        int key = 0;
        printf("1.Searching by TEL \n2.Searching by Name\n ");
        scanf("%d", &key);
        switch (key)
        {
        case 1:
            Telsearch(p);
            break;
        case 2:
            Namesearch(p);
            break;
        }
    }
}
void Telsearch(pCTT p)
{
    char find[TEL_LEN] = { 0 };
    int flag = 0;
    printf("Pleasr enter TEL in part or full->");
    scanf("%s", find);
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
        {
            continue;
        }
        if (strstr(p->data[i].tel, find) != NULL)
        {
            printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
            printf("\n******\n");
            flag++;
        }
    }
    if (0 == flag)
    {
        printf("No result from your enter ");
    }
}
void Namesearch(pCTT p)
{
    char find[NAME_MAX] = { 0 };
    int flag = 0;
    printf("Please enter Name->");
    scanf("%s", find);
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
        {
            continue;
        }
        if (strstr(p->data[i].name, find) != NULL)
        {
            printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
            printf("\n******\n");
            flag++;
        }
    }
    if (0 == flag)
    {
        printf("No result from your enter ");
    }
}

程序代码

contact.h函数原型

#pragma once
#define FILENAME "r.dat"
#define NAME_MAX 20
#define SEX_LEN 6
#define TEL_LEN 11
#define DEFAU_SIZE 3
#define UP_SUCCESS 1
#define UP_FAIL -1
typedef struct Peinfo
{
    char name[NAME_MAX];
    int age;
    char sex[SEX_LEN];
    char tel[TEL_LEN];
    int flag;
}Peinfo;
typedef struct contact
{
    Peinfo* data;
    int count;
    int cap;
    int trash;//用于记录回收站是否有内容
}CTT,*pCTT;
//初始化通讯录
//添加信息
//查找信息
//修改信息
//排序
//删除
//回收站
//显示
//文件写入写出
void Init(pCTT p);
void Showcontact(pCTT p);
void Addcontact(pCTT p);
int Checkcontact(pCTT p);
void Loadcontact(pCTT p);
void Searchcontact(pCTT p);
void Savecontact(pCTT p);
void Telsearch(pCTT p);
void Namesearch(pCTT p);
void modify(pCTT p);
void Sortcon(pCTT p);    
int cmp(const void* str1, const void* str2);
void Delete(pCTT p);
void Trash(pCTT p);
void move(pCTT p);
int cmptrash(const void* str1, const void* str2);
void recover(pCTT p);

contact.c函数定义

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include "contact.h"
#include<string.h>

void Init(pCTT p)
{
    p->cap = DEFAU_SIZE;
    p->count = 0;
    p->data = (Peinfo*)calloc(sizeof(Peinfo), p->cap); //此处每次更新后需要初始化空间
    p->trash = 0;
    Loadcontact(p);

}
void Showcontact(pCTT p)
{
    if (0 == p->count)
    {
        printf("There have no contact.\n");
    }
    else
    {
        printf("Number of contacts->%d \n", p->count - p->trash);//有效信息数目
        printf("\n******\n");

        int i = 0;
        for (i = 0; i < p->count; i++)
        {
            if (0 == p->data[i].flag)
            {
                printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
                printf("\n******\n");
            }
        }
    }
}

void Addcontact(pCTT p)
{
    if (UP_FAIL == Checkcontact(p))
    {
        printf("Increase capacity failed");
        return;
    }
    else if (UP_SUCCESS == Checkcontact(p))
    {
        printf("Increase capacity success");
    }
    printf("Please enter Name:>");
    scanf("%s", p->data[p->count].name);
    printf("Please enter Age:>");
    scanf("%d", &(p->data[p->count].age));
    printf("Please enter sex:>");
    scanf("%s", p->data[p->count].sex);
    printf("Please enter TEL:>");
    scanf("%s", p->data[p->count].tel);
    p->data[p->count].flag = 0;//至关重要relloc后新内存flag为随机值
    p->count++;//有效大小加1
    printf("Add acontact success.\n");
}

int Checkcontact(pCTT p)
{
    if (p->count >= p->cap)
    {
        Peinfo* tmp = (Peinfo*)realloc(p->data, sizeof(Peinfo)*(p->count + 2));
        if (tmp != NULL)
        {
            p->data = tmp;
            tmp = NULL;
            p->cap =p->count+2;//在进行扩容后更新cap大小。
            //切记,relloc后空间内容为随机值
            return UP_SUCCESS;
        }
        else {
            printf("contacts increase failed");
            return UP_FAIL;
        }
    }
    return 0;
}

void Loadcontact(pCTT p)
{
    FILE *fp = (FILENAME, "r");
    if (NULL == fp)
    {
        perror("Load data");
        exit(EXIT_FAILURE);
    }
    Peinfo tmp = { 0 };
    while (fread(&tmp, sizeof(Peinfo), 1, fp))//防止文件为空或者出错读取
    {
        Checkcontact(p);
        p->data[p->count] = tmp;
        if (p->data[p->count].flag == 1)
        {
            p->trash++;
        }
        p->count++;
    }
    fclose(fp);
    fp = NULL;
}

void Searchcontact(pCTT p)
{
    if (0 == p->count)
    {
        printf("There have no contact\n ");
    }
    else
    {
        int key = 0;
        printf("1.Searching by TEL \n2.Searching by Name\n ");
        scanf("%d", &key);
        switch (key)
        {
        case 1:
            Telsearch(p);
            break;
        case 2:
            Namesearch(p);
            break;
        }
    }
}

void Savecontact(pCTT p)
{
    FILE *fp=fopen(FILENAME, "W");
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        fwrite(p->data + i, sizeof(Peinfo), 1, fp);
    }
    fclose(fp);
    fp = NULL;
    free(p->data); //别忘了释放
    p->data = NULL;
}

void Telsearch(pCTT p)
{
    char find[TEL_LEN] = { 0 };
    int flag = 0;
    printf("Pleasr enter TEL in part or full->");
    scanf("%s", find);
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
        {
            continue;
        }
        if (strstr(p->data[i].tel, find) != NULL)
        {
            printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
            printf("\n******\n");
            flag++;
        }
    }
    if (0 == flag)
    {
        printf("No result from your enter ");
    }
}
void Namesearch(pCTT p)
{
    char find[NAME_MAX] = { 0 };
    int flag = 0;
    printf("Please enter Name->");
    scanf("%s", find);
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
        {
            continue;
        }
        if (strstr(p->data[i].name, find) != NULL)
        {
            printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
            printf("\n******\n");
            flag++;
        }
    }
    if (0 == flag)
    {
        printf("No result from your enter ");
    }
}
void modify(pCTT p)
{
    if (0 == p->count)
    {
        printf("There have no contact.\n");
    }
    else
    {
        char find[NAME_MAX] = { 0 };
        int i = 0;
        printf("Please enter name whose you wanna modify\n");
        scanf("%s", find);
        int key = 0;
        for (i = 0; i < p->count; i++)
        {
            if (1 == p->data[i].flag)//如果已经被加上删除标记那么则跳过
            {
                continue;
            }
            if (strcmp(p->data[i].name, find) == 0)
            {
                printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
                printf("\nModify select:\n1.Name\n2.tel\n");
                scanf("%d", &key);
                switch (key)
                {
                case 1:
                    printf("Please enter Name:>");
                    scanf("%s", p->data[i].name);
                    break;
                case 2:
                    printf("Please enter TEL:>");
                    scanf("%s", p->data[i].tel);
                    break;

                default:
                    printf("WRONG NUM");
                    break;
                }
                return;
            }
        }
        printf("No result");
    }
}

void Sortcon(pCTT p)
{
    if (2 >= p->count)
    {
        printf("There have no contact.");
    }
    else
    {
        qsort(p->data, p->count, sizeof(Peinfo), cmp);

        printf("Sort done");
    }
}
int cmp(const void* str1, const void* str2)
{
    return strcmp(((Peinfo*)str1)->name, ((Peinfo*)str2)->name);
}

void Delete(pCTT p)
{
    if (0 == p->count)
    {
        printf("There have no contact.\n");
    }
    else
    {
        char find[NAME_MAX] = { 0 };
        int i = 0;
        printf("Just give me a exact name\n");
        scanf("%s", find);
        for (i = 0; i < p->count; i++)
        {
            if (0 == strcmp(p->data[i].name, find))
            {
                p->data[i].flag = 1;  //将目标单元信息组中得删除标记置1 
                p->trash++;
                printf("Target has been remove to TRASH\n");
                return;
            }
        }
        printf("Not found\n");
    }

}

void Trash(pCTT p)
{
    if (0 == p->count || p->trash == 0)
    {
        printf("Nothing here.\n");
    }

    else
    {
        printf("contacts in Trash->%d \n", p->trash);
        printf("\n******\n");
        int i = 0;
        int choose = 0;
        for (i = 0; i < p->count; i++)//打印信息
        {
            if (1 == p->data[i].flag)
            {
                printf("Name:%10s Age:%3d Sex:%3s TEL:%s", p->data[i].name, p->data[i].age, p->data[i].sex, p->data[i].tel);
                printf("\n******\n");
            }
        }
        printf("1. remove all \n2. recover all ");
        scanf("%d", &choose);
        switch (choose)
        {
        case 1:
            move(p);
            break;
        case 2:
            recover(p);
            break;
        default:
            printf("IPUT ERROR");
            break;
        }
    }

}

void move(pCTT p)
{
    qsort(p->data, p->count, sizeof(Peinfo), cmptrash);//将有删除标记得放在最后
    p->count -= p->trash;
    p->trash = 0;
    printf("Trash has been cleaned up");
}

void recover(pCTT p)
{
    int i = 0;
    for (i = 0; i < p->count; i++)
    {
        if (1 == p->data[i].flag)
        {
            p->data[i].flag = 0;
            p->trash--;
        }
    }
    printf("Recover done");
}


int cmptrash(const void* str1, const void* str2)
{
    return ((Peinfo*)str1)->flag - ((Peinfo*)str2)->flag;
}

main.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include "contact.h"

void menu()
{
    printf("***********************************\n");
    printf("********1. ADD   contacts   *******\n");
    printf("********2.Search contacts   *******\n");
    printf("********3.Modify contacts   *******\n");
    printf("********4. Sort  contacts   *******\n");
    printf("********5. Show  contacts   *******\n");
    printf("********6.Delete contacts   *******\n");
    printf("********7.    TRASH         *******\n");
    printf("******** 0.SAVE AND EXIT   ********\n");
    printf("***********************************\n");
}
int main()
{

    int option;
    CTT contact;
    Init(&contact);
    char a = 0;

    do
    {
        menu();
        printf("Enter right sequence number to operate->");

        while (scanf("%d", &option) != 1)
        {
            printf("input error\n");
            scanf("%*[^\n]*c");
        }
        void(*arrfun[])(pCTT) = { Savecontact, Addcontact,Searchcontact,modify,Sortcon,Showcontact,Delete,Trash };
        if (option >= 0 && option < sizeof(arrfun))
        {
            arrfun[option](&contact);
        }
    } while (option);
    system("pause");
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值