c语言--链表应用:通信录管理

项目:基于链表的通信录管理
意义:对于一个通信录来说,要管理联系人的信息,包括编号,姓名,性别,电话。
—级菜单内容
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数组包含了历史注册的用户(从文件加载),登录时能正常校验用户名和密码,实现 “后续注册的用户也能用账号密码登录” 的需求。

若需要更完善的持久化(如联系人数据也持久化、防文件损坏等),可进一步扩展文件读写逻辑(比如用二进制存储、添加校验等),但上述调整已能解决跨程序运行的用户注册、登录核心问题。

*/

你可能感兴趣的:(c语言,链表,开发语言)