练习使用了结构体,动态内存管理malloc函数,文件读写函数
//main.c
#include "contacts.h"
enum choose
{
EXIT,
ADD,
DEL,
MODIFY,
FIND,
SORT
};
int main()
{
int input = 0;
//通讯录当前联系人个数
int size = 0;
Contacts contacts;//创建通讯录
InitContacts(&contacts);
do
{
menu();
printf("Pleae choose:> ");
scanf_s("%d", &input);
switch (input)
{
case 0:
Write_to_File(&contacts);
FreeContacts(&contacts);
break;
case 1:
Add(&contacts);
break;
case 2:
Del(&contacts);
break;
case 3:
Modify(&contacts);
break;
case 4:
Find(&contacts);
break;
case 5:
Sort(&contacts);
break;
case 6:
Print(&contacts);
break;
default:
printf("Wrong! Please input again.\n");
break;
}
} while (input);
return 0;
}
main.c用于实现基本框架,选择进入相应功能
//contacts.c
#include "contacts.h"
void menu()
{
printf("############################\n");
printf("### 1.ADD ####### 2. DEL ###\n");
printf("### 3.MODIFY #### 4.FIND ###\n");
printf("### 5.SORT #### 6. PRINT ###\n");
printf("### 0.EXIT #################\n");
printf("############################\n");
}
void InitContacts(Contacts* pf)
{
pf->data = (Info*)malloc(DEFAULT_SZ*sizeof(Info));
if (pf->data == NULL)
{
perror("InitContacts");
return;
}
pf->num = 0;
pf->size = DEFAULT_SZ;
memset(pf->data, 0, DEFAULT_SZ * sizeof(Info));
Read_from_File(pf);
}
void Add(Contacts* pf)
{
Enlarge(pf);
printf("Please Input Name:> ");
scanf_s("%s", pf->data[pf->num].name, 20);
printf("Please Input Sex:> ");
scanf_s("%s", pf->data[pf->num].sex, 10);
printf("Please Input Age:> ");
scanf_s("%d", &(pf->data[pf->num].age));
printf("Please Input Phone Number:> ");
scanf_s("%s", pf->data[pf->num].phone, 12);
(pf->num)++;
}
void Del(Contacts* pf)
{
char temp[20] = { 0 };
printf("Please input the Name you want to delete:> ");
scanf_s("%s", temp, 20);
for (size_t i = 0; i < pf->num; i++)
{
if (strcmp(temp, pf->data[i].name) == 0)
{
printf("Delete succeeded.\n");
//将data[i+1]和之后的所有数据前移,覆盖要删除的数据
memmove((pf->data)+i, (pf->data)+i+1, (pf->size-i)*sizeof(pf->data[0]));
(pf->num)--;
return;
}
}
printf("Can't delete.No such a person.\n");
}
void Modify(Contacts* pf)
{
char temp[20] = { 0 };
printf("Please input the Name you want to modify:> ");
scanf_s("%s", temp, 20);
for (size_t i = 0; i < pf->num; i++)
{
if (strcmp(temp, pf->data[i].name) == 0)
{
printf("Please Input new Name:> ");
scanf_s("%s", pf->data[i].name, 20);
printf("Please Input new Sex:> ");
scanf_s("%s", pf->data[i].sex, 10);
printf("Please Input new Age:> ");
scanf_s("%d", &pf->data[i].age);
printf("Please Input new Phone Number:> ");
scanf_s("%s", pf->data[i].phone, 12);
printf("Modify succeeded:> \n");
printf("%-20s\t%-10s\t%-3s\t%-12s\n", "Name", "Sex", "Age", "Phone Number");
printf("%-20s\t%-10s\t%-3d\t%-12s\n", pf->data[i].name,
pf->data[i].sex,
pf->data[i].age,
pf->data[i].phone);
return;
}
}
printf("Can't modify.No such a person.\n");
}
void Find(const Contacts* pf)
{
char temp[20] = { 0 };
printf("Please input the Name you want to find:> ");
scanf_s("%s", temp, 20);
for (size_t i = 0; i < pf->num; i++)
{
if (strcmp(temp, pf->data[i].name) == 0)
{
printf("Search succeeded.\n");
printf("%-20s\t%-10s\t%-3s\t%-12s\n", "Name", "Sex", "Age", "Phone Number");
printf("%-20s\t%-10s\t%-3d\t%-12s\n", pf->data[i].name,
pf->data[i].sex,
pf->data[i].age,
pf->data[i].phone);
return;
}
}
printf("Can't find.\n");
}
void Sort(Contacts* pf)
{
Info temp = pf->data[0];
Info* pc = &temp;
int flag = pf->num;
int is_ordered = 0;//置1时代表已经按序排列
while (flag && !is_ordered)
{
for (size_t i = 0; i < (pf->num) - 1; i++)
{
if (strcmp(pf->data[i].name, pf->data[i + 1].name) <= 0)
is_ordered = 1;
else if (strcmp(pf->data[i].name, pf->data[i + 1].name) > 0)
{
memcpy(pc, &(pf->data[i + 1]), sizeof(pf->data[0]));
memcpy(&(pf->data[i + 1]), &(pf->data[i]), sizeof(pf->data[0]));
memcpy(&(pf->data[i]), pc, sizeof(pf->data[0]));
is_ordered = 0;
}
}
flag--;
}
}
void Print(const Contacts* pf)
{
printf("%-20s\t%-10s\t%-3s\t%-12s\n", "Name", "Sex", "Age", "Phone Number");
if (pf->num == 0)
{
printf("Contacts is Null.\n");
return;
}
for (size_t i = 0; i < pf->num; i++)
{
printf("%-20s\t%-10s\t%-3d\t%-12s\n",
pf->data[i].name,
pf->data[i].sex,
pf->data[i].age,
pf->data[i].phone);
}
}
//使用文件data.txt初始化
void Read_from_File(Contacts* pf)
{
int i = 0;
FILE* pfile = fopen("data.txt", "r");
if (pfile == NULL)
{
perror("fopen");
return;
}
while (1)
{
Enlarge(pf);
if (fscanf(pfile, "%s %s %d %s\n",
pf->data[i].name,
pf->data[i].sex,
&(pf->data[i].age),
pf->data[i].phone) == EOF)
break;
i++;
(pf->num)++;
}
printf("Contacts Init successed.\n");
fclose(pfile);
pfile = NULL;
}
void Write_to_File(Contacts* pf)
{
FILE* pfile = fopen("data.txt", "w");
if (pfile == NULL)
{
perror("fopen");
return;
}
for (size_t i = 0; i < pf->num; i++)
{
fprintf(pfile, "%s %s %d %s\n",
pf->data[i].name,
pf->data[i].sex,
pf->data[i].age,
pf->data[i].phone);
}
fclose(pfile);
pfile = NULL;
}
void Enlarge(Contacts* pf)
{
if (pf->num == pf->size)
{
Info* ptr = (Info*)realloc(pf->data, (INC_SZ + pf->size)*sizeof(Info));
if (ptr != NULL)
{
printf("Enlarge Contacts.\n");
pf->data = ptr;
pf->size += INC_SZ;
}
else
{
perror("realloc");
return;
}
}
}
void FreeContacts(Contacts* pf)
{
free(pf->data);
pf->data = NULL;
}
contacts.c用于实现各种功能
//contacts.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 1000
//默认初始通讯录大小
#define DEFAULT_SZ 5
//扩大通讯录容量时每次增加的大小
#define INC_SZ 2
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
typedef struct information
{
int age;
char sex[10];
char name[20];
char phone[12];
}Info;
//动态大小通讯录
typedef struct contacts
{
Info* data;
int num;//通讯录当前有效信息
int size;//通讯录最大容量
}Contacts;
//初始菜单
void menu();
//初始化通讯录
void InitContacts(Contacts* pf);
//添加联系人
void Add(Contacts* pf);
//删除联系人
void Del(Contacts* pf);
//修改联系人
void Modify(Contacts* pf);
//查找联系人
void Find(const Contacts* pf);
//对联系人按姓名首字母由a-z排序
void Sort(Contacts* pf);
//打印联系人
void Print(const Contacts* pf);
//从文件中读取数据
void Read_from_File(Contacts* pf);
//写入修改到文件
void Write_to_File(Contacts* pf);
//释放为通讯录开辟的动态空间
void FreeContacts(Contacts* pf);
//增大通讯录的空间
void Enlarge(Contacts* pf);
contacts.h函数声明,结构体定义和头文件包含。
使用时在项目文件夹下创建一个data.txt用于存放数据。
写完这段代码后看了一本关于代码风格的书,发现有很多不足点。例如Read_from_File,Write_to_File函数命名,大小写字母命名和下划线不应该混合使用。在结构体定义时用typedef将通讯录结构体命名为了Contacts,而在创建结构体时创建名为contacts,当时没有意识到,后续使用时很容易混淆。