【C语言】动态顺序表 + 文件存储 = 通讯录


前言

在前面曾用静态、动态顺序表两种方式实现通讯录,但每次运行程序我们都得重新输入,之前输入的成员信息并不会保存,而现实中,通讯录里的信息创建后是永久保存的,除非你删除它,今天我们就来模拟一下如何将数据存储在文件中,当下一次运行时加载一下即可,这种做法更贴合实际。

程序中会用到与文件操作相关的函数,提前介绍一下:

  • fopen 它的函数原型为:FILE*fopen(const char *filename,const char *mode) ,filename:创建文件的名字;mode:允许进入文件的类型;简单来说这个文件的作用就是打开一个文件流;与fclose:关闭文件流配套使用.
  • perror: 它的函数原型为:void perror(const char * string) ,这是一种报告文件错误的函数;后面包括一个分号和一个空格,然后打印出一条用于解释errno当前错误代码的信息;
  • fwrite: 它的函数原型为:size_t fwrite(const void *buffer,size_t size,size_t count,FILE*stream) ,buffer:数据写入的体格缓冲区;

通讯录简要功能:

  • 初始化通讯录
  • 添加联系人
  • 查找联系人
  • 删除联系人
  • 修改联系人
  • 按姓名排序
  • 清空联系人
  • 联系人列表
  • 检查容量
  • 加载文件
  • 保存文件
  • 销毁通讯录
  • 退出

参考代码:

Contact.h

/***********************************************************
*                      程序名称:通讯录(静态顺序表)         *
*                      编译环境:VS2013                     *
*                      编制日期:2018.5.29                  *
*                                      -----by Hunter     *
***********************************************************/


#ifndef __CONTACT_H__
#define __CONTACT_H__

#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

enum OPPTION
{
    EXIT,
    ADD,
    SEARCH,
    DEIETE,
    MODIFY,
    SORT,
    SHOW,
    EMPTY
};

typedef char datatype;

#define MAX_NAME 10
#define MAX_SEX 5
#define MAX_TEL 11
#define MAX_ADDR 30
#define MAX_SIZE 1000

#define FILE_NAME  "contact.dat"

typedef struct PeoInfo
{
    datatype Name[MAX_NAME];
    datatype Sex[MAX_SEX];
    int age;
    datatype Tel[MAX_TEL];
    datatype Addr[MAX_ADDR];
}PeoInfo, *pPeoInfo;

typedef struct Contact
{
    pPeoInfo data;
    int size;
    int capacity;
}Contact, *pContact;

//初始化通讯录
void InitContact(pContact pc);
//添加联系人
void AddContact(pContact pc);
//删除联系人
void DeleteContact(pContact pc);
//查找联系人
int SearchContact(pContact pc);
//修改联系人
void ModifyContact(pContact pc);
//按姓排序
void SortContact(pContact pc);
//列表联系人
void ShowContact(pContact pc);
//清空联系人
void EmptyContact(pContact pc);
//销毁
void DestoryContact(pContact pc);
//加载
void LoadContact(pContact pc);
//保存
void SaveContact(pContact pc);

#endif //__CONTACT_H__
~~~

Contact.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"


//检查扩容
void CheckCapacity(pContact pc)
{
    assert(pc);
    pPeoInfo *p = NULL;
    if (pc->size == pc->capacity)
    {
        p = (pPeoInfo)realloc(pc->data, (pc->capacity + 2)*sizeof(PeoInfo));
        if (p != NULL)
        {
            pc->data = p;

        }
        else
        {
            printf("\t\t\t增容失败");
            exit(EXIT_FAILURE);
        }

        pc->capacity += 2;
        printf("\t\t\t增容成功\n");
    }
}
//加载
void LoadContact(pContact pc)
{   
    int i = 0;
    FILE* pfRead = fopen("contact.dat", "r");
    PeoInfo tmp = { 0 };   //创建临时变量保存每次读取的信息
    assert(pc);
    if (pfRead == NULL)
    {
        perror("the file to read");
        exit(EXIT_FAILURE);
    }

    while (fread(&tmp, sizeof(PeoInfo), 1, pfRead))
    {
            CheckCapacity(pc);
            pc->data[i] = tmp;
            i++;
            pc->size++;
    }

    fclose(pfRead);
    pfRead = NULL;

}
//保存
void SaveContact(pContact pc)
{
    assert(pc);
    FILE *pfwrite = fopen("contact.dat", "w");
    int i = 0;
    if (pfwrite == NULL)
    {
        perror("the file to write");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i<pc->size; i++)
    {
        fwrite(pc->data+ i, sizeof(PeoInfo), 1, pfwrite);
    }
    fclose(pfwrite);
    pfwrite = NULL;

}

//初始化通讯录
void InitContact(pContact pc)
{
    assert(pc);
    pc->size = 0;
    pc->capacity = 3;
    pc->data = (pPeoInfo)malloc((pc->capacity)*sizeof(PeoInfo));
    if (pc->data == NULL)
    {
        printf("\t\t\t内存分配失败");
        exit(EXIT_FAILURE);
    }
    memset(pc->data, 0, sizeof(pc->data));
    LoadContact(pc);
}

//添加联系人
void AddContact(pContact pc)
{
    assert(pc);
    if (pc->size == MAX_SIZE)
    {
        printf("\t\t\t空间不足");
        return;
    }
    CheckCapacity(pc);
    printf("\t\t\t请输入姓名:>");
    scanf("%s", pc->data[pc->size].Name);
    printf("\t\t\t请输入性别:>");
    scanf("%s", pc->data[pc->size].Sex);
    printf("\t\t\t请输入年龄:>");
    scanf("%d", &pc->data[pc->size].age);
    printf("\t\t\t请输入电话号:>");
    scanf("%s", pc->data[pc->size].Tel);
    printf("\t\t\t请输入地址:>");
    scanf("%s", pc->data[pc->size].Addr);
    pc->size++;
    printf("\t\t\t添加成功\n");
}
//查找联系人
int SearchContact(pContact pc)
{
    char name[MAX_NAME];
    int i = 0;
    assert(pc);
    if (0 == pc->size)
    {
        printf("\t\t\t无此联系人\n");
        return -1;
    }
    printf("\t\t\t");
    scanf("%s", name);
    printf("\t\t\tName\tSex\tAge\tTel\t\tAddr\n");
    for (i = 0; i < pc->size; i++)
    {
        if (0 == strcmp(pc->data[i].Name, name))
        {

            printf("\t\t\t%-5s\t%-5s\t%-5d\t%-12s\t%-15s\n",
                pc->data[i].Name,
                pc->data[i].Sex,
                pc->data[i].age,
                pc->data[i].Tel,
                pc->data[i].Addr);
            return i;
        }
    }
    printf("\t\t\t无此联系人\n");
    return -1;

}
//删除联系人
void DeleteContact(pContact pc)
{
    int i = 0;
    int num = 0;
    assert(pc);
    if (0 == pc->size)
    {
        printf("\t\t\t无联系人\n");
        return;
    }
    num = SearchContact(pc);
    if (num != -1)
    {
        int n = 0;
        printf("\t\t\t确定删除?  1.yes,  2.no:>");
        printf("\t\t\t");
        scanf("%d", &n);
        if (1 == n)
        {
            for (i = num; i < (pc->size) - 1; i++)
            {
                pc->data[i] = pc->data[i + 1];

            }
            pc->size--;
            printf("\t\t\t删除成功\n");
        }
        else
        {
            return;
        }
    }

}

//交换
void Swap(pPeoInfo *a, pPeoInfo *b)
{
    pPeoInfo *Tmp;
    Tmp = *a;
    *a = *b;
    *b = Tmp;

}


//修改联系人
void ModifyContact(pContact pc)
{
    int modify = 0;
    assert(pc);
    if (0 == pc->size)
    {
        printf("\t\t\t无联系人\n");
        return;
    }
    modify = SearchContact(pc);
    if (modify != -1)
    {
        int n = 0;
        printf("\t\t\t确认修改?1.yes  2.no:>");
        printf("\t\t\t");
        scanf("%d", &n);
        if (1 == n)
        {
            printf("\t\t\t请输入姓名:>");
            scanf("%s", pc->data[modify].Name);
            printf("\t\t\t请输入性别:>");
            scanf("%s", pc->data[modify].Sex);
            printf("\t\t\t请输入年龄:>");
            scanf("%d", &pc->data[modify].age);
            printf("\t\t\t请输入电话号:>");
            scanf("%s", pc->data[modify].Tel);
            printf("\t\t\t请输入地址:>");
            scanf("%s", pc->data[modify].Addr);
            printf("\t\t\t修改成功\n");


        }
        else
        {
            return;
        }
    }


}
//按姓排序
void SortContact(pContact pc)
{
    int i = 0;
    int j = 0;
    int flag = 0;
    assert(pc);
    if (0 == pc->size)
    {
        printf("\t\t\t无联系人\n");
        return;
    }
    // 冒泡次数
    for (i = 0; i < pc->size - 1; i++)
    {
        //冒泡排序
        for (j = 0; j < pc->size - i - 1; j++)
        {
            if (strcmp(pc->data[j].Name, pc->data[j + 1].Name)>0)
            {
                Swap(&pc->data[j], &pc->data[j + 1]);
                flag = 1;
            }
        }
        if (0 == flag)
        {
            break;
        }
    }
    printf("排序成功\n");
}
//列表联系人
void ShowContact(pContact pc)
{
    int i = 0;
    assert(pc);
    if (0 == pc->size)
    {
        printf("\t\t\t无联系人\n");
        return;
    }
    printf("\t\t\tName\tSex\tAge\tTel\t\tAddr\n");
    for (i = 0; i < pc->size; i++)
    {
        printf("\t\t\t%-5s\t%-5s\t%-5d\t%-12s\t%-15s\n",
            pc->data[i].Name,
            pc->data[i].Sex,
            pc->data[i].age,
            pc->data[i].Tel,
            pc->data[i].Addr);

    }

}
//清空联系人
void EmptyContact(pContact pc)
{
    assert(pc);
    pc->size = 0;
    printf("\t\t\t清空成功");
}
//销毁通讯录
void DestoryContact(pContact pc)
{
    assert(pc);
    SaveContact(pc);
    free(pc->data);
    pc->data = NULL;
    pc->capacity = 0;
    pc->size = 0;
    printf("\t\t\t销毁成功");
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"
void meau()
{
    printf("\t\t\t******         《通讯录》       ********\n");
    printf("\t\t\t****************************************\n");
    printf("\t\t\t****** 1.添加信息       2.查找信息******\n");
    printf("\t\t\t****** 3.删除信息       4.修改信息******\n");
    printf("\t\t\t****** 5.按姓排序       6.信息列表******\n");
    printf("\t\t\t****** 7.清空信息       0.退出    ******\n");
    printf("\t\t\t****************************************\n");
}

void test()
{
    int input = 0;
    Contact pc;
    InitContact(&pc);
    do
    {
        meau();
        printf("\t\t\t请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case ADD:
            AddContact(&pc);
            break;
        case SEARCH:
            SearchContact(&pc);
            break;
        case DEIETE:
            DeleteContact(&pc);
            break;
        case MODIFY:
            ModifyContact(&pc);
            break;
        case SORT:
            SortContact(&pc);
            break;
        case SHOW:
            ShowContact(&pc);
            break;
        case EMPTY:
            EmptyContact(&pc);
            break;
        case EXIT:
            break;
        default:
            printf("\t\t\t输入有误,请重新输入:>");
            break;
        }

    } while (input);

}

int main()
{
    Contact pc;
    test();

    //销毁通讯录
    DestoryContact(&pc);
    system("pause");
    return 0;
}

# 结语:

最初的自己是个编程菜鸟,然而通过努力的学习,现在也能逐渐的自己写小程序了,相信这就是一种进步,暂不希望自己能有多强大。只要每一步走的充实,我相信一定会有好的回报,
且行且努力!

猜你喜欢

转载自blog.csdn.net/qq_41035588/article/details/80555876