本人水平实在有限学的还少,这个东西已经花了我很长时间并且找了一遍又一遍的错误,但可能还有一些BUG,大家可以测试一下,谢谢!
test.c 文件(测试通讯录)
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
#include "note.h"
void menu_contact(void)
{
printf("************************************************\n");
printf("******** My Contact *********\n");
printf("******** 1. add 2. del *********\n");
printf("******** 3. search 4. show *********\n");
printf("******** 5. modify 6. sort *********\n");
printf("******** 7. note 0. exit *********\n");
printf("************************************************\n");
}
void menu_note(void)
{
printf("************************************************\n");
printf("******** My Daily Note *********\n");
printf("******** 1. add 2. del *********\n");
printf("******** 3. browse 0. exit *********\n");
printf("************************************************\n");
}
int main()
{
int input_contact = 0;
int input_note = 0;
Contact Con; //创建通讯录结构体与结构体指针
Contact* pc = &Con;
Note book; //创建日记本结构体变量与指针
Note* bookpoint = &book;
Init_Con(pc); //初始化通讯录结构体
Init_book(bookpoint); //初始化日记本结构体
if (!PasswordSetting()) //设置第一次登录通讯录的密码
{
printf("用户放弃设置密码,退出程序....\n");
return 0;
}
system("cls");
if (!PasswordAccess()) //用户放弃输入密码
{
printf("访问通讯录失败....\n");
return 0;
}
//正式进入通讯录里面
do
{
system("cls");
menu_contact();
printf("-------- 当前已有联系人:%d/%d ---------\n", pc->sz, pc->capacity);
printf("请输入菜单上的数字:");
scanf("%d", &input_contact);
printf("\n");
switch (input_contact)
{
case 1:
AddContact(pc);
Sleep(2000);
break;
case 2:
DelContact(pc);
Sleep(2000);
break;
case 3:
SearchContact(pc);
HoldupDisplay();
break;
case 4:
ShowContact(pc);
HoldupDisplay();
break;
case 5:
ModifyContact(pc);
Sleep(2000);
break;
case 6:
SortContact(pc);
Sleep(2000);
break;
case 7:
if (!PasswordAccess())
{
printf("无法访问记事本\n");
break;
}
do
{
system("cls");
menu_note();
printf("-------- 当前已有记事:%d/%d ---------\n", bookpoint->sz, bookpoint->capacity);
printf("请输入菜单上的数字:");
scanf("%d", &input_note);
printf("\n");
switch (input_note)
{
case 1:
AddNote(bookpoint);
HoldupDisplay();
break;
case 2:
DelNote(bookpoint);
Sleep(2000);
break;
case 3:
BrowseNote(bookpoint);
HoldupDisplay();
break;
case 0:
printf("退出成功,将返回通讯录\n");
break;
}
} while (input_note);
break;
case 0:
DestroyContact(pc);
DestroyNote(bookpoint);
printf("退出通讯录\n");
break;
default:
printf("输入有误,重新输入\n");
break;
}
} while (input_contact);
return 0;
}
note.h 有关于记事本的头文件
#pragma once
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <windows.h>
#include <ctype.h>
#define Book_Capacity_Max 5
#define Book_Capacity_INC 5
#define Original_Words_Limit 10
#define Tmp_Note_Words 150
//日记本结构体
typedef struct Note
{
char** message;
int sz;
int capacity;
}Note; //结构体类型为Note
//初始化日记结构体变量
void Init_book(bookpoint);
//检查你输入的字符个数与bookmark指向的堆区空间预先设置的字数的大小关系,条件满足进行加长
void CheckTmpNoteWords(int LenOfWords, int OriginalWordsLimit, char** Message);
//判断当前日记条数是否已满,已满则扩容
void CheckCapacity_Note(Note* bookpoint);
//增加一条记事
void AddNote(Note* bookpoint);
//浏览已有记事
void BrowseNote(const Note* bookpoint);
//删除指定的记事
void DelNote(Note* bookpoint);
//程序结束销毁通讯录
void DestroyNote(bookpoint);
note.c 有关于记事本功能实现的源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "note.h"
//初始化结构体变量
void Init_book(Note* bookpoint)
{
assert(bookpoint);
bookpoint->message = (char**)malloc(Book_Capacity_Max * sizeof(char*));
if (bookpoint->message == NULL)
{
perror("Init_book::Malloc");
return;
}
bookpoint->capacity = Book_Capacity_Max;
bookpoint->sz = 0;
}
//判断当前日记条数是否已满,已满则扩容
void CheckCapacity_Note(Note* bookpoint)
{
assert(bookpoint);
if (bookpoint->capacity == bookpoint->sz)
{
printf("日记条数已满,已将容量扩充%d条\n", Book_Capacity_INC);
printf("\n");
char* tmp = (char*)realloc(bookpoint->message, sizeof(char*) * (bookpoint->capacity + Book_Capacity_INC)); //扩容
if (tmp == NULL)
{
perror("CheckCapacity_Note::Realloc");
return;
}
bookpoint->message = tmp;
bookpoint->capacity += Book_Capacity_INC;
}
}
//检查你输入的字符个数与bookmark指向的堆区空间预先设置的字数的大小关系,条件满足进行加长
void CheckTmpNoteWords(int LenOfWords, int OriginalWordsLimit, char** Message)
{
assert(Message);
if (LenOfWords > OriginalWordsLimit)
{
char* tmp = (char*)realloc(*Message, sizeof(char) * LenOfWords + 1); // +1 是为了等会打印的时候撞见\0
if (tmp == NULL)
{
perror("CheckTmpNoteWords::Malloc");
return;
}
*Message = tmp;
printf("由于你的字数超出原有既定限制,现将空间自动扩容至%d字节\n", LenOfWords);
}
}
//增加一条记事
void AddNote(Note* bookpoint)
{
assert(bookpoint);
CheckCapacity_Note(bookpoint);
char* bookmark = (char*)malloc(Original_Words_Limit * sizeof(char)); //在message指向的堆区空间的每个元素记为bookmark
if (bookmark == NULL) //bookmark又指向一块堆区空间
{
perror("AddNote::Malloc");
return;
}
bookpoint->message[bookpoint->sz] = bookmark;
char Input_words[Tmp_Note_Words] = { 0 };
printf("请输入你要记录的内容:");
getchar(); //清理输入缓冲区
gets(Input_words);
int LenOfWords = strlen(Input_words); //我输入的字符个数
CheckTmpNoteWords(LenOfWords, Original_Words_Limit, bookpoint->message + bookpoint->sz); //必要时进行加长空间
strcpy(bookpoint->message[bookpoint->sz], Input_words); //拷贝字符串到堆区
printf("\n");
printf("添加成功!此次你添加的记事:%s\n", bookpoint->message[bookpoint->sz]);
printf("\n");
bookpoint->sz++;
}
//浏览已有记事
void BrowseNote(const Note* bookpoint)
{
assert(bookpoint);
if (bookpoint->sz == 0)
{
printf("当前无记录......\n");
return;
}
printf("当前已有记事如下:\n");
int i = 0;
for (i = 0; i < bookpoint->sz; i++)
{
printf("%d:> %s\n", i + 1, bookpoint->message[i]);
}
}
//删除指定的记事
void DelNote(Note* bookpoint)
{
BrowseNote(bookpoint);
int num = 0;
printf("请选择要删除的记事的序号:");
scanf("%d", &num);
if (num > bookpoint->sz)
{
printf("输入错误,当前最多仅有%d份记录\n", bookpoint->sz);
return;
}
int i = 0;
for (i = num - 1; i <= (bookpoint->sz) - 2; i++)
{
strcpy(bookpoint->message[i], bookpoint->message[i + 1]);
}
free(bookpoint->message[(bookpoint->sz) - 1]);
bookpoint->sz--;
char** tmp = (char**)realloc(bookpoint->message, sizeof(char*) * bookpoint->sz);
if (tmp == NULL)
{
perror("DelNote::Realloc");
}
bookpoint->message = tmp;
printf("删除成功\n");
}
//程序结束销毁记事本
void DestroyNote(Note* bookpoint)
{
assert(bookpoint);
int i = 0;
for (i = 0; i < bookpoint->sz; i++)
{
free(bookpoint->message[i]);
}
free(bookpoint);
bookpoint->message = NULL;
bookpoint->capacity = 0;
bookpoint->sz = 0;
bookpoint = NULL;
}
contact.h 有关于通讯录(除记事本)的头文件
#pragma once
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <windows.h>
#include <ctype.h>
#define Password_MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 20
#define TELE_MAX 20
#define STANDARD_NUM 5
#define INC_SZ 3
#define CAP_MAX 5
//人员结构体
typedef struct PeoInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char addr[ADDR_MAX];
char tele[TELE_MAX];
}PeoInfo;
//通讯录结构体
typedef struct Contact
{
PeoInfo* data;
int capacity;
int sz;
}Contact;
//密码
static char InputPassword_Final[Password_MAX] = { '\0' };
//滞留显示功能的函数(按0退出)
void HoldupDisplay(void);
//初始化通讯录结构体
void Init_Con(Contact* pc);
//判断用户设置的密码是否合规
int JudgePassword(char* InputPassword);
//设置通讯录密码
int PasswordSetting(void);
//执行操作前的密码输入
int PasswordAccess(void);
//判断通讯录是否需要增容
void CheckCapicity_Contact(Contact* pc);
//增加通讯录联系人
void AddContact(Contact* pc);
//输入姓名查找联系人
int FindByName(const Contact* pc, char* name);
//删除通讯录联系人
void DelContact(Contact* pc);
//查找指定联系人
void SearchContact(const Contact* pc);
//显示通讯录所有人的信息
void ShowContact(const Contact* pc);
//对于排序标准的界定
int CmpStandard(const char* standard);
//按照规则排序联系人
void SortContact(const Contact* pc);
//修改通讯录联系人
void ModifyContact(Contact* pc);
//程序结束销毁通讯录
void DestroyContact(Contact* pc);
contact.c 有关于通讯录功能实现的源文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
#include "note.h"
//滞留显示功能的函数(按0退出)
void HoldupDisplay()
{
int num = 0;
printf("..........\n");
printf("按0退出:");
while (1)
{
scanf("%d", &num);
if (num == 0)
break;
printf("输入无效,重新输入:");
}
}
//初始化通讯录结构体
void Init_Con(Contact* pc)
{
assert(pc);
pc->data = (PeoInfo*)calloc(CAP_MAX, sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("Init_Con::Calloc");
return;
}
pc->sz = 0;
pc->capacity = CAP_MAX;
}
//判断用户设置的密码是否合规
int JudgePassword(char* InputPassword)
{
assert(InputPassword);
int len = strlen(InputPassword);
if (len < 6)
return 0;
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int i = 0;
for (i = 0; i < len; i++)
{
if (islower(*(InputPassword + i)))
flag1 = 1;
else if (isupper(*(InputPassword + i)))
flag2 = 1;
else if (isdigit(*(InputPassword + i)))
flag3 = 1;
if (flag1 + flag2 + flag3 == 3)
return 1;
}
return 0;
}
//设置通讯录的密码
int PasswordSetting()
{
char InputPassword[Password_MAX] = { 0 };
Elon:
printf("******************* PASSWORD SETTING ******************* \n");
printf("请设置通讯录密码(必须包含大小写字母与数字 && 长度不低于6个)(按0退出访问通讯录):");
while (1)
{
gets(InputPassword);
if (strcmp("0", InputPassword) == 0)
return 0;
if (JudgePassword(InputPassword)) //第一次输入已经成功,第二次输入确认
{
system("cls");
while (1)
{
printf("请再次输入确认密码(按0重新设置):");
gets(InputPassword_Final);
if (strcmp("0", InputPassword_Final) == 0)
{
system("cls");
goto Elon;
}
if (strcmp(InputPassword, InputPassword_Final) == 0)
{
printf("密码已经设置成功!\n");
printf("正在加载.........\n");
Sleep(2000);
return 1;
}
else
printf("输入有误,重新输入\n");
}
}
else
printf("设置的密码不合规范,请重新输入(按0退出访问通讯录):");
}
}
//执行操作前的密码输入
int PasswordAccess(void)
{
char password[Password_MAX] = { 0 };
printf("请输入密码以解锁访问与修改权限(按0退出访问):");
while (1)
{
gets(password);
if (strcmp(password, "0") == 0)
return 0;
if (strcmp(password, InputPassword_Final) == 0)
{
printf("输入成功,正在加载.....\n");
Sleep(1000);
return 1;
}
else
{
printf("输入错误,请重新输入(按0退出访问):");
}
}
return 0;
}
//判断通讯录是否需要增容
void CheckCapicity_Contact(Contact* pc)
{
assert(pc);
if (pc->sz == pc->capacity)
{
printf("当然通讯录已满,容量将自动增加%d个\n", INC_SZ);
PeoInfo* data_1 = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
if (data_1 == NULL)
{
perror("CheckCapacity::Realloc");
return;
}
pc->data = data_1;
pc->capacity += INC_SZ;
}
}
//增加通讯录联系人
void AddContact(Contact* pc)
{
assert(pc);
CheckCapicity_Contact(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].addr);
printf("请输入联系人电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("输入成功,添加信息如下:\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-15s\n", "NAME", "SEX", "AGE", "ADDRESS", "TELENUMBER");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-15s\n", pc->data[pc->sz].name,
pc->data[pc->sz].sex,
pc->data[pc->sz].age,
pc->data[pc->sz].addr,
pc->data[pc->sz].tele);
pc->sz++;
}
//输入姓名查找联系人
int FindByName(const Contact* pc, char* name)
{
assert(pc && name);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->data[i].name, name) == 0)
return i;
}
return -1;
}
//删除通讯录联系人
void DelContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("请输入联系人姓名:");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要删除的人不存在\n");
return;
}
int i = 0;
for (i = pos; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("已删除成功\n");
}
//查找指定联系人
void SearchContact(const Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("请输入联系人姓名:");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
printf("该联系人的信息为:\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-15s\n", "NAME", "SEX", "AGE", "ADDRESS", "TELENUMBER");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-15s\n", pc->data[pos].name,
pc->data[pos].sex,
pc->data[pos].age,
pc->data[pos].addr,
pc->data[pos].tele);
}
//显示通讯录所有人的信息
void ShowContact(const Contact* pc)
{
assert(pc);
printf("当前所有联系人的信息为:\n");
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-15s\n", "NAME", "SEX", "AGE", "ADDRESS", "TELENUMBER");
int i = 0;
for (i = 0; i < pc->sz; i++)
{
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-15s\n", pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].addr,
pc->data[i].tele);
}
}
//对于排序标准的界定
int CmpStandard(const char* StdNeed)
{
assert(StdNeed);
char* standard[STANDARD_NUM] = { "NAME","SEX","AGE","ADDRESS","TELENUMBER" };
int sz = sizeof(standard) / sizeof(standard[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
if (strcmp(standard[i], StdNeed) == 0)
{
return i;
}
}
return -1;
}
//qsort排序姓名
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
//qsort排序性别
int cmp_sex(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->sex, ((PeoInfo*)e2)->sex);
}
//qsort排序age
int cmp_age(const void* e1, const void* e2)
{
return ((PeoInfo*)e1)->age - ((PeoInfo*)e2)->age;
}
//qsort排序地址
int cmp_addr(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->addr, ((PeoInfo*)e2)->addr);
}
//qsort排序电话
int cmp_tele(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->tele, ((PeoInfo*)e2)->tele);
}
//按照规则排序联系人
void SortContact(const Contact* pc)
{
assert(pc);
char StdNeed[NAME_MAX] = { 0 };
printf("请输入排序的标准(NAME/SEX/AGE/ADDRESS/TELENUMBER):");
scanf("%s", StdNeed);
int ret = CmpStandard(StdNeed);
switch (ret)
{
case 0:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_name);
break;
case 1:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_sex);
break;
case 2:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_age);
break;
case 3:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_addr);
break;
case 4:
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_tele);
break;
}
printf("已排序完成\n");
}
//修改通讯录联系人
void ModifyContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人姓名:");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要修改的人不存在\n");
return;
}
printf("请输入新的联系人姓名:");
scanf("%s", pc->data[pos].name);
printf("请输入新的联系人性别:");
scanf("%s", pc->data[pos].sex);
printf("请输入新的联系人年龄:");
scanf("%d", &pc->data[pos].age);
printf("请输入新的联系人地址:");
scanf("%s", pc->data[pos].addr);
printf("请输入新的联系人电话:");
scanf("%s", pc->data[pos].tele);
printf("已经修改成功\n");
}
//程序结束销毁通讯录
void DestroyContact(Contact* pc)
{
assert(pc);
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
pc = NULL;
}