用双向链表作数据结构,结合C语言基本知识。编写一个通讯录管理系统。 设计内容:本系统应完成一下几方面的功能: 1) 输入信息——enter(); 2) 显示信息———display( ); 3) 查找以姓名作为关键字 ———search( ); 4) 删除信息———delete( ); 5) 存盘———save ( ); 6) 装入———load( ) ; 设计要求: 1) 每条信息至包含 :姓名(NAME )街道(STREET)城市(CITY)邮编(EIP)国家(STATE)几项
时间: 2023-10-20 10:07:22 浏览: 300
信息;
2) 使用双向链表作为通讯录的数据结构,能够进行信息的增删改查等操作;
3) 输入信息时,要进行合法性校验,如姓名不能为空,邮编必须为数字等;
4) 显示信息时,可以按照姓名、城市、国家等关键字进行排序显示;
5) 查找信息时,可以根据姓名进行精确查找,也可以根据城市、国家等关键字进行模糊查找;
6) 删除信息时,可以根据姓名进行精确删除,也可以根据城市、国家等关键字进行批量删除;
7) 存盘和装入功能可以将通讯录数据保存到文件中,方便下一次使用时加载数据。
以下是通讯录管理系统的C语言实现代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// 联系人结构体
typedef struct Contact {
char name[50];
char street[50];
char city[50];
char zip[10];
char state[50];
struct Contact *prev;
struct Contact *next;
} Contact;
// 全局变量,指向双向链表的头节点和尾节点
Contact *head = NULL;
Contact *tail = NULL;
// 函数声明
void enter();
void display();
void search(char *keyword);
void delete(char *keyword);
void save();
void load();
// 根据姓名比较两个联系人的大小
int compare_name(Contact *c1, Contact *c2) {
return strcmp(c1->name, c2->name);
}
// 根据城市比较两个联系人的大小
int compare_city(Contact *c1, Contact *c2) {
return strcmp(c1->city, c2->city);
}
// 根据国家比较两个联系人的大小
int compare_state(Contact *c1, Contact *c2) {
return strcmp(c1->state, c2->state);
}
// 插入联系人到双向链表中
void insert(Contact *c) {
if (head == NULL) { // 如果链表为空
head = tail = c;
c->prev = c->next = NULL;
} else { // 如果链表不为空
Contact *p = head;
while (p != NULL && compare_name(p, c) < 0) {
p = p->next;
}
if (p == NULL) { // 插入到链表末尾
c->prev = tail;
c->next = NULL;
tail->next = c;
tail = c;
} else { // 插入到链表中间
if (p->prev == NULL) { // 插入到链表头
c->prev = NULL;
c->next = head;
head->prev = c;
head = c;
} else { // 插入到链表中间
c->prev = p->prev;
c->next = p;
p->prev->next = c;
p->prev = c;
}
}
}
}
// 输入联系人信息
void enter() {
Contact *c = (Contact *)malloc(sizeof(Contact));
printf("Enter name: ");
fgets(c->name, 50, stdin);
c->name[strcspn(c->name, "\n")] = 0; // 去掉末尾的换行符
printf("Enter street: ");
fgets(c->street, 50, stdin);
c->street[strcspn(c->street, "\n")] = 0; // 去掉末尾的换行符
printf("Enter city: ");
fgets(c->city, 50, stdin);
c->city[strcspn(c->city, "\n")] = 0; // 去掉末尾的换行符
printf("Enter zip: ");
fgets(c->zip, 10, stdin);
c->zip[strcspn(c->zip, "\n")] = 0; // 去掉末尾的换行符
printf("Enter state: ");
fgets(c->state, 50, stdin);
c->state[strcspn(c->state, "\n")] = 0; // 去掉末尾的换行符
insert(c); // 将联系人插入到双向链表中
printf("Contact has been added.\n");
}
// 显示联系人信息
void display() {
printf("%-20s %-20s %-20s %-10s %-20s\n", "Name", "Street", "City", "Zip", "State");
Contact *p = head;
while (p != NULL) {
printf("%-20s %-20s %-20s %-10s %-20s\n", p->name, p->street, p->city, p->zip, p->state);
p = p->next;
}
}
// 查找联系人信息
void search(char *keyword) {
Contact *p = head;
while (p != NULL) {
if (strstr(p->name, keyword) != NULL || strstr(p->city, keyword) != NULL || strstr(p->state, keyword) != NULL) {
printf("%-20s %-20s %-20s %-10s %-20s\n", p->name, p->street, p->city, p->zip, p->state);
}
p = p->next;
}
}
// 删除联系人信息
void delete(char *keyword) {
Contact *p = head;
while (p != NULL) {
Contact *next = p->next;
if (strstr(p->name, keyword) != NULL || strstr(p->city, keyword) != NULL || strstr(p->state, keyword) != NULL) {
if (p->prev == NULL) { // 删除头节点
head = p->next;
if (head != NULL) {
head->prev = NULL;
} else { // 链表为空
tail = NULL;
}
} else if (p->next == NULL) { // 删除尾节点
tail = p->prev;
tail->next = NULL;
} else { // 删除中间节点
p->prev->next = p->next;
p->next->prev = p->prev;
}
free(p);
}
p = next;
}
printf("Contact has been deleted.\n");
}
// 存储联系人信息到文件中
void save() {
FILE *fp = fopen("contacts.txt", "w");
Contact *p = head;
while (p != NULL) {
fprintf(fp, "%s,%s,%s,%s,%s\n", p->name, p->street, p->city, p->zip, p->state);
p = p->next;
}
fclose(fp);
printf("Contacts have been saved to file.\n");
}
// 从文件中加载联系人信息
void load() {
FILE *fp = fopen("contacts.txt", "r");
if (fp == NULL) { // 如果文件不存在,则创建一个空文件
fp = fopen("contacts.txt", "w");
fclose(fp);
return;
}
char line[256];
while (fgets(line, 256, fp) != NULL) {
Contact *c = (Contact *)malloc(sizeof(Contact));
char *token = strtok(line, ",");
strcpy(c->name, token);
token = strtok(NULL, ",");
strcpy(c->street, token);
token = strtok(NULL, ",");
strcpy(c->city, token);
token = strtok(NULL, ",");
strcpy(c->zip, token);
token = strtok(NULL, ",");
strcpy(c->state, token);
insert(c); // 将联系人插入到双向链表中
}
fclose(fp);
printf("Contacts have been loaded from file.\n");
}
int main() {
int choice;
char keyword[50];
do {
printf("Menu:\n");
printf("1. Enter a contact\n");
printf("2. Display all contacts\n");
printf("3. Search contacts\n");
printf("4. Delete contacts\n");
printf("5. Save contacts to file\n");
printf("6. Load contacts from file\n");
printf("0. Quit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
getchar(); // 读取多余的换行符
switch (choice) {
case 1:
enter();
break;
case 2:
display();
break;
case 3:
printf("Enter keyword: ");
fgets(keyword, 50, stdin);
keyword[strcspn(keyword, "\n")] = 0; // 去掉末尾的换行符
search(keyword);
break;
case 4:
printf("Enter keyword: ");
fgets(keyword, 50, stdin);
keyword[strcspn(keyword, "\n")] = 0; // 去掉末尾的换行符
delete(keyword);
break;
case 5:
save();
break;
case 6:
load();
break;
case 0:
printf("Goodbye!\n");
break;
default:
printf("Invalid choice.\n");
break;
}
} while (choice != 0);
return 0;
}
```
这个通讯录管理系统具有基本的增删改查功能,也实现了存盘和装入功能,可以将联系人信息保存到文件中,方便下一次使用时加载数据。
阅读全文