C语言 通讯录管理系统(链表,手机号码分段存储,txt文件存取)

发布于:2023-02-12 ⋅ 阅读:(611) ⋅ 点赞:(0)


一、需求分析

设计一个通讯录管理系统,记录联系人的手机号码,姓名,联系地址,职业,公司,邮箱。可以增加联系人信息,删除联系人信息,修改联系人信息,查找联系人,排序,打印通讯录信息,一键清空通信录等


二、设计思路

1.根据需求分析,需要对数据进行增加,删除,修改,查找,排序等,我选择了双向链表作为内存数据结构,考虑到每个人的手机号码是唯一的,选择了手机号码作为key,同时考虑到数据量很大的情况下,可能会影响排序性能,所以考虑用手机号码的前四位进行分段存储,每一段对应一个链表,所以代码中管理了10000条双向链表,分别对应手机号码前四位0-9999的手机号码段。
在这里插入图片描述

2.数据持久化,我选择将通讯录内存数据保存到txt文件中,从内存数据到txt文件,用C语言库函数提供的fopen函数和sprintf函数即可实现,从txt文件数据到内存数据,用C语言库函数fopen函数和strtok函数即可实现。


三、数据

1、内存数据结构

联系人信息

struct People
{
    char tel[20];   //手机号码
    char name[30];  //姓名
    char address[100]; //联系地址
    char occupation[20]; //职业
    char company[40]; //公司
    char email[30]; //邮箱
};

链表中的一个节点

struct People_Node
{
    struct People people; //联系人信息
    struct People_Node *next; //上一个节点
    struct People_Node *pre; //下一个节点
};

一条链表

struct People_List
{
    int len; //链表节点总个数
    struct People_Node *head; //头节点
    struct People_Node *tail; //尾节点
};

2、文件数据

默认 contact.txt 文件(注意最后一行是空白行)

手机号码 姓名 联系地址 职业 公司 邮箱

contact.txt 文件 保存示例(用测试命令生产的数据)

手机号码 姓名 联系地址 职业 公司 邮箱
10121882476 宋八 天津 快递员 云上科技 555@163.com
10698756589 宋八 武汉 老师 云上科技 333@qq.com
12121198969 唐九 武汉 个体 小云直播 666@163.com
14779567330 王五 广西 个体 小葱蔬菜 111@163.com
18817493813 李四 北京 快递员 滕芬网络 111@163.com


四、主要功能接口

增加联系人相关

int add_con(); //增加联系人
int add_people(struct People people); //增加联系人到链表

删除联系人相关

int del_con(); //删除联系人
int del_people(struct People people); //从链表中删除联系人

修改联系人相关

int mod_con(); //修改联系人信息
int mod_people(struct People people); //从链表中修改联系人信息

查找联系人相关

int find_con(); //查找联系人
struct People_Node *find_people(struct People people); //从链表中查找联系人

排序通讯录相关

void sort_con(); //排序通讯录
void sort_people_list(); //按照手机号码从小到大排序通讯录并输出到屏幕

打印通讯录相关

void print_con(); //打印通讯录
void print_people_list(); //打印通讯录列表
void print_people(struct People *p); //打印联系人信息

清空通讯录

int clean_con(); //清空通讯录

退出通讯录

void exit_con(); //退出通讯录

五、问题以及解决方案

1.从txt文件中读取数据到内存时

fprintf(fp, "%s %s %s %s %s %s\n", people.tel, people.name, people.address, people.occupation, people.company, people.email);

问题1:如上代码所示,因为用fprintf函数写入到txt文件时,最后一个数据是加了\n的,所以从txt文件中读取数据到内存数据时,应该将\0替换掉\n,再保存在内存中,如下代码所示。

//字符串拷贝剔除掉换行符\n
void strcpy_not_n(char *des, char *src)
{
    while (*src != '\0')
    {
        if (*src != '\n')
            *des = *src;
        else
            *des = '\0';

        src++;
        des++;
    }
}

从txt文件中加载数据到内存代码片段

           switch (column)
            {
                case 0:
                    strcpy(people.tel, str);
                    break;
                case 1:
                    strcpy(people.name, str);
                    break;
                case 2:
                    strcpy(people.address, str);
                    break;
                case 3:
                    strcpy(people.occupation, str);
                    break;
                case 4:
                    strcpy(people.company, str);
                    break;
                default:
                    strcpy_not_n(people.email, str); //去掉\n
                    break;
            }
            str = strtok(NULL, LINE);
            column++;

问题2:因为我们存储数据的txt文件,默认最后一行是空白行,所以从txt文件中加载数据到内存的时候,应该过滤掉空白行,不然我们从txt文件中加载数据会多了一个6个数据都为空的记录,具体处理如下所示。

从txt文件中加载数据到内存代码片段

    char buf[BUFF_SIZE];
    int len = 0;
    int row = 0;
    while(fgets(buf, BUFF_SIZE, fp))
    {
        if ((row++) == 0)  //第一行是注释 手机号码 姓名 联系地址 职业 公司 邮箱
            continue;
        if(buf[0] == '\n') //过滤掉读到的是空白行
            continue;

2.用scanf函数从stdin中读取输入数据,因错误输入的数据可能导致scanf函数死循环的问题

因为scanf函数,我们从命令行输入数据,并按下enter换行键后,scanf函数会从stdin缓冲区中按照我们格式化的格式读取输入的数据,并且不符合读取格式的数据会跳过,并还留在缓冲区中,直到按照我们的格式读取到完整数据为止,并且输入过多的未读取的数据也还在缓冲区中,所以为了防止残留的stdin中的垃圾数据阻碍我们下一次从stdin缓冲区中读取到不准确的数据,我们应该在scanf函数读取到完整数据后,对stdin缓冲区进行清空,处理如下:

//清空无效的输入
void clean_stdin()
{
    char s;
    do
    {
        scanf("%c", &s);
    }while(s != '\n');
}

部分代码段

    scanf("%s %s %s %s %s", people.name, people.address, people.occupation, people.company, people.email);
    clean_stdin();

3.itoa函数不是C语言标准库函数,需要实现该函数

//数字转字符串函数
char *itoa_my(int value, char *str, int radix) {
    static char dig_my[] =
        "0123456789"
        "abcdefghijklmnopqrstuvwxyz";
    int n = 0, neg = 0;
    unsigned int v;
    char* p, *q;
    char c;
	/* 负数:十进制直接在前面加负号,其它进制用补码 */
    if (radix == 10 && value < 0) {
        v = -value;
        neg = 1;
    }else
    {
        v = value;
    }
    /* 其它进制的负数转为unsigned int类型,即取了补码 */
    do {
        str[n++] = dig_my[v%radix];
        v /= radix;
    } while (v);
    if (neg)
        str[n++] = '-';
    str[n] = '\0';
	/* 字符串反转 */
    for (p = str, q = p + (n-1); p < q; ++p, --q)
        c = *p, *p = *q, *q = c;
    return str;
}

六、完整代码

contact.h 文件

#ifndef CONTACT_H
#define CONTACT_H

#define CON_TXT_PATH "./contact.txt"
#define BUFF_SIZE 256
#define LINE " "  //分割符号
#define COUNT_TEL_MAX 9999
#define RETURN_MAIN ".."
#define RETURN_MAIN_FLAG 100
#define PEOPLE_INFO "手机号码\t姓名\t联系地址\t职业\t公司\t邮箱\n"

enum OPTION
{
    TEST = 0,
    ADD = 1,
    DEL,
    MOD,
    FIND,
    SORT,
    PRINT,
    CLEAN,
    EXIT,
    END
};

//联系人信息
struct People
{
    char tel[20];   //手机号码
    char name[30];  //姓名
    char address[100]; //联系地址
    char occupation[20]; //职业
    char company[40]; //公司
    char email[30]; //邮箱
};

//链表中的一个节点
struct People_Node
{
    struct People people; //联系人信息
    struct People_Node *next; //上一个节点
    struct People_Node *pre; //下一个节点
};

//一个链表
struct People_List
{
    int len; //链表节点总个数
    struct People_Node *head; //头节点
    struct People_Node *tail; //尾节点
};

//手机号码前四位对应的链表集合
struct People_List *g_tel[COUNT_TEL_MAX];

void display_menu(); //列出功能菜单
int init_con(); //初始化通讯录
int load_con(); //从txt文件中加载通讯录

int add_con(); //增加联系人
int add_people(struct People people); //增加联系人到链表

int del_con(); //删除联系人
int del_people(struct People people); //从链表中删除联系人

int mod_con(); //修改联系人信息
int mod_people(struct People people); //从链表中修改联系人信息

int find_con(); //查找联系人
struct People_Node *find_people(struct People people); //从链表中查找联系人

void sort_con(); //排序通讯录
void sort_people_list(); //按照手机号码从小到大排序通讯录并输出到屏幕

void print_con(); //打印通讯录
void print_people_list(); //打印通讯录列表
void print_people(struct People *p); //打印联系人信息

int clean_con(); //清空通讯录

void exit_con(); //退出通讯录

int test_cmd(); //测试命令

//辅助函数
void clean_stdin(); //清空无效的输入
int check_return_main(const char *str); //是否返回主菜单
int get_key(const char *tel); //返回手机号码对应的数组数组下标
int is_digit_string(const char *str); //检测str是否为全数字
int check_people(struct People people); //检测输入的格式比如手机号码格式是否正确等
void strcpy_not_n(char *des, char *src); //字符串拷贝剔除掉换行符\n
void save_people_list(); //保持数据到txt文件
char *itoa_my(int value, char *str, int radix); //数字转字符串函数

#endif

contact.c 文件

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "contact.h"

extern int errno;

int main()
{
    srand((unsigned)time(NULL)); /*播种子*/
    init_con();
    enum OPTION op = 0;
    int r = 0;
    while(1)
    {
        display_menu();
        r = scanf("%d", &op);
        if (r == 0 || op < TEST || op >= END) 
        {
            clean_stdin();
            printf("输入错误,请重新选择功能\n");
            continue;
        }

        switch(op)
        {
            case TEST:
            {
                while(1)
                {
                    r = test_cmd();
                    if (r == RETURN_MAIN_FLAG)
                        break;
                }
                break;
            }
            case ADD:
            {
                while(1)
                {
                    r = add_con();
                    if (r == RETURN_MAIN_FLAG)
                        break;
                }
                break;
            }
            case DEL:
            {
                while(1)
                {
                    r = del_con();
                    if (r == RETURN_MAIN_FLAG)
                        break;
                }
                break;
            }
            case MOD:
            {
                while(1)
                {
                    r = mod_con();
                    if (r == RETURN_MAIN_FLAG)
                        break;
                }
                break;
            }
            case FIND:
            {
                while(1)
                {
                    r = find_con();
                    if (r == RETURN_MAIN_FLAG)
                        break;
                }
                break;
            }
            case SORT:
                sort_con();
                break;
            case PRINT:
                print_con();
                break;
            case CLEAN:
            {
                while(1)
                {
                    r = clean_con();
                    if (r != 0)
                        break;
                }
                break;
            }
            case EXIT:
                exit_con();
                break;
            default:
                break;
        }
     }

    return 0;
}

//列出功能菜单
void display_menu()
{
    printf("*****************************************************************************************\n");
    printf("**                                      通讯录                                         **\n");
    printf("**                                                                                     **\n");
    printf("**                                  请选择功能                                         **\n");
    printf("**                                  0:测试命令                                        **\n");
    printf("**                                  1:增加联系人                                      **\n");
    printf("**                                  2:删除联系人                                      **\n");
    printf("**                                  3:修改联系人                                      **\n");
    printf("**                                  4:查找联系人                                      **\n");
    printf("**                                  5:排序联系人                                      **\n");
    printf("**                                  6:打印通讯录                                      **\n");
    printf("**                                  7:清空通讯录                                      **\n");
    printf("**                                  8:退出                                            **\n");
    printf("**                                                                                     **\n");
    printf("**                          在子功能下输入:.. 返回到主目录                            **\n");
    printf("**                                                                                     **\n");
    printf("*****************************************************************************************\n");
}

//初始化通讯录
int init_con()
{
    int i = 0;
    for (i = 0; i < COUNT_TEL_MAX; i++)
    {
        struct People_List *list = (struct People_List *)malloc(sizeof(struct People_List));
        list->len = 0;
        list->head = NULL;
        list->tail = NULL;
        g_tel[i] = list;
    }

    return load_con();
}

//从contact.txt文件中加载通讯录
int load_con()
{
    FILE *fp = fopen(CON_TXT_PATH, "r");
    if (!fp)
    {
        fprintf(stderr, "打开%s文件错误:%s\n", CON_TXT_PATH, strerror(errno));
        return 0;
    }
    
    char buf[BUFF_SIZE];
    int len = 0;
    int row = 0;
    while(fgets(buf, BUFF_SIZE, fp))
    {
        if ((row++) == 0)  //第一行是注释 手机号码 姓名 联系地址 职业 公司 邮箱
            continue;
        if(buf[0] == '\n') //过滤掉读到的是空白行
            continue;

        int column = 0;
        struct People people;
        char *str = strtok(buf, LINE);
        while(str)
        {
            switch (column)
            {
                case 0:
                    strcpy(people.tel, str);
                    break;
                case 1:
                    strcpy(people.name, str);
                    break;
                case 2:
                    strcpy(people.address, str);
                    break;
                case 3:
                    strcpy(people.occupation, str);
                    break;
                case 4:
                    strcpy(people.company, str);
                    break;
                default:
                    strcpy_not_n(people.email, str); //去掉\n
                    break;
            }
            str = strtok(NULL, LINE);
            column++;
        }

        add_people(people);
        row++;
    }

    fclose(fp);

    //print_people_list();

    return 1;
}

//增加联系人
int add_con()
{
    printf("请输入手机号码 姓名 联系地址 职业 公司 邮箱\n");
    struct People people; 
    scanf("%s", people.tel);
    if(check_return_main(people.tel))
    {
        clean_stdin();
        return RETURN_MAIN_FLAG;
    }

    scanf("%s %s %s %s %s", people.name, people.address, people.occupation, people.company, people.email);
    clean_stdin();

    int r = check_people(people);
    if (r == -1)
        return 0;

    if (find_people(people))
    {   
        printf("手机号码:%s 的联系人已经存在!\n", people.tel);
        return 0;
    }

    r = add_people(people);
    if (!r)
        return 0;

    //print_people_list();

    FILE *fp = fopen(CON_TXT_PATH, "a+"); /*打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。
                                            读取会从文件的开头开始,写入则只能是追加模式。*/
    if (!fp)
    {
        fprintf(stderr, "打开%s文件错误:%s\n", CON_TXT_PATH, strerror(errno));
        return 0;
    }

    fprintf(fp, "%s %s %s %s %s %s\n", people.tel, people.name, people.address, people.occupation, people.company, people.email);

    fclose(fp);

    printf("添加联系人成功!\n");

    return 1;
}

//增加联系人到链表
int add_people(struct People people)
{
    struct People_List *plist = NULL;

    //加入手机号码对应的链表库
    struct People_Node *pnode = (struct People_Node *)malloc(sizeof(struct People_Node));
    if (!pnode)
    {
        fprintf(stderr, "申请内存失败:%s\n", strerror(errno));
        return 0;
    }
    pnode->people = people;
    pnode->pre = NULL;
    pnode->next = NULL;

    int key = get_key(people.tel);
    plist = g_tel[key];
    if ((plist->len++) == 0)  //链表为空时
    {
        plist->head = pnode;
        plist->tail = pnode;
    } else {
        pnode->pre = plist->tail;
        plist->tail->next = pnode;
        plist->tail = pnode;
    }

    return 1;
}

//删除联系人
int del_con()
{    
    printf("请输入要删除的联系人的手机号码\n");
    struct People people;
    int r = scanf("%s", &people.tel);
    clean_stdin();

    if(check_return_main(people.tel))
        return RETURN_MAIN_FLAG;

    if (r == 0) 
    {
        printf("输入手机号码格式不正确--------r = %d\n", r);
        return 0;
    }

    r = check_people(people);
    if (r == -1)
        return 0;

    return del_people(people);
}

//从链表中删除联系人
int del_people(struct People people)
{
    int key = get_key(people.tel);

    struct People_Node *pnode = g_tel[key]->head;
    int find = 0;
    while(pnode)
    {
        if (strcmp(people.tel, pnode->people.tel) == 0)
        {
            find = 1;
            break;
        } 

        pnode = pnode->next;
    }
    
    if (!find)
    {
        printf("没有找到要删除的联系人\n");
        return 0;
    }

    g_tel[key]->len = g_tel[key]->len - 1;
    
    if (pnode == g_tel[key]->head)
    {
        g_tel[key]->head = pnode->next;
        if (g_tel[key]->len == 0)
            g_tel[key]->tail = NULL;
        else 
            pnode->next->pre = NULL;
    } else if (pnode == g_tel[key]->tail) {
        g_tel[key]->tail = pnode->pre;
        pnode->pre->next = NULL;
    } else {
        pnode->pre->next = pnode->next;
        pnode->next->pre = pnode->pre;
    }

    free(pnode);

    //print_people_list();

    save_people_list();

    printf("删除联系人成功!\n");

    return 1;
}

//修改联系人信息
int mod_con()
{
    printf("请输入需要修改联系人的 手机号码 姓名 联系地址 职业 公司 邮箱\n");
    struct People people;
    scanf("%s", people.tel);
    if(check_return_main(people.tel))
    {
        clean_stdin();
        return RETURN_MAIN_FLAG;
    }
    scanf("%s %s %s %s %s", people.name, people.address, people.occupation, people.company, people.email);
    clean_stdin();

    if(check_return_main(people.tel))
        return RETURN_MAIN_FLAG;

    int r = check_people(people);
    if (r == -1)
        return 0;

    return mod_people(people);
}

//从链表中修改联系人信息
int mod_people(struct People people)
{
    int key = get_key(people.tel);

    struct People_Node *pnode = g_tel[key]->head;
    int find = 0;
    while(pnode)
    {
        if (strcmp(people.tel, pnode->people.tel) == 0)
        {
            find = 1;
            break;
        } 

        pnode = pnode->next;
    }
    
    if (!find)
    {
        printf("没有找到要修改的联系人\n");
        return 0;
    }

    pnode->people = people;

    //print_people_list();

    save_people_list();

    printf("修改联系人成功!\n");

    return 1;
}

//查找联系人
int find_con()
{
    printf("请输入要查找的联系人的手机号码\n");
    struct People people;
    int r = scanf("%s", &people.tel);
    clean_stdin();

    if(check_return_main(people.tel))
        return RETURN_MAIN_FLAG;

    if (r == 0) 
    {
        printf("输入手机号码格式不正确\n");
        return 0;
    }

    r = check_people(people);
    if (r == -1)
        return 0;

    struct People_Node *pnode = find_people(people);
    if (!pnode)
    {
        printf("没有查找到手机号码对应的联系人!\n");
        return 0;
    }

    printf(PEOPLE_INFO);
    print_people(&pnode->people);

    return 1;
}

//从链表中查找联系人
struct People_Node *find_people(struct People people)
{
    int key = get_key(people.tel);

    struct People_Node *pnode = g_tel[key]->head;
    while(pnode)
    {
        if (strcmp(people.tel, pnode->people.tel) == 0)
        {
            return pnode;
        } 

        pnode = pnode->next;
    }
    
    return NULL;
}

//排序通讯录
void sort_con()
{
    sort_people_list();
}

//按照手机号码从小到大排序通讯录并输出到屏幕
void sort_people_list()
{
    // printf("---------------before sort---------------\n");
    // print_people_list();

    struct People_List *plist = NULL;
    struct People_Node *pnode = NULL;
    struct People_Node *pnext = NULL;
    struct People_Node *pmin = NULL;
    struct People ptemp;
    int i = 0;
    for (i = 0; i < COUNT_TEL_MAX; i++)
    {
        plist = g_tel[i];
        pnode = plist->head;
        while (pnode)
        {
            pmin = pnode;
            //ptemp = pnode;
            pnext = pnode->next;
            while(pnext)
            {
                if (atof(pmin->people.tel) > atof(pnext->people.tel))
                    pmin = pnext;
                pnext = pnext->next;
            }

            if (pmin != pnode) //当前节点不是最小节点
            {
                ptemp = pnode->people;
                pnode->people = pmin->people;
                pmin->people = ptemp;
            }

            pnode = pnode->next;
        } 
    }

    // printf("---------------after sort---------------\n");
    // print_people_list();

    printf("排序成功!\n");
}

//打印通讯录
void print_con()
{
    printf("----------开始打印通讯录----------\n");

    print_people_list();

    printf("----------打印通讯录完毕----------\n");
}

//打印通讯录列表
void print_people_list()
{
    int i = 0;
    struct People_Node *pnode;
    printf(PEOPLE_INFO);
    for (i = 0; i < COUNT_TEL_MAX; i++)
    {
        pnode = g_tel[i]->head;
        while (pnode)
        {
            //printf("key = %d   ", i);
            print_people(&(pnode->people));
            pnode = pnode->next;
        }
    }
}

//打印联系人信息
void print_people(struct People *p)
{
    printf("%s\t%s\t%s\t%s\t%s\t%s\n", p->tel, p->name, p->address, p->occupation, p->company, p->email);
}

//清空通讯录
int clean_con()
{
    printf("是否清空通讯录:y or n\n");
    char op[100];
    int r = scanf("%s", &op);
    clean_stdin();

    if (check_return_main(op) || strcmp(op, "n") == 0)
        return RETURN_MAIN_FLAG;
    
    if (strcmp(op, "y") != 0)
    {
        printf("输入:y or n 错误!\n");
        return 0;
    }

    printf("----------开始清空通讯录,开始释放内存数据----------\n");

    int i = 0;
    struct People_List *plist;
    struct People_Node *pcur = NULL;
    struct People_Node *pnext = NULL;
    for (i = 0; i < COUNT_TEL_MAX; i++)
    {
        plist = g_tel[i];
        pcur = plist->head;
        while (pcur)
        {
            pnext = pcur->next;
            //printf("free node tel = %s\n", pcur->people.tel);
            free(pcur);
            pcur = pnext;
        }
        plist->len = 0;
        plist->head = NULL;
        plist->tail = NULL;
    }

    save_people_list();

    printf("----------释放内存数据成功,清空通讯录成功----------\n");

    return 1;
}

//退出通讯录
void exit_con()
{
    printf("----------开始保存通讯录----------\n");
    save_people_list();

    printf("----------开始退出通讯录,开始释放内存数据----------\n");

    int i = 0;
    struct People_List *plist;
    struct People_Node *pcur = NULL;
    struct People_Node *pnext = NULL;
    for (i = 0; i < COUNT_TEL_MAX; i++)
    {
        plist = g_tel[i];
        pcur = plist->head;
        while (pcur)
        {
            pnext = pcur->next;
            //printf("free node tel = %s\n", pcur->people.tel);
            free(pcur);
            pcur = pnext;
        }
        free(plist);
    }

    printf("----------释放内存数据成功,退出通讯录成功----------\n");
    exit(1);
}

//清空无效的输入
void clean_stdin()
{
    char s;
    do
    {
        scanf("%c", &s);
    }while(s != '\n');
}

//是否返回主菜单
int check_return_main(const char *str)
{
    if (strcmp(str, RETURN_MAIN) == 0)
        return 1;
    
    return 0;
}

//返回手机号码对应的数组数组下标
int get_key(const char *tel)
{
    char str[5];
    memcpy(str, tel, 4);
    int key = atoi(str);
    
    if (key > COUNT_TEL_MAX || key < 0)
        return -1;

    return key;
}

//检测str是否为全数字
int is_digit_string(const char *str)
{
    if (*str == '\0')
        return 0;

    while (*str != '\0')
    {
        if(!isdigit(*str++))
            return 0;
    }
    
    return 1;
}

// 检测输入的格式比如手机号码格式是否正确等
int check_people(struct People people)
{
    if (!is_digit_string(people.tel))  //是否是数字
    {
        printf("手机号码格式不全是数字\n");
        return -1;
    }

    if (strlen(people.tel) < 4) //手机号码是否过短
    {
        printf("手机号码不能低于4位\n");
        return -1;
    }

    return 0;
}

//字符串拷贝剔除掉换行符\n
void strcpy_not_n(char *des, char *src)
{
    while (*src != '\0')
    {
        if (*src != '\n')
            *des = *src;
        else
            *des = '\0';

        src++;
        des++;
    }
}

//保持数据到txt文件
void save_people_list()
{
    FILE *fp = fopen(CON_TXT_PATH, "w"); /*打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。
                                         读取会从文件的开头开始,写入则只能是追加模式。*/
    if (!fp)
    {
        fprintf(stderr, "打开%s文件错误:%s\n", CON_TXT_PATH, strerror(errno));
        return ;
    }

    int i = 0;
    fprintf(fp, "手机号码 姓名 联系地址 职业 公司 邮箱\n");
    int interval = 3;
    char dest[1024] = "";
    char str[256] = "";
    int record = 0;
    struct People_Node *pnode = NULL;
    for (i = 0; i < COUNT_TEL_MAX; i++)
    {
        pnode = g_tel[i]->head;
        while (pnode)
        {   
            record = record + 1;
            sprintf(str, "%s %s %s %s %s %s\n", pnode->people.tel, pnode->people.name, pnode->people.address, 
                pnode->people.occupation, pnode->people.company, pnode->people.email);
            strcat(dest, str);
            strcpy(str, "");
            if (record%interval == 0)
            {
                fprintf(fp, dest);
                record = 0;
                strcpy(dest, "");
            }
            pnode = pnode->next;
        }
    }
    if (strcmp(dest, "") != 0)
        fprintf(fp, dest);

    fclose(fp);
}

//测试命令
int test_cmd()
{
    printf("1:随机增加n个联系人,例如:1 1000 就是随机增加1000个联系人\n");
    char cmd1[20];
    int cmd2 = 0;
    scanf("%s", &cmd1);
    if(check_return_main(cmd1))
    {
        clean_stdin();
        return RETURN_MAIN_FLAG;
    }
    scanf("%d", &cmd2);
    clean_stdin();
    
    if (atoi(cmd1) != 1 || cmd2 <= 0)
    {
        printf("输入的测试命令格式不对\n");
        return 0;
    }

    char *family_names[10] = {
        "李一一","欧阳二","张三","李四","王五",
        "易六","高七","宋八","唐九","杨十"
    };
    char *address[10] = {
        "广州","上海","天津","北京","武汉",
        "拉萨","新疆","河北","河南","广西"
    };
    char *occupation[10] = {
        "老师","快递员","工程师","个体","医生",
        "护士","培训师","务农","健身教练","CEO"
    };
   char *company[10] = {
        "滕芬网络","云上科技","佳佳超市","水煮鱼餐饮","来一杯奶茶",
        "好多好吃","小葱蔬菜","水果批发商","酸菜鱼特产","小云直播"
    };
   char *email[10] = {
        "111@163.com","222@qq.com","333@qq.com","444@163.com","555@163.com",
        "666@163.com","777@163.com","888@qq.com","999@qq.com","123@163.com"
    };

    struct People people;
    int i = 0, j = 0;
    int temp;
    char tel[12] = "1";
    char str[2];
    for (i = 0; i < cmd2; i ++)
    {
        for (j = 0; j < 10; j++)
        {
            temp = (int)rand()%10;
            //printf("%d\n", temp);
            itoa_my(temp, str, 10);
            strcat(tel, str);
            strcpy(str, "");
        }
        strcpy(people.tel, tel);
        strcpy(people.name, family_names[(int)rand()%10]);
        strcpy(people.address, address[(int)rand()%10]);
        strcpy(people.occupation, occupation[(int)rand()%10]);
        strcpy(people.company, company[(int)rand()%10]);
        strcpy(people.email, email[(int)rand()%10]);
        //printf("%s\n", tel);
        add_people(people);
        strcpy(tel, "1");
    }

    save_people_list();

    printf("新增联系人成功\n");

    return 1;
}

//数字转字符串函数
char *itoa_my(int value, char *str, int radix) {
    static char dig_my[] =
        "0123456789"
        "abcdefghijklmnopqrstuvwxyz";
    int n = 0, neg = 0;
    unsigned int v;
    char* p, *q;
    char c;
	/* 负数:十进制直接在前面加负号,其它进制用补码 */
    if (radix == 10 && value < 0) {
        v = -value;
        neg = 1;
    }else
    {
        v = value;
    }
    /* 其它进制的负数转为unsigned int类型,即取了补码 */
    do {
        str[n++] = dig_my[v%radix];
        v /= radix;
    } while (v);
    if (neg)
        str[n++] = '-';
    str[n] = '\0';
	/* 字符串反转 */
    for (p = str, q = p + (n-1); p < q; ++p, --q)
        c = *p, *p = *q, *q = c;
    return str;
}

七、效果截图

首页

在这里插入图片描述

测试命令增加10个联系人,并打印通讯录

在这里插入图片描述

退出通讯录

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到

热门文章