C语言通讯录的实现(动态链表)
编译器VS2017
AddressList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct AddressList {
char sex;
int age;
char Tel[20];
char name[50];
char Add[100];
struct AddressList* next;
}AL;
enum {
退出,
添加,
删除,
修改,
查找,
显示,
清空,
排序,
保存,
读取,
};
int Menu();//菜单
void AddressList();
void input(AL*);//输入
AL* add(AL*);//增
void del(AL*);//删
void alter(AL*); //改
AL** allfind(AL*);//查
AL* find_1(AL*, const char*);//按姓名找
AL* find_2(AL*, const char*);//按年龄找
AL* find_3(AL*, const char*);//按电话号码找
AL* find_4(AL*, const char*);//按地址找
void print(AL*);//输出
void allprint(AL*); //全部输出
int empty(AL*);//清空
void swap(AL*, AL*);//交换
int sort(AL*);//排序
int save(AL*);//保存
void finput(AL*, FILE*);//
AL* read(AL*);//读取
func.h
#pragma once
#include"AddressList.h"
int Menu() {//菜单
int choic;
int n = 0;
printf("1.添加联系人 2.删除联系人\n"
"3.修改联系人信息 4.查找联系人\n"
"5.显示所有联系人 6.清空所有联系人\n"
"7.按名称排序 8.保存到文件\n"
"9.从文件中读取联系人 0.退出\n"
"请输入您的选项!\n");
n = scanf("%d", &choic);
while (n != 1 || choic < 0 || choic > 9) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%d", &choic);
}
return choic;
}
void input(AL* p) {
int n = 0;
printf("请输入姓名\n");
scanf("%s", p->name);
getchar();
printf("请输入性别,男m,女f\n");
n = scanf("%c", &p->sex);
while (n != 1 || p->sex != 'm' && p->sex != 'f') {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%c", &p->sex);
}
printf("请输入年龄\n");
n = scanf("%d", &p->age);
while (n != 1 || p->age <= 0 || p->age > 130) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%d", &p->age);
}
printf("请输入地址\n");
scanf("%s", p->Add);
printf("请输入电话号码\n");
scanf("%s", p->Tel);
}
AL* add(AL* temphead) {//增
int n = 0;
AL* p = temphead;
AL* s = NULL;
char choic;
do {
s = (AL*)malloc(sizeof(AL));
if (s == NULL) {
exit(EXIT_FAILURE);
}
input(s);
s->next = p->next;
p->next = s;
p = p->next;
p->next = NULL;
printf("继续输入请输入'y'\n");
getchar();
n = scanf("%c", &choic);
while (n != 1) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%c", &choic);
}
} while (choic == 'y');
system("cls");
return p;
}
void del(AL* p) {//删
AL* temp;
temp = p->next;
p->next = temp->next;
free(temp);
}
void alter(AL* p) {//改
input(p->next);
}
AL* find_1(AL* p, const char* str) {//按姓名找
if (strstr(p->next->name, str)) {
return p;
}
return NULL;
}
AL* find_2(AL* p, const char* str) {//按年龄找
char temp[5];
sprintf(temp, "%d", p->next->age);
if (strstr(temp, str)) {
return p;
}
return NULL;
}
AL* find_3(AL* p, const char* str) {//按电话号码找
if (strstr(p->next->Tel, str)) {
return p;
}
return NULL;
}
AL* find_4(AL* p, const char* str) {//按地址找
if (strstr(p->next->Add, str)) {
return p;
}
return NULL;
}
AL** allfind(AL* head) {//查
if (head->next == NULL) {
printf("还未添加联系人\n");
return NULL;
}
char str[100] = { 0 };
AL* find = NULL;
AL** ptr = NULL;
ptr = (AL**)calloc(4, sizeof(AL*));
if (ptr == NULL) {
exit(EXIT_FAILURE);
}
printf("请输入需要查找的信息\n");
scanf("%s", str);
static int count;
count = 1;
int m = 4;
for (AL* p = head; p->next != NULL; p = p->next) {
if (count >= m) {
m += 4;
AL** pt = (AL**)realloc(ptr, m * sizeof(AL*));
if (pt == NULL) {
exit(EXIT_FAILURE);
}
ptr = pt;
}
if (find = find_1(p, str)) {
ptr[count++] = find;
continue;
}
if (find = find_2(p, str)) {
ptr[count++] = find;
continue;
}
if (find = find_3(p, str)) {
ptr[count++] = find;
continue;
}
if (find = find_4(p, str)) {
ptr[count++] = find;
continue;
}
}
if (count != 0) {
printf("序号\t姓名\t性别\t年龄\t地址\t\t电话\t\t\n");
for (int i = 1; i < count; ++i) {
printf("%d\t", i);
print(ptr[i]->next);
}
ptr[0] = (AL*)&count;
return ptr;
}
return NULL;
}
void print(AL* p) {//输出
printf("%s\t%c\t%d\t%s\t\t%s\t\t\n", p->name, p->sex, p->age, p->Add, p->Tel);
}
void allprint(AL* head) {//全部输出
if (head->next == NULL) {
printf("没有联系人\n");
return;
}
printf("序号\t姓名\t性别\t年龄\t地址\t\t电话\t\t\n");
int i = 1;
for (AL* p = head->next; p != NULL; p = p->next, ++i) {
printf("%d\t", i);
print(p);
}
}
int empty(AL* head) {//清空
if (head->next == NULL) {
return 0;
}
for (AL* p = head; p->next != NULL;) {
del(p);
}
return 1;
}
void swap(AL* p, AL* q) {
AL temp;
AL* t;
temp = *p;
*p = *q;
*q = temp;
t = p->next;
p->next = q->next;
q->next = t;
}
int sort(AL* head) {
if (head->next == NULL) {
return 0;
}
for (AL* p = head->next; p != NULL; p = p->next) {
for (AL* q = p->next; q != NULL; q = q->next) {
if (strcmp(p->name, q->name) > 0) {
swap(p, q);
}
}
}
return 1;
}
int save(AL* head) {
FILE* fp;//定义指向文件型数据的指针变量(是一个结构体变量)fp
char temp[5] = { 0 };
int choic;
int n = 0;
if (head->next == NULL) {
return -1;
}
if ((fp = fopen("AL.txt", "r+")) == NULL) {//fopen(文件名,使用方式),此处w为write,只写.
//应返回指向这个文件的指针,文件不存在则建立新文件,既不存在又创建新文件失败则返回NULL
return 0;//
}
getc(fp);
if (feof(fp)) {
printf("文件为空,直接保存!\n");
fclose(fp);
fp = NULL;
if ((fp = fopen("AL.txt", "w+")) == NULL) {//fopen(文件名,使用方式),此处w为write,只写.
//应返回指向这个文件的指针,文件不存在则建立新文件,既不存在又创建新文件失败则返回NULL
return 0;//
}
}
else {
fclose(fp);
fp = NULL;
printf("1.覆盖 2.并入\n请输入选择\n");
n = scanf("%d", &choic);
while (n != 1 || choic < 1 || choic > 2) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%d", &choic);
}
if (choic == 1) {
if ((fp = fopen("AL.txt", "w+")) == NULL) {//fopen(文件名,使用方式),此处w为write,只写.
//应返回指向这个文件的指针,文件不存在则建立新文件,既不存在又创建新文件失败则返回NULL
return 0;//
}
}
else {
if ((fp = fopen("AL.txt", "a+")) == NULL) {
return 0;
}
}
}
for (AL* p = head->next; p != NULL; p = p->next) {
#if 0
fputs(p->name, fp);
fputc(' ', fp);
fputc(p->sex, fp);
fputc(' ', fp);
sprintf(temp, "%d", p->age);
fputs(temp, fp);
fputc(' ', fp);
fputs(p->Add, fp);
fputc(' ', fp);
fputs(p->Tel, fp);
fputc('\n', fp);
#endif
#if 1
fprintf(fp, "%s ", p->name);
fprintf(fp, "%c ", p->sex);
fprintf(fp, "%d ", p->age);
fprintf(fp, "%s ", p->Add);
fprintf(fp, "%s\n", p->Tel);
#endif
}
fclose(fp);//关闭
return 1;
}
void finput(AL* p, FILE* fp) {
fscanf(fp, "%s", p->name);
fgetc(fp);
fscanf(fp, "%c", &p->sex);
fscanf(fp, "%d", &p->age);
fscanf(fp, "%s", p->Add);
fscanf(fp, "%s", p->Tel);
}
AL* read(AL* temphead) {
FILE* fp;//定义指向文件型数据的指针变量(是一个结构体变量)fp
AL* p = temphead;
AL* s = NULL;
if ((fp = fopen("AL.txt", "r+")) == NULL) {//fopen(文件名,使用方式),此处r为read,只写.
//应返回指向这个文件的指针,文件不存在则返回NULL
printf("没有保存的联系人文件!\n");
return p;//
}
getc(fp);
if (feof(fp)) {//遇见EOF返回非0
printf("文件为空!\n");
fclose(fp);
return p;
}
while (1) {
s = (AL*)malloc(sizeof(AL));
if (s == NULL) {
exit(EXIT_FAILURE);
}
finput(s, fp);
if (feof(fp)) {//遇见EOF返回非0
break;
}
s->next = p->next;
p->next = s;
p = p->next;
p->next = NULL;
}
fclose(fp);
printf("读取成功!\n");
return p;
}
void AddressList() {
int n = 0;
int choic_1;
AL** find = NULL;
int choic_2;
int choic_3;
AL* head = (AL*)malloc(sizeof(AL));//头结点
head->next = NULL;
if (head == NULL) {
exit(EXIT_FAILURE);
}
AL* temphead = head;
while (1) {
choic_1 = Menu();
switch (choic_1) {
case 添加:
temphead = add(temphead);
break;
case 删除:
if ((find = allfind(head)) == NULL) {
printf("未找到!\n");
}
else {
printf("请输入需要删除的选项\n");
n = scanf("%d", &choic_2);
while (n != 1 || choic_2 < 1 || choic_2 > *(int*)find[0] - 1) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%d", &choic_2);
}
del(find[choic_2]);
free(find);
find = NULL;
printf("删除成功!\n");
}
system("pause");
system("cls");
break;
case 修改:
if ((find = allfind(head)) == NULL) {
printf("未找到!\n");
}
else {
printf("请输入需要修改的选项\n");
n = scanf("%d", &choic_2);
while (n != 1 || choic_2 < 1 || choic_2 > *(int*)find[0] - 1) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%d", &choic_2);
}
alter(find[choic_2]);
free(find);
find = NULL;
printf("修改成功!\n");
}
system("pause");
system("cls");
break;
case 查找:
find = allfind(head);
free(find);
find = NULL;
system("pause");
system("cls");
break;
case 显示:
allprint(head);
system("pause");
system("cls");
break;
case 清空://全部删除
if (empty(head)) {
temphead = head;
printf("已清空\n");
}
else {
printf("联系人为空\n");
}
system("pause");
system("cls");
break;
case 排序:
if (sort(head)) {
printf("已排序!\n");
}
else {
printf("联系人为空!\n");
}
system("pause");
system("cls");
break;
case 保存:
n = save(head);
if (n == 1) {
printf("保存成功!\n");
}
else if (n == 0) {
printf("打开文件或创建文件失败!\n");
}
else {
printf("联系人为空!\n");
}
system("pause");
system("cls");
break;
case 读取:
if (head->next != NULL) {//已有数据
printf("已有数据!\n");
printf("1.覆盖 2.并入\n请输入选项\n");
n = scanf("%d", &choic_3);
while (n != 1 || choic_3 < 1 || choic_3 > 2) {
printf("您的输入有误,请重新输入\n");
while (getchar() != '\n');
n = scanf("%d", &choic_3);
}
if (choic_3 == 1) {
temphead = read(head);
}
else {
temphead = read(temphead);
}
}
else {
temphead = read(head);
}
system("pause");
system("cls");
break;
case 退出:
printf("再见!\n");
system("pause");
exit(0);
break;
default:
printf("出错!\n");
system("pause");
exit(0);
}
}
}
.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"func.h"
int main() {
AddressList();
return 0;
}
先输入数据
显示联系人
查找联系人
删除联系人,删除前需要查找,修改也需要查找,这里就不再演示
删除之后在查看联系人
保存
我们可以打开创建的AL.txt,发现数据已经保存
读取文件中的数据,如果我们已经输入了数据, 可以选择覆盖或者并入
选择并入可以看到文件中的信息已经读取并加到了后面