项目:基于链表的通信录管理
意义:对于一个通信录来说,要管理联系人的信息,包括编号,姓名,性别,电话。
—级菜单内容
1>注册模块:完成用户信息的注册用于登录管理系统,将注册信息存入结构体数组
2>登录模块:使用输入的登录账号和密码与结构体数组存储信息对比
3>退出系统
二级菜单内容:
1>创建模块create:创建链表完成对通信录的存储
2>添加数据add:添加通信录的信息放入链表中
3>查找信息find:可以通过姓名进行查找
4>修改信息update:可以修改联系人信息并保存,修改联系人信息有
包括了对联系人编号,姓名,性别,电话号码的分别修改
5>删除信息delete:可根据输入的姓名进行删除
6>插入信息insert:将给定的信息以及插入位置信息完成插入
7>展示信息show:将通讯录的所有信息进行展示
8>按照姓名将通讯录排序
9>返回上一级
辅助功能:
10>初始化链表init:将链表进行初始化
11>获取链表长度getLength:
12>统计性别;
方案一:通信录: 每个用户使用独立的链表存联系人信息
#include
#include
#include
// 定义联系人结构体
typedef struct Contact {
int id; // 联系人编号
char name[50]; // 姓名
char gender[10]; // 性别
char phone[20]; // 电话
struct Contact* next; // 指向下一个联系人的指针
} Contact;
// 定义用户结构体(包含独立的联系人链表)
typedef struct {
char username[50];
char password[50];
Contact* contactHead; // 该用户的联系人链表头指针
} User;
// 全局变量
User users[100]; // 用户数组
int userCount = 0; // 用户数量
int loggedIn = 0; // 登录状态
int currentUserId = -1; // 当前用户ID
// 函数声明
Contact* initContactList();
int getLength(Contact* head);
void createContact();
void addContact();
void findContact();
void updateContact();
void deleteContact();
void insertContact();
void showContacts();
void sortContactsByName();
void countGender();
void registerUser();
int login();
void saveContactsToFile(User* user);
void loadContactsFromFile(User* user);
void freeContacts(Contact* head);
// 初始化链表
Contact* initContactList() {
return NULL; // 初始化为空链表
}
// 获取链表长度
int getLength(Contact* head) {
int count = 0;
Contact* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
// 创建联系人(初始化当前用户的链表)
void createContact() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
// 释放现有链表并初始化为空
freeContacts(users[currentUserId].contactHead);
users[currentUserId].contactHead = initContactList();
printf("链表已初始化,现在可以添加联系人了。\n");
}
// 添加联系人
void addContact() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("请先创建链表!\n");
return;
}
Contact* newContact = (Contact*)malloc(sizeof(Contact));
if (newContact == NULL) {
printf("内存分配失败!\n");
return;
}
// 自动分配ID
newContact->id = getLength(head) + 1;
printf("请输入姓名: ");
scanf("%s", newContact->name);
printf("请输入性别: ");
scanf("%s", newContact->gender);
printf("请输入电话: ");
scanf("%s", newContact->phone);
// 添加到链表尾部
newContact->next = head;
users[currentUserId].contactHead = newContact; // 更新头指针
printf("联系人添加成功!ID: %d\n", newContact->id);
}
// 查找联系人
void findContact() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("通信录为空!\n");
return;
}
char name[50];
printf("请输入要查找的姓名: ");
scanf("%s", name);
Contact* current = head;
int found = 0;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
printf("ID: %d, 姓名: %s, 性别: %s, 电话: %s\n",
current->id, current->name, current->gender, current->phone);
found = 1;
}
current = current->next;
}
if (!found) {
printf("未找到该联系人!\n");
}
}
// 修改联系人信息
void updateContact() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("通信录为空!\n");
return;
}
int id;
printf("请输入要修改的联系人ID: ");
scanf("%d", &id);
Contact* current = head;
while (current != NULL && current->id != id) {
current = current->next;
}
if (current == NULL) {
printf("未找到该联系人!\n");
return;
}
printf("当前信息 - ID: %d, 姓名: %s, 性别: %s, 电话: %s\n",
current->id, current->name, current->gender, current->phone);
char choice;
char temp[50];
printf("是否修改姓名?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新姓名: ");
scanf("%s", temp);
strcpy(current->name, temp);
}
printf("是否修改性别?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新性别: ");
scanf("%s", temp);
strcpy(current->gender, temp);
}
printf("是否修改电话?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新电话: ");
scanf("%s", temp);
strcpy(current->phone, temp);
}
printf("联系人信息已更新!\n");
}
// 删除联系人
void deleteContact() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("通信录为空!\n");
return;
}
char name[50];
printf("请输入要删除的联系人姓名: ");
scanf("%s", name);
Contact* current = head;
Contact* previous = NULL;
int found = 0;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
if (previous == NULL) {
users[currentUserId].contactHead = current->next; // 更新头指针
} else {
previous->next = current->next;
}
free(current);
printf("联系人已删除!\n");
found = 1;
break;
}
previous = current;
current = current->next;
}
if (!found) {
printf("未找到该联系人!\n");
} else {
// 重新编号
int i = 1;
current = users[currentUserId].contactHead;
while (current != NULL) {
current->id = i++;
current = current->next;
}
}
}
// 插入联系人
void insertContact() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("请先创建链表!\n");
return;
}
int position;
printf("请输入插入位置(在该位置之后插入): ");
scanf("%d", &position);
if (position < 0 || position > getLength(head)) {
printf("插入位置无效!\n");
return;
}
Contact* newContact = (Contact*)malloc(sizeof(Contact));
if (newContact == NULL) {
printf("内存分配失败!\n");
return;
}
printf("请输入姓名: ");
scanf("%s", newContact->name);
printf("请输入性别: ");
scanf("%s", newContact->gender);
printf("请输入电话: ");
scanf("%s", newContact->phone);
if (position == 0) {
// 插入到头部
newContact->id = 1;
newContact->next = head;
users[currentUserId].contactHead = newContact; // 更新头指针
// 重新编号
int i = 2;
Contact* current = newContact->next;
while (current != NULL) {
current->id = i++;
current = current->next;
}
} else {
// 插入到中间或尾部
Contact* current = head;
for (int i = 1; i < position; i++) {
current = current->next;
}
newContact->id = current->id + 1;
newContact->next = current->next;
current->next = newContact;
// 更新后续节点的编号
current = newContact->next;
while (current != NULL) {
current->id++;
current = current->next;
}
}
printf("联系人插入成功!\n");
}
// 展示所有联系人
void showContacts() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("通信录为空!\n");
return;
}
printf("=== %s的通信录列表 ===\n", users[currentUserId].username);
printf("ID\t姓名\t性别\t电话\n");
printf("------------------------\n");
Contact* current = head;
while (current != NULL) {
printf("%d\t%s\t%s\t%s\n",
current->id, current->name, current->gender, current->phone);
current = current->next;
}
}
// 按姓名排序
void sortContactsByName() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL || head->next == NULL) {
printf("通信录为空或只有一个联系人,无需排序!\n");
return;
}
int swapped;
Contact* ptr1;
Contact* lptr = NULL;
do {
swapped = 0;
ptr1 = head;
while (ptr1->next != lptr) {
if (strcmp(ptr1->name, ptr1->next->name) > 0) {
// 交换节点数据
Contact temp = *ptr1;
strcpy(temp.name, ptr1->name);
strcpy(temp.gender, ptr1->gender);
strcpy(temp.phone, ptr1->phone);
strcpy(ptr1->name, ptr1->next->name);
strcpy(ptr1->gender, ptr1->next->gender);
strcpy(ptr1->phone, ptr1->next->phone);
strcpy(ptr1->next->name, temp.name);
strcpy(ptr1->next->gender, temp.gender);
strcpy(ptr1->next->phone, temp.phone);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
} while (swapped);
printf("通信录已按姓名排序!\n");
}
// 统计性别
void countGender() {
if (currentUserId == -1) {
printf("请先登录!\n");
return;
}
Contact* head = users[currentUserId].contactHead;
if (head == NULL) {
printf("通信录为空!\n");
return;
}
int maleCount = 0;
int femaleCount = 0;
int otherCount = 0;
Contact* current = head;
while (current != NULL) {
if (strcmp(current->gender, "男") == 0 || strcmp(current->gender, "male") == 0) {
maleCount++;
} else if (strcmp(current->gender, "女") == 0 || strcmp(current->gender, "female") == 0) {
femaleCount++;
} else {
otherCount++;
}
current = current->next;
}
printf("性别统计结果:\n");
printf("男: %d\n", maleCount);
printf("女: %d\n", femaleCount);
printf("其他: %d\n", otherCount);
}
// 从文件加载用户数据
void loadUsers() {
FILE *file = fopen("users.dat", "r");
if (file == NULL) {
// 文件不存在则创建(首次运行)
return;
}
userCount = 0;
while (fscanf(file, "%s %s", users[userCount].username, users[userCount].password) == 2) {
users[userCount].contactHead = initContactList(); // 初始化联系人链表
userCount++;
}
fclose(file);
}
// 向文件写入用户数据(注册时调用)
void saveUser(User newUser) {
FILE *file = fopen("users.dat", "a"); // 追加模式
if (file == NULL) {
printf("保存用户失败!\n");
return;
}
fprintf(file, "%s %s\n", newUser.username, newUser.password);
fclose(file);
}
// 注册用户
void registerUser() {
if (userCount >= 100) {
printf("用户数量已达到上限!\n");
return;
}
User newUser;
printf("请输入用户名: ");
scanf("%s", newUser.username);
// 检查用户名是否已存在
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, newUser.username) == 0) {
printf("用户名已存在!\n");
return;
}
}
printf("请输入密码: ");
scanf("%s", newUser.password);
// 初始化用户的联系人链表
newUser.contactHead = initContactList();
// 先写入文件持久化,再更新内存数组
saveUser(newUser);
users[userCount++] = newUser;
printf("注册成功!\n");
}
// 用户登录
int login() {
if (userCount == 0) {
printf("没有注册用户,请先注册!\n");
return 0;
}
char username[50];
char password[50];
printf("请输入用户名: ");
scanf("%s", username);
printf("请输入密码: ");
scanf("%s", password);
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, username) == 0 &&
strcmp(users[i].password, password) == 0) {
printf("登录成功!欢迎,%s\n", username);
currentUserId = i;
loadContactsFromFile(&users[i]); // 加载用户的联系人数据
return 1;
}
}
printf("用户名或密码错误!\n");
return 0;
}
// 保存联系人到文件
void saveContactsToFile(User* user) {
if (user->contactHead == NULL) {
printf("通信录为空,无需保存!\n");
return;
}
char filename[100];
sprintf(filename, "%s_contacts.txt", user->username);
FILE* file = fopen(filename, "w");
if (file == NULL) {
printf("无法打开文件!\n");
return;
}
Contact* current = user->contactHead;
while (current != NULL) {
fprintf(file, "%d %s %s %s\n",
current->id, current->name, current->gender, current->phone);
current = current->next;
}
fclose(file);
printf("联系人已保存到文件!\n");
}
// 从文件加载联系人
void loadContactsFromFile(User* user) {
// 释放现有链表
freeContacts(user->contactHead);
user->contactHead = initContactList();
char filename[100];
sprintf(filename, "%s_contacts.txt", user->username);
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("未找到保存的联系人文件,将使用空通信录!\n");
return;
}
Contact temp;
while (fscanf(file, "%d %s %s %s",
&temp.id, temp.name, temp.gender, temp.phone) != EOF) {
Contact* newContact = (Contact*)malloc(sizeof(Contact));
*newContact = temp;
// 插入到链表头部(效率更高)
newContact->next = user->contactHead;
user->contactHead = newContact;
}
fclose(file);
printf("联系人已从文件加载!\n");
}
// 释放链表内存
void freeContacts(Contact* head) {
Contact* current = head;
Contact* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
}
// 二级菜单(联系人管理)
void contactMenu() {
int choice;
do {
printf("\n=== 通信录管理菜单 ===\n");
printf("1. 创建模块(create)\n");
printf("2. 添加数据(add)\n");
printf("3. 查找信息(find)\n");
printf("4. 修改信息(update)\n");
printf("5. 删除信息(delete)\n");
printf("6. 插入信息(insert)\n");
printf("7. 展示信息(show)\n");
printf("8. 按姓名排序\n");
printf("9. 统计性别\n");
printf("10. 返回上一级\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
createContact();
break;
case 2:
addContact();
break;
case 3:
findContact();
break;
case 4:
updateContact();
break;
case 5:
deleteContact();
break;
case 6:
insertContact();
break;
case 7:
showContacts();
break;
case 8:
sortContactsByName();
break;
case 9:
countGender();
break;
case 10:
saveContactsToFile(&users[currentUserId]); // 返回前保存数据
printf("返回主菜单...\n");
break;
default:
printf("无效选择,请重新输入!\n");
}
} while (choice != 10);
}
// 一级菜单(主菜单)
void mainMenu() {
int choice;
do {
printf("\n=== 通信录系统主菜单 ===\n");
printf("1. 注册模块\n");
printf("2. 登录模块\n");
printf("3. 退出系统\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
registerUser();
break;
case 2:
loggedIn = login();
if (loggedIn) {
contactMenu(); // 登录成功后进入联系人管理菜单
}
break;
case 3:
printf("感谢使用通信录系统,再见!\n");
break;
default:
printf("无效选择,请重新输入!\n");
}
} while (choice != 3);
}
int main() {
// 程序启动时加载用户数据
loadUsers();
mainMenu();
// 程序退出前释放所有用户的联系人链表
for (int i = 0; i < userCount; i++) {
freeContacts(users[i].contactHead);
}
return 0;
}
方案二:通信录:全部用户,共用同一个联系人链表
#include
#include
#include
// 定义用户结构体
typedef struct {
char username[50];
char password[50];
} User;
// 定义联系人结构体
typedef struct Contact {
int id; // 联系人编号
char name[50]; // 姓名
char gender[10]; // 性别
char phone[20]; // 电话
struct Contact* next; // 指向下一个联系人的指针
} Contact;
// 全局变量
Contact* head = NULL; // 链表头指针
User users[100]; // 用户数组
int userCount = 0; // 用户数量
int loggedIn = 0; // 登录状态
int currentUserId = -1; // 当前用户ID
// 函数声明
void initContactList();
int getLength();
void createContact();
void addContact();
void findContact();
void updateContact();
void deleteContact();
void insertContact();
void showContacts();
void sortContactsByName();
void countGender();
void registerUser();
int login();
void saveContactsToFile();
void loadContactsFromFile();
void freeContacts();
// 初始化链表
void initContactList() {
freeContacts(); // 释放现有内存
head = NULL;
}
// 获取链表长度
int getLength() {
int count = 0;
Contact* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
// 创建联系人(用于初始化链表)
void createContact() {
initContactList();
printf("链表已初始化,现在可以添加联系人了。\n");
}
// 添加联系人
void addContact() {
if (head == NULL) {
printf("请先创建链表!\n");
return;
}
Contact* newContact = (Contact*)malloc(sizeof(Contact));
if (newContact == NULL) {
printf("内存分配失败!\n");
return;
}
// 自动分配ID
newContact->id = getLength() + 1;
printf("请输入姓名: ");
scanf("%s", newContact->name);
printf("请输入性别: ");
scanf("%s", newContact->gender);
printf("请输入电话: ");
scanf("%s", newContact->phone);
// 添加到链表尾部
if (head == NULL) {
head = newContact;
newContact->next = NULL;
} else {
Contact* temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newContact;
newContact->next = NULL;
}
printf("联系人添加成功!ID: %d\n", newContact->id);
}
// 查找联系人
void findContact() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
char name[50];
printf("请输入要查找的姓名: ");
scanf("%s", name);
Contact* current = head;
int found = 0;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
printf("ID: %d, 姓名: %s, 性别: %s, 电话: %s\n",
current->id, current->name, current->gender, current->phone);
found = 1;
}
current = current->next;
}
if (!found) {
printf("未找到该联系人!\n");
}
}
// 修改联系人信息
void updateContact() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
int id;
printf("请输入要修改的联系人ID: ");
scanf("%d", &id);
Contact* current = head;
while (current != NULL && current->id != id) {
current = current->next;
}
if (current == NULL) {
printf("未找到该联系人!\n");
return;
}
printf("当前信息 - ID: %d, 姓名: %s, 性别: %s, 电话: %s\n",
current->id, current->name, current->gender, current->phone);
char choice;
char temp[50];
printf("是否修改姓名?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新姓名: ");
scanf("%s", temp);
strcpy(current->name, temp);
}
printf("是否修改性别?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新性别: ");
scanf("%s", temp);
strcpy(current->gender, temp);
}
printf("是否修改电话?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新电话: ");
scanf("%s", temp);
strcpy(current->phone, temp);
}
printf("联系人信息已更新!\n");
}
// 删除联系人
void deleteContact() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
char name[50];
printf("请输入要删除的联系人姓名: ");
scanf("%s", name);
Contact* current = head;
Contact* previous = NULL;
int found = 0;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
if (previous == NULL) {
head = current->next;
} else {
previous->next = current->next;
}
free(current);
printf("联系人已删除!\n");
found = 1;
break;
}
previous = current;
current = current->next;
}
if (!found) {
printf("未找到该联系人!\n");
} else {
// 重新编号
int i = 1;
current = head;
while (current != NULL) {
current->id = i++;
current = current->next;
}
}
}
// 插入联系人
void insertContact() {
if (head == NULL) {
printf("请先创建链表!\n");
return;
}
int position;
printf("请输入插入位置(在该位置之后插入): ");
scanf("%d", &position);
if (position < 0 || position > getLength()) {
printf("插入位置无效!\n");
return;
}
Contact* newContact = (Contact*)malloc(sizeof(Contact));
if (newContact == NULL) {
printf("内存分配失败!\n");
return;
}
printf("请输入姓名: ");
scanf("%s", newContact->name);
printf("请输入性别: ");
scanf("%s", newContact->gender);
printf("请输入电话: ");
scanf("%s", newContact->phone);
if (position == 0) {
// 插入到头部
newContact->id = 1;
newContact->next = head;
head = newContact;
// 重新编号
int i = 2;
Contact* current = head->next;
while (current != NULL) {
current->id = i++;
current = current->next;
}
} else {
// 插入到中间或尾部
Contact* current = head;
for (int i = 1; i < position; i++) {
current = current->next;
}
newContact->id = current->id + 1;
newContact->next = current->next;
current->next = newContact;
// 更新后续节点的编号
current = newContact->next;
while (current != NULL) {
current->id++;
current = current->next;
}
}
printf("联系人插入成功!\n");
}
// 展示所有联系人
void showContacts() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
printf("=== 通信录列表 ===\n");
printf("ID\t姓名\t性别\t电话\n");
printf("------------------------\n");
Contact* current = head;
while (current != NULL) {
printf("%d\t%s\t%s\t%s\n",
current->id, current->name, current->gender, current->phone);
current = current->next;
}
}
// 按姓名排序
void sortContactsByName() {
if (head == NULL || head->next == NULL) {
printf("通信录为空或只有一个联系人,无需排序!\n");
return;
}
int swapped;
Contact* ptr1;
Contact* lptr = NULL;
do {
swapped = 0;
ptr1 = head;
while (ptr1->next != lptr) {
if (strcmp(ptr1->name, ptr1->next->name) > 0) {
// 交换节点数据
Contact temp = *ptr1;
strcpy(temp.name, ptr1->name);
strcpy(temp.gender, ptr1->gender);
strcpy(temp.phone, ptr1->phone);
strcpy(ptr1->name, ptr1->next->name);
strcpy(ptr1->gender, ptr1->next->gender);
strcpy(ptr1->phone, ptr1->next->phone);
strcpy(ptr1->next->name, temp.name);
strcpy(ptr1->next->gender, temp.gender);
strcpy(ptr1->next->phone, temp.phone);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
} while (swapped);
printf("通信录已按姓名排序!\n");
}
// 统计性别
void countGender() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
int maleCount = 0;
int femaleCount = 0;
int otherCount = 0;
Contact* current = head;
while (current != NULL) {
if (strcmp(current->gender, "男") == 0 || strcmp(current->gender, "male") == 0) {
maleCount++;
} else if (strcmp(current->gender, "女") == 0 || strcmp(current->gender, "female") == 0) {
femaleCount++;
} else {
otherCount++;
}
current = current->next;
}
printf("性别统计结果:\n");
printf("男: %d\n", maleCount);
printf("女: %d\n", femaleCount);
printf("其他: %d\n", otherCount);
}
// 注册用户
void registerUser() {
if (userCount >= 100) {
printf("用户数量已达到上限!\n");
return;
}
User newUser;
printf("请输入用户名: ");
scanf("%s", newUser.username);
// 检查用户名是否已存在
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, newUser.username) == 0) {
printf("用户名已存在!\n");
return;
}
}
printf("请输入密码: ");
scanf("%s", newUser.password);
users[userCount++] = newUser;
printf("注册成功!\n");
}
// 用户登录
int login() {
if (userCount == 0) {
printf("没有注册用户,请先注册!\n");
return 0;
}
char username[50];
char password[50];
printf("请输入用户名: ");
scanf("%s", username);
printf("请输入密码: ");
scanf("%s", password);
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, username) == 0 &&
strcmp(users[i].password, password) == 0) {
printf("登录成功!欢迎,%s\n", username);
currentUserId = i;
loadContactsFromFile(); // 加载用户的联系人数据
return 1;
}
}
printf("用户名或密码错误!\n");
return 0;
}
// 保存联系人到文件
void saveContactsToFile() {
if (head == NULL) {
printf("通信录为空,无需保存!\n");
return;
}
char filename[100];
sprintf(filename, "%s_contacts.txt", users[currentUserId].username);
FILE* file = fopen(filename, "w");
if (file == NULL) {
printf("无法打开文件!\n");
return;
}
Contact* current = head;
while (current != NULL) {
fprintf(file, "%d %s %s %s\n",
current->id, current->name, current->gender, current->phone);
current = current->next;
}
fclose(file);
printf("联系人已保存到文件!\n");
}
// 从文件加载联系人
void loadContactsFromFile() {
initContactList(); // 清空现有链表
char filename[100];
sprintf(filename, "%s_contacts.txt", users[currentUserId].username);
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("未找到保存的联系人文件,将使用空通信录!\n");
return;
}
Contact temp;
while (fscanf(file, "%d %s %s %s",
&temp.id, temp.name, temp.gender, temp.phone) != EOF) {
Contact* newContact = (Contact*)malloc(sizeof(Contact));
*newContact = temp;
newContact->next = NULL;
if (head == NULL) {
head = newContact;
} else {
Contact* current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = newContact;
}
}
fclose(file);
printf("联系人已从文件加载!\n");
}
// 释放链表内存
void freeContacts() {
Contact* current = head;
Contact* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
head = NULL;
}
// 二级菜单(联系人管理)
void contactMenu() {
int choice;
do {
printf("\n=== 通信录管理菜单 ===\n");
printf("1. 创建模块(create)\n");
printf("2. 添加数据(add)\n");
printf("3. 查找信息(find)\n");
printf("4. 修改信息(update)\n");
printf("5. 删除信息(delete)\n");
printf("6. 插入信息(insert)\n");
printf("7. 展示信息(show)\n");
printf("8. 按姓名排序\n");
printf("9. 统计性别\n");
printf("10. 返回上一级\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
createContact();
break;
case 2:
addContact();
break;
case 3:
findContact();
break;
case 4:
updateContact();
break;
case 5:
deleteContact();
break;
case 6:
insertContact();
break;
case 7:
showContacts();
break;
case 8:
sortContactsByName();
break;
case 9:
countGender();
break;
case 10:
saveContactsToFile(); // 返回前保存数据
printf("返回主菜单...\n");
break;
default:
printf("无效选择,请重新输入!\n");
}
} while (choice != 10);
}
// 一级菜单(主菜单)
void mainMenu() {
int choice;
do {
printf("\n=== 通信录系统主菜单 ===\n");
printf("1. 注册模块\n");
printf("2. 登录模块\n");
printf("3. 退出系统\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
registerUser();
break;
case 2:
loggedIn = login();
if (loggedIn) {
contactMenu(); // 登录成功后进入联系人管理菜单
}
break;
case 3:
printf("感谢使用通信录系统,再见!\n");
break;
default:
printf("无效选择,请重新输入!\n");
}
} while (choice != 3);
}
int main() {
mainMenu();
return 0;
}
方案三:通信录: 全部用户共用一个联系人链表。实现使用,后续注册的用户的用户名和密码登录
#include
#include
#include
// 定义用户结构体
typedef struct {
char username[50];
char password[50];
} User;
// 定义联系人结构体
typedef struct Contact {
int id; // 联系人编号
char name[50]; // 姓名
char gender[10]; // 性别
char phone[20]; // 电话
struct Contact* next; // 指向下一个联系人的指针
} Contact;
// 全局变量
Contact* head = NULL; // 链表头指针
User users[100]; // 用户数组
int userCount = 0; // 用户数量
int loggedIn = 0; // 登录状态
int currentUserId = -1; // 当前用户ID
// 函数声明
void initContactList();
int getLength();
void createContact();
void addContact();
void findContact();
void updateContact();
void deleteContact();
void insertContact();
void showContacts();
void sortContactsByName();
void countGender();
void registerUser();
int login();
void saveContactsToFile();
void loadContactsFromFile();
void freeContacts();
void loadUsers();
void saveUser(User newUser);
// 初始化链表
void initContactList() {
freeContacts(); // 释放现有内存
head = NULL;
}
// 获取链表长度
int getLength() {
int count = 0;
Contact* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
// 创建联系人(用于初始化链表)
void createContact() {
initContactList();
printf("链表已初始化,现在可以添加联系人了。\n");
}
// 添加联系人
void addContact() {
if (head == NULL) {
printf("请先创建链表!\n");
return;
}
Contact* newContact = (Contact*)malloc(sizeof(Contact));
if (newContact == NULL) {
printf("内存分配失败!\n");
return;
}
// 自动分配ID
newContact->id = getLength() + 1;
printf("请输入姓名: ");
scanf("%s", newContact->name);
printf("请输入性别: ");
scanf("%s", newContact->gender);
printf("请输入电话: ");
scanf("%s", newContact->phone);
// 添加到链表尾部
if (head == NULL) {
head = newContact;
newContact->next = NULL;
} else {
Contact* temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newContact;
newContact->next = NULL;
}
printf("联系人添加成功!ID: %d\n", newContact->id);
}
// 查找联系人
void findContact() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
char name[50];
printf("请输入要查找的姓名: ");
scanf("%s", name);
Contact* current = head;
int found = 0;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
printf("ID: %d, 姓名: %s, 性别: %s, 电话: %s\n",
current->id, current->name, current->gender, current->phone);
found = 1;
}
current = current->next;
}
if (!found) {
printf("未找到该联系人!\n");
}
}
// 修改联系人信息
void updateContact() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
int id;
printf("请输入要修改的联系人ID: ");
scanf("%d", &id);
Contact* current = head;
while (current != NULL && current->id != id) {
current = current->next;
}
if (current == NULL) {
printf("未找到该联系人!\n");
return;
}
printf("当前信息 - ID: %d, 姓名: %s, 性别: %s, 电话: %s\n",
current->id, current->name, current->gender, current->phone);
char choice;
char temp[50];
printf("是否修改姓名?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新姓名: ");
scanf("%s", temp);
strcpy(current->name, temp);
}
printf("是否修改性别?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新性别: ");
scanf("%s", temp);
strcpy(current->gender, temp);
}
printf("是否修改电话?(y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
printf("请输入新电话: ");
scanf("%s", temp);
strcpy(current->phone, temp);
}
printf("联系人信息已更新!\n");
}
// 删除联系人
void deleteContact() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
char name[50];
printf("请输入要删除的联系人姓名: ");
scanf("%s", name);
Contact* current = head;
Contact* previous = NULL;
int found = 0;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
if (previous == NULL) {
head = current->next;
} else {
previous->next = current->next;
}
free(current);
printf("联系人已删除!\n");
found = 1;
break;
}
previous = current;
current = current->next;
}
if (!found) {
printf("未找到该联系人!\n");
} else {
// 重新编号
int i = 1;
current = head;
while (current != NULL) {
current->id = i++;
current = current->next;
}
}
}
// 插入联系人
void insertContact() {
if (head == NULL) {
printf("请先创建链表!\n");
return;
}
int position;
printf("请输入插入位置(在该位置之后插入): ");
scanf("%d", &position);
if (position < 0 || position > getLength()) {
printf("插入位置无效!\n");
return;
}
Contact* newContact = (Contact*)malloc(sizeof(Contact));
if (newContact == NULL) {
printf("内存分配失败!\n");
return;
}
printf("请输入姓名: ");
scanf("%s", newContact->name);
printf("请输入性别: ");
scanf("%s", newContact->gender);
printf("请输入电话: ");
scanf("%s", newContact->phone);
if (position == 0) {
// 插入到头部
newContact->id = 1;
newContact->next = head;
head = newContact;
// 重新编号
int i = 2;
Contact* current = head->next;
while (current != NULL) {
current->id = i++;
current = current->next;
}
} else {
// 插入到中间或尾部
Contact* current = head;
for (int i = 1; i < position; i++) {
current = current->next;
}
newContact->id = current->id + 1;
newContact->next = current->next;
current->next = newContact;
// 更新后续节点的编号
current = newContact->next;
while (current != NULL) {
current->id++;
current = current->next;
}
}
printf("联系人插入成功!\n");
}
// 展示所有联系人
void showContacts() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
printf("=== 通信录列表 ===\n");
printf("ID\t姓名\t性别\t电话\n");
printf("------------------------\n");
Contact* current = head;
while (current != NULL) {
printf("%d\t%s\t%s\t%s\n",
current->id, current->name, current->gender, current->phone);
current = current->next;
}
}
// 按姓名排序
void sortContactsByName() {
if (head == NULL || head->next == NULL) {
printf("通信录为空或只有一个联系人,无需排序!\n");
return;
}
int swapped;
Contact* ptr1;
Contact* lptr = NULL;
do {
swapped = 0;
ptr1 = head;
while (ptr1->next != lptr) {
if (strcmp(ptr1->name, ptr1->next->name) > 0) {
// 交换节点数据
Contact temp = *ptr1;
strcpy(temp.name, ptr1->name);
strcpy(temp.gender, ptr1->gender);
strcpy(temp.phone, ptr1->phone);
strcpy(ptr1->name, ptr1->next->name);
strcpy(ptr1->gender, ptr1->next->gender);
strcpy(ptr1->phone, ptr1->next->phone);
strcpy(ptr1->next->name, temp.name);
strcpy(ptr1->next->gender, temp.gender);
strcpy(ptr1->next->phone, temp.phone);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
} while (swapped);
printf("通信录已按姓名排序!\n");
}
// 统计性别
void countGender() {
if (head == NULL) {
printf("通信录为空!\n");
return;
}
int maleCount = 0;
int femaleCount = 0;
int otherCount = 0;
Contact* current = head;
while (current != NULL) {
if (strcmp(current->gender, "男") == 0 || strcmp(current->gender, "male") == 0) {
maleCount++;
} else if (strcmp(current->gender, "女") == 0 || strcmp(current->gender, "female") == 0) {
femaleCount++;
} else {
otherCount++;
}
current = current->next;
}
printf("性别统计结果:\n");
printf("男: %d\n", maleCount);
printf("女: %d\n", femaleCount);
printf("其他: %d\n", otherCount);
}
// 从文件加载用户数据
void loadUsers() {
FILE *file = fopen("users.dat", "r");
if (file == NULL) {
// 文件不存在则创建(首次运行),无需处理
return;
}
userCount = 0;
while (fscanf(file, "%s %s", users[userCount].username, users[userCount].password) == 2) {
userCount++;
}
fclose(file);
}
// 向文件写入用户数据(注册时调用)
void saveUser(User newUser) {
FILE *file = fopen("users.dat", "a"); // 追加模式
if (file == NULL) {
printf("保存用户失败!\n");
return;
}
fprintf(file, "%s %s\n", newUser.username, newUser.password);
fclose(file);
}
// 注册用户
void registerUser() {
if (userCount >= 100) {
printf("用户数量已达到上限!\n");
return;
}
User newUser;
printf("请输入用户名: ");
scanf("%s", newUser.username);
// 检查用户名是否已存在(基于文件加载的完整数据)
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, newUser.username) == 0) {
printf("用户名已存在!\n");
return;
}
}
printf("请输入密码: ");
scanf("%s", newUser.password);
// 先写入文件持久化,再更新内存数组
saveUser(newUser);
users[userCount++] = newUser;
printf("注册成功!\n");
}
// 用户登录
int login() {
if (userCount == 0) {
printf("没有注册用户,请先注册!\n");
return 0;
}
char username[50];
char password[50];
printf("请输入用户名: ");
scanf("%s", username);
printf("请输入密码: ");
scanf("%s", password);
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, username) == 0 &&
strcmp(users[i].password, password) == 0) {
printf("登录成功!欢迎,%s\n", username);
currentUserId = i;
loadContactsFromFile(); // 加载用户的联系人数据
return 1;
}
}
printf("用户名或密码错误!\n");
return 0;
}
// 保存联系人到文件
void saveContactsToFile() {
if (head == NULL) {
printf("通信录为空,无需保存!\n");
return;
}
char filename[100];
sprintf(filename, "%s_contacts.txt", users[currentUserId].username);
FILE* file = fopen(filename, "w");
if (file == NULL) {
printf("无法打开文件!\n");
return;
}
Contact* current = head;
while (current != NULL) {
fprintf(file, "%d %s %s %s\n",
current->id, current->name, current->gender, current->phone);
current = current->next;
}
fclose(file);
printf("联系人已保存到文件!\n");
}
// 从文件加载联系人
void loadContactsFromFile() {
initContactList(); // 清空现有链表
char filename[100];
sprintf(filename, "%s_contacts.txt", users[currentUserId].username);
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("未找到保存的联系人文件,将使用空通信录!\n");
return;
}
Contact temp;
while (fscanf(file, "%d %s %s %s",
&temp.id, temp.name, temp.gender, temp.phone) != EOF) {
Contact* newContact = (Contact*)malloc(sizeof(Contact));
*newContact = temp;
newContact->next = NULL;
if (head == NULL) {
head = newContact;
} else {
Contact* current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = newContact;
}
}
fclose(file);
printf("联系人已从文件加载!\n");
}
// 释放链表内存
void freeContacts() {
Contact* current = head;
Contact* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
head = NULL;
}
// 二级菜单(联系人管理)
void contactMenu() {
int choice;
do {
printf("\n=== 通信录管理菜单 ===\n");
printf("1. 创建模块(create)\n");
printf("2. 添加数据(add)\n");
printf("3. 查找信息(find)\n");
printf("4. 修改信息(update)\n");
printf("5. 删除信息(delete)\n");
printf("6. 插入信息(insert)\n");
printf("7. 展示信息(show)\n");
printf("8. 按姓名排序\n");
printf("9. 统计性别\n");
printf("10. 返回上一级\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
createContact();
break;
case 2:
addContact();
break;
case 3:
findContact();
break;
case 4:
updateContact();
break;
case 5:
deleteContact();
break;
case 6:
insertContact();
break;
case 7:
showContacts();
break;
case 8:
sortContactsByName();
break;
case 9:
countGender();
break;
case 10:
saveContactsToFile(); // 返回前保存数据
printf("返回主菜单...\n");
break;
default:
printf("无效选择,请重新输入!\n");
}
} while (choice != 10);
}
// 一级菜单(主菜单)
void mainMenu() {
int choice;
do {
printf("\n=== 通信录系统主菜单 ===\n");
printf("1. 注册模块\n");
printf("2. 登录模块\n");
printf("3. 退出系统\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
registerUser();
break;
case 2:
loggedIn = login();
if (loggedIn) {
contactMenu(); // 登录成功后进入联系人管理菜单
}
break;
case 3:
printf("感谢使用通信录系统,再见!\n");
break;
default:
printf("无效选择,请重新输入!\n");
}
} while (choice != 3);
}
int main() {
// 程序启动时加载用户数据
loadUsers();
mainMenu();
return 0;
}
//下方是更新说明
/*
在之前的代码中,注册的用户信息是存储在users数组中,且程序运行结束后数组数据不会持久化保存 ,每次重新运行程序,之前注册的用户数据会丢失,无法实现 “后续注册的用户用用户名和密码登录”(除非在同一次程序运行中先注册再登录)。若要真正实现持久化的用户注册、登录功能,需结合文件存储或数据库,以下是基于文件存储的改进思路与代码调整:
一、核心思路
用户数据持久化:
将注册的用户信息(用户名、密码)写入文件保存,程序启动时从文件加载用户数据到users数组,保证多次运行程序时,注册的用户信息不丢失。
文件读写逻辑:
程序启动:读取用户数据文件,初始化users数组和userCount。
用户注册:新增用户信息时,先写入文件,再更新users数组。
程序退出:(可选)可再次写入文件确保最新,但一般注册时实时写入更简单。
二、代码调整(关键部分)
1. 新增文件读写函数
c
运行
// 从文件加载用户数据
void loadUsers() {
FILE *file = fopen("users.dat", "r");
if (file == NULL) {
// 文件不存在则创建(首次运行),无需处理
return;
}
userCount = 0;
while (fscanf(file, "%s %s", users[userCount].username, users[userCount].password) == 2) {
userCount++;
}
fclose(file);
}
// 向文件写入用户数据(注册时调用)
void saveUser(User newUser) {
FILE *file = fopen("users.dat", "a"); // 追加模式
if (file == NULL) {
printf("保存用户失败!\n");
return;
}
fprintf(file, "%s %s\n", newUser.username, newUser.password);
fclose(file);
}
2. 修改registerUser函数
c
运行
void registerUser() {
if (userCount >= 100) {
printf("用户数量已达到上限!\n");
return;
}
User newUser;
printf("请输入用户名: ");
scanf("%s", newUser.username);
// 检查用户名是否已存在(基于文件加载的完整数据)
for (int i = 0; i < userCount; i++) {
if (strcmp(users[i].username, newUser.username) == 0) {
printf("用户名已存在!\n");
return;
}
}
printf("请输入密码: ");
scanf("%s", newUser.password);
// 先写入文件持久化,再更新内存数组
saveUser(newUser);
users[userCount++] = newUser;
printf("注册成功!\n");
}
3. 在main函数初始化时加载用户数据
c
运行
int main() {
// 程序启动时加载用户数据
loadUsers();
mainMenu();
return 0;
}
三、效果说明
注册用户:新用户信息会写入users.dat文件,同时更新内存中的users数组,下次程序启动时,loadUsers会读取文件内容,恢复用户数据。
登录验证:由于users数组包含了历史注册的用户(从文件加载),登录时能正常校验用户名和密码,实现 “后续注册的用户也能用账号密码登录” 的需求。
若需要更完善的持久化(如联系人数据也持久化、防文件损坏等),可进一步扩展文件读写逻辑(比如用二进制存储、添加校验等),但上述调整已能解决跨程序运行的用户注册、登录核心问题。
*/