【C语言项目】 以链表实现的管理系统(注册、登录、对表进行数据操作)

第一次编辑这么长的文章,如果对你有帮助,可以点赞收藏一下一起学习!一起进步!


目录

一、项目介绍

二、代码介绍

三、小记

四、完整代码

五、输出结果展示

1、成功将终端输入的用户姓名和密码分别存入到.txt文件中

2、登陆成功     &&    退出成功

3、创建/初始化管理表成功

4、录入人员信息成功

5、按位置插入人员信息成功,插入位置不对会报错

6、输出所有人员信息成功

7、通过姓名查找人员信息成功

8、通过姓名删除人员信息成功

9、导出所有人员信息到文件内成功

10、打印文件信息到终端上成功

11、按姓名将通讯录排序成功(实现的是升序排序)

12、获取链表长度成功

13、统计性别数量成功

14、返回上级菜单成功

15、销毁链表成功

16、退出成功


一、项目介绍

        项目:基于链表的通信录管理

意义:对于一个通信录来说,要管理联系人的信息,包括编号,姓名,性别,电话。开发其系统主要为了帮助用户提高通讯录有管理效率,节约资源,提高信息的精确度

模块:
一级菜单内容
1> 注册模块:完成用户信息的注册用于登录管理系统,将注册信息存入文件
2> 登录模块:使用输入的登录账号和密码与文件存储信息对比
3> 退出系统


二级菜单内容:
3> 创建模块create:创建链表完成对通信录的存储
4> 添加数据add:添加通信录的信息放入链表中
5> 查找信息find:可以通过姓名进行查找
6> 修改信息update:可以修改联系人信息并保存,修改联系人信息有包括了对联系人编号,姓名,性别,电话号码的分别修改,也可以同时对编号,姓名,性别,电话号码修改;
7> 删除信息delete:可根据输入的姓名进行删除
8> 插入信息insert:将给定的信息以及插入位置信息完成插入
9> 展示信息show:将通讯录的所有信息进行展示
10> 导出信息export:将通讯录信息导出到文件中
11> 按照姓名将通讯录排序
12> 返回上一级
辅助功能:
13> 初始化链表init:将链表进行初始化
14> 获取链表长度getLength:
15> 统计性别;


二、代码介绍

  1. 采用分文件编译,link_list.h,link_list.c,main.c
  2. 在堆区申请了空间用于存放链表
  3. link_list.h中定义了两个结构体,一个是管理结构体,一个是人员信息结构体,同时包含了函数的声明
  4. link_list.c中完成了函数功能的封装
  5. mian.c主函数里,使用了两个while循环,进行菜单的循环展示,如果登录成功,则会进入下一级菜单,使用switch,进行功能的实现
  6. 在注册的时候,只保证了一个用户的创建,多个用户的创建还没实现

三、小记

        项目不难,有耐心就能完成,其中也是遇到了很多的问题。例如在对链表进行操作的时候,没有对输入的内容进行逻辑判断是否合理,导致指针指向的位置发生偏移出现段错误。在进行赋值语句的时候,尝尝忘记数组不能作为常量直接进行赋值,如果需要赋值,需要借助strcmp等函数进行操作,否则会发生报错。


四、完整代码

//link_list.h
#ifndef LINK_LIST_H
#define LINK_LIST_H
#include <myhead.h>

#define MAX 100

//人员信息
typedef struct Person
{
    char id[20];
    char name[20];
    char gender[20];
    char telephone[20];
}Person,*PersonPtr;

//人e员管理
typedef struct Manage
{
    Person person;
    int len;
    struct Manage *next;
}Manage,*ManagePtr;


//创建登录视图
void create_log_view();

//注册
int register_user();

//登录
int log_user();

//判空
int link_empty(ManagePtr person_ptr);

//创建管理视图
void create_view();

//创建班级链表
ManagePtr link_person_create();

//申请人员信息结点
ManagePtr link_apply_node(Person person);

//头删
int link_delete_head(ManagePtr person_ptr);

//头插插入人员信息
int link_insert_person(ManagePtr person_ptr,Person person);

//遍历人员信息
int link_printf_person(ManagePtr person_ptr);

//按位置查找人员结点
ManagePtr link_search_person_pos(ManagePtr person_ptr,int pos);

//按位置插入人员信息
int link_insert_person_pos(ManagePtr person_ptr,int pos,Person person);

//通过姓名查找人员信息
int link_search_name(ManagePtr person_ptr);

//通过人名删除信息
int link_delete_name(ManagePtr person_ptr);

//导出所有人员信息到文件内
void link_export_person(ManagePtr person_ptr);

//打印文件信息
void file_show();

//按照姓名将通讯录排序
void link_person_sort_name(ManagePtr person_ptr);

//统计人员总人数(链表长度)
int link_len(ManagePtr person_ptr);

//统计性别
void link_gender_statistics(ManagePtr person_ptr);

//销毁管理表
void link_destroy(ManagePtr person_ptr);

#endif
//link_list.c
#include "link_list.h"

// 创建登录视图
void create_log_view()
{
    printf("\t\t======1.注册\n");
    printf("\t\t======2.登录\n");
    printf("\t\t======3.退出\n");
}

// 注册
int register_user()
{
    // 存用户和密码
    char user_name[30] = {0};
    char password[30] = {0};

    // 判断是否成功打开文件
    FILE *fp_user = NULL, *fp_password = NULL;
    if ((fp_user = fopen("./user.txt", "w+")) == NULL || (fp_password = fopen("./password.txt", "w+")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    // 从终端输入用户姓名和密码
    printf("请输入用户姓名:");
    fgets(user_name, sizeof(user_name), stdin);

    printf("请输入密码:");
    fgets(password, sizeof(password), stdin);

    // 使用fputs将用户名存入user_name.txt
    fputs(user_name, fp_user);
    user_name[strlen(user_name) - 1] = '\0'; // 将回车换成 '\0'

    // 使用fputs将密码写入password.txt
    fputs(password, fp_password);
    password[strlen(user_name) - 1] = '\0';

    // 关闭文件
    fclose(fp_user);
    fclose(fp_password);

    printf("注册成功\n");
    return 0;
}

// 登录
int log_user()
{
    char buf_name[30] = {0};
    char buf_password[30] = {0};
    char input_name[30] = {0};
    char input_password[30] = {0};

    // 打开文件
    FILE *fp_user = NULL, *fp_password = NULL;
    if ((fp_user = fopen("./user.txt", "r")) == NULL || (fp_password = fopen("./password.txt", "r")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    // 从文件里获取账号和密码
    while (1)
    {
        // 如果是NULL,用户姓名读取结束
        if ((fgets(buf_name, sizeof(buf_name), fp_user)) == NULL)
        {
            break;
        }

        // 如果是NULL,密码读取结束
        if ((fgets(buf_password, sizeof(buf_password), fp_password)) == NULL)
        {
            break;
        }
    }
    buf_name[strlen(buf_name) - 1] = '\0'; // 将回车换成 '\0
    buf_password[strlen(buf_password) - 1] = '\0';

    // 输入用户名和密码
    printf("请输入用户名:");
    scanf("%s", input_name);
    getchar();

    printf("请输入密码:");
    scanf("%s", input_password);
    getchar();

    // 判断是否相等
    if (strcmp(buf_name, input_name) == 0 && strcmp(buf_password, input_password) == 0)
    {
        printf("登录成功\n");
        return 0;
    }
    printf("用户名或密码错误,请重新输入\n");
    return -1;
}

// 判空
int link_empty(ManagePtr person_ptr)
{
    return person_ptr->next == NULL; // 如果头指针为空,则表示该链表为空,返回1;
}

// 创建管理视图
void create_view()
{
    printf("\t\t======1.创建/初始化管理表\n");
    printf("\t\t======2.录入人员信息\n");
    printf("\t\t======3.按位置插入人员信息\n");
    printf("\t\t======4.输出所有人员信息\n");
    printf("\t\t======5.通过姓名查找人员信息\n");
    printf("\t\t======6.通过姓名删除人员信息\n");
    printf("\t\t======7.导出所有人员信息到文件内\n");
    printf("\t\t======8.打印文件信息\n");
    printf("\t\t======9.按照姓名将通讯录排序\n");
    printf("\t\t======10.获取链表长度\n");
    printf("\t\t======11.统计性别\n");
    printf("\t\t======12.返回上级菜单\n");
    printf("\t\t======13.销毁管理表\n");
    printf("\t\t======0.退出\n");
}

// 创建人员管理链表
ManagePtr link_person_create()
{
    ManagePtr person_ptr = (ManagePtr)malloc(sizeof(Manage)); // 在堆区申请空间

    // 判断逻辑
    if (person_ptr == NULL)
    {
        printf("人员管理表创建失败\n");
        return NULL;
    }

    // 链表初始化
    person_ptr->len = 0;
    person_ptr->next = NULL;
    printf("人员管理表创建成功\n");
    putchar(10);
    return person_ptr;
}

// 申请人员信息结点
ManagePtr link_apply_node(Person person)
{
    ManagePtr p = (ManagePtr)malloc(sizeof(Manage));

    // 判断逻辑
    if (p == NULL)
    {
        printf("结点创建失败\n");
        return NULL;
    }
    p->person = person;
    p->next = NULL;
    return p;
}

// 头删
int link_delete_head(ManagePtr person_ptr)
{
    // 判断逻辑
    if (NULL == person_ptr || link_empty(person_ptr))
    {
        printf("头删失败\n");
        return -1;
    }

    ManagePtr q = person_ptr->next; // 保存要删除的节点

    // 执行头删逻辑
    person_ptr->next = q->next;
    free(q);

    person_ptr->len--;
    return 0;
}

// 头插插入人员信息
int link_insert_person(ManagePtr person_ptr, Person person)
{
    // 判断逻辑
    if (person_ptr == NULL)
    {
        printf("插入失败\n");
        return -1;
    }

    // 申请一个新的结点
    ManagePtr p = link_apply_node(person);
    p->next = person_ptr->next;
    person_ptr->next = p;
    person_ptr->len++;
    printf("插入成功\n");
    return 0;
}

// 遍历人员信息
int link_printf_person(ManagePtr person_ptr)
{
    // 判断逻辑
    if (NULL == person_ptr)
    {
        printf("遍历失败,链表不存在或已被销毁,请检查!\n");
        return -1;
    }

    ManagePtr q = person_ptr->next;

    // 循环链表
    while (q)
    {
        printf("%s\t%s\t%s\t%s\n", q->person.id, q->person.name, q->person.gender, q->person.telephone);
        q = q->next;
    }
    putchar(10);
    return 0;
}

// 按位置查找人员结点
ManagePtr link_search_person_pos(ManagePtr person_ptr, int pos)
{
    // 判断逻辑
    if (NULL == person_ptr || pos < 0 || pos > person_ptr->len)
    {
        printf("查找失败\n");
        return NULL;
    }

    // 通过位置查找结点
    ManagePtr q = person_ptr;
    for (int i = 0; i < pos; i++)
    {
        q = q->next;
    }

    // 返回结点
    return q;
}

// 按位置插入人员信息
int link_insert_person_pos(ManagePtr person_ptr, int pos, Person person)
{
    if (NULL == person_ptr || pos < 0 || pos > person_ptr->len)
    {
        printf("插入失败,您输入的位置不对,或者链表不存在,请检查!\n");
        printf("\n");
        return -1;
    }

    // 申请一个新的结点
    ManagePtr p = link_apply_node(person);

    // 查找前驱结点
    ManagePtr q = link_search_person_pos(person_ptr, pos - 1);

    p->next = q->next;
    q->next = p;
    person_ptr->len++;
    printf("插入成功\n");
    return 0;
}

// 通过姓名查找人员信息
int link_search_name(ManagePtr person_ptr)
{
    // 判断逻辑,链表是否存在
    if (NULL == person_ptr)
    {
        printf("查找失败\n");
        return -1;
    }

    // 输入人员姓名
    char search_name[30] = {0};
    printf("请输入你需要查找的人员信息的姓名:");
    scanf("%s", search_name);
    getchar();

    ManagePtr q = person_ptr->next;

    // 循环比较输入的内容与存储在链表里面的内容,是否相等
    while (q)
    {
        if (strcmp(q->person.name, search_name) == 0)
        {
            // 如果相等,就输出这个人的姓名
            printf("编号\t姓名\t性别\t电话\n");
            printf("%s\t%s\t%s\t%s\n", q->person.id, q->person.name, q->person.gender, q->person.telephone);
            printf("\n");
            return 0;
        }
        q = q->next;
    }

    // 如果q为NULL,则表示表中没有这个人,返回查找失败信息
    if (q == NULL)
    {
        printf("查无此人\n");
        printf("\n");
        return -1;
    }
}

// 通过人名删除信息
int link_delete_name(ManagePtr person_ptr)
{
    // 判断逻辑
    if (NULL == person_ptr)
    {
        printf("删除失败\n");
        return -1;
    }

    // 输入人员姓名
    char delete_name[30] = {0};
    printf("请输入你需要删除的人员信息的姓名:");
    scanf("%s", delete_name);
    getchar();

    // 查找链表中是否有该人员,如果有,则删除

    ManagePtr p = person_ptr; // 记录头指针
    ManagePtr L = p->next;
    ManagePtr temp = NULL; // 定义一个交换指针

    while (L)
    {
        // 如果查找到了,就删除该结点
        if (strcmp(L->person.name, delete_name) == 0)
        {
            temp = L; // 记录要删除的结点
            p->next = L->next;
            free(temp);
            person_ptr->len--;
            printf("删除成功\n");
            return 0;
        }

        // 循环后移节点
        p = p->next;
        L = L->next;
    }

    // 程序执行至此,表示没有找到该人员姓名
    printf("没有此人,无需删除\n");
    printf("\n");
    return -1;
}

// 导出所有人员信息到文件内
void link_export_person(ManagePtr person_ptr)
{
    char huiche[10] = {'\n'};
    char t[10] = {'\t'};

    // 判断逻辑
    if (NULL == person_ptr)
    {
        printf("导出失败\n");
        return;
    }

    FILE *fp_person = NULL;
    // 判断文件是否成功打开
    if ((fp_person = fopen("./person_information.txt", "w+")) == NULL)
    {
        perror("fopen error");
        return;
    }

    ManagePtr p = person_ptr->next; // 记录头指针

    while (p)
    {
        // 把链表里面的内容依次输入到文件中
        fputs(p->person.id, fp_person);
        fputs(t, fp_person); // 自动格式化一下
        fputs(p->person.name, fp_person);
        fputs(t, fp_person);
        fputs(p->person.gender, fp_person);
        fputs(t, fp_person);
        fputs(p->person.telephone, fp_person);
        fputs(huiche, fp_person); // 自动换行
        p = p->next;
    }

    // 关闭文件
    fclose(fp_person);

    printf("导出数据成功\n");
    return;
}

// 打印文件信息
void file_show()
{
    FILE *fp_person = NULL;
    char buf[30] = {0}; // 定义一个容器用来接收读取到的内容
    // 以只读的形式打开文件
    if ((fp_person = fopen("./person_information.txt", "r")) == NULL)
    {
        perror("fopen error"); // 输出错误信息
        return;
    }

    printf("文件中的数据如下所示:\n");

    // 从文件中获取数据
    while ((fgets(buf, sizeof(buf), fp_person)) != NULL)
    {
        printf("%s", buf);
    }

    printf("\n输出成功\n");
    return;
}

// 按照姓名将通讯录排序
void link_person_sort_name(ManagePtr person_ptr)
{
    // 判断逻辑
    if (NULL == person_ptr || link_empty(person_ptr))
    {
        printf("排序失败\n");
        return;
    }

    ManagePtr prev = person_ptr;
    // 记录数据
    ManagePtr p = person_ptr->next;

    Person temp;   //定义一个结构体,用来存储交换的数据

    // 执行排序逻辑
    for (int i = 1; i < person_ptr->len; i++)
    {
        for (int j = 0; j < person_ptr->len - i; j++)
        {
            if (strcmp(p->person.name, p->next->person.name) > 0)
            {
                // 交换三步曲
                temp = p->person;
                p->person = p->next->person;
                p->next->person = temp;
            }
            p = p->next;
        }
        p = prev->next;
    }

    printf("升序排序成功\n");
    return;
}


//统计人员总人数(链表长度)
int link_len(ManagePtr person_ptr)
{
    return person_ptr->len;
}


//统计性别
void link_gender_statistics(ManagePtr person_ptr)
{
    int man = 0;     //男性计数器
    int woman = 0;   //女性计数器

    //判断逻辑
    if(NULL == person_ptr || link_empty(person_ptr))
    {
        printf("统计失败\n");
        return ;
    }

    ManagePtr p = person_ptr->next;

    while(p)
    {
        if(strcmp(p->person.gender,"男") == 0)
        {
            man++;
        }
        else if(strcmp(p->person.gender,"女") == 0)
        {
            woman++;
        }
        p = p->next;
    }
    
    printf("统计完毕\n");
    printf("男生一共有%d个,女生一共有%d个\n",man,woman);
    printf("\n");
    return ;
}

// 销毁管理表
void link_destroy(ManagePtr person_ptr)
{
    // 判断逻辑
    if (NULL == person_ptr)
    {
        printf("无需销毁\n");
        return;
    }

    // 执行头删
    while (!link_empty(person_ptr))
    {
        link_delete_head(person_ptr);
    }

    // 释放结点
    free(person_ptr);
    person_ptr = NULL;

    printf("释放链表成功\n");
    return;
}
//main.c
#include "link_list.h"
int main(int argc, char const *argv[])
{
    int n = 0, pos = 0, logsuccess = 1;
    int retval;
    int len = 0;
    
    ManagePtr person_ptr;
    Person person;

    // 登录视图
    while (logsuccess)
    {
        START:
        create_log_view();
        printf("请输入您的需求:");
        scanf("%d", &n);
        getchar();
        switch (n)
        {
        case 1:
            retval = register_user();
            break;

        case 2:
            retval = log_user();
            logsuccess = retval;
            break;

        case 3:
            goto END;
            break;

        default:
            break;
        }
    }

    // 管理试图
    while (1)
    {
        create_view();
        printf("请输入您需要实现的功能:");
        scanf("%d", &n);
        getchar();
        switch (n)
        {
        case 1:
            person_ptr = link_person_create();
            break;

        case 2:
            printf("请输入你需要插入的编号:");
            scanf("%s", person.id);
            getchar();

            printf("请输入你需要插入的姓名:");
            scanf("%s", person.name);
            getchar();

            printf("请输入你需要插入的性别:");
            scanf("%s", person.gender);
            getchar();

            printf("请输入你需要插入的电话:");
            scanf("%s", person.telephone);
            getchar();

            link_insert_person(person_ptr, person);
            break;

        case 3:
            printf("请输入你需要插入的位置:");
            scanf("%d",&pos);
            getchar();

            printf("请输入你需要插入的编号:");
            scanf("%s", person.id);
            getchar();

            printf("请输入你需要插入的姓名:");
            scanf("%s", person.name);
            getchar();

            printf("请输入你需要插入的性别:");
            scanf("%s", person.gender);
            getchar();

            printf("请输入你需要插入的电话:");
            scanf("%s", person.telephone);
            getchar();

            link_insert_person_pos(person_ptr, pos, person);
            break;

        case 4:
            printf("编号\t姓名\t性别\t电话\n");
            link_printf_person(person_ptr);
            break;

        case 5:
            link_search_name(person_ptr);
            break;

        case 6:
            link_delete_name(person_ptr);
            break;  

        case 7:
            link_export_person(person_ptr);
            break; 

        case 8:
            file_show();
            break;     

        case 9:
            link_person_sort_name(person_ptr);
            break;

        case 10:
            len = link_len(person_ptr);
            printf("表中一共有%d个人\n",len);
            printf("\n");
            break;

        case 11:
            link_gender_statistics(person_ptr);
            break;

        case 12:
            printf("已返回上级菜单\n");
            printf("\n");
            goto START;
            break;

        case 13:
            link_destroy(person_ptr);
            person_ptr = NULL;
            break;

        case 0:
            goto END;
            break;

        default:
            break;
        }
    }
END:
    printf("退出成功\n");
    return 0;
}

五、输出结果展示

1、成功将终端输入的用户姓名和密码分别存入到.txt文件中


2、登陆成功     &&    退出成功

如果用户名密码对不上,提示重新输入

直接退出


3、创建/初始化管理表成功


4、录入人员信息成功


5、按位置插入人员信息成功,插入位置不对会报错


6、输出所有人员信息成功


7、通过姓名查找人员信息成功


8、通过姓名删除人员信息成功

可以看出已经把张三从表里删除了


9、导出所有人员信息到文件内成功

成功输入进person_information.txt文件中


10、打印文件信息到终端上成功


11、按姓名将通讯录排序成功(实现的是升序排序)

可以看出已经成功根据姓名进行了升序排序


12、获取链表长度成功


13、统计性别数量成功


14、返回上级菜单成功


15、销毁链表成功


16、退出成功

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴回答你关于C语言课程设计的问题!链表是一种常用的数据结构,可以用来实现学生信息管理系统。下面是一个简单的示例代码,实现了学生信息的添加、查找和删除功能: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct student { char name[50]; int age; struct student* next; } Student; Student* createStudent(char name[], int age) { Student* newStudent = (Student*)malloc(sizeof(Student)); strcpy(newStudent->name, name); newStudent->age = age; newStudent->next = NULL; return newStudent; } void addStudent(Student** head, char name[], int age) { Student* newStudent = createStudent(name, age); if (*head == NULL) { *head = newStudent; } else { Student* temp = *head; while (temp->next != NULL) { temp = temp->next; } temp->next = newStudent; } printf("学生 %s 添加成功\n", name); } void findStudent(Student* head, char name[]) { if (head == NULL) { printf("学生信息为空\n"); return; } Student* temp = head; while (temp != NULL) { if (strcmp(temp->name, name) == 0) { printf("找到学生 %s,年龄:%d\n", name, temp->age); return; } temp = temp->next; } printf("未找到学生 %s\n", name); } void deleteStudent(Student** head, char name[]) { if (*head == NULL) { printf("学生信息为空\n"); return; } Student* temp = *head; Student* prev = NULL; while (temp != NULL) { if (strcmp(temp->name, name) == 0) { if (prev == NULL) { *head = temp->next; } else { prev->next = temp->next; } free(temp); printf("删除学生 %s 成功\n", name); return; } prev = temp; temp = temp->next; } printf("未找到学生 %s\n", name); } void printStudents(Student* head) { if (head == NULL) { printf("学生信息为空\n"); return; } printf("学生信息列表:\n"); Student* temp = head; while (temp != NULL) { printf("姓名:%s,年龄:%d\n", temp->name, temp->age); temp = temp->next; } } void destroyStudents(Student** head) { if (*head == NULL) { return; } Student* current = *head; Student* next; while (current != NULL) { next = current->next; free(current); current = next; } *head = NULL; printf("释放学生信息成功\n"); } int main() { Student* head = NULL; addStudent(&head, "张三", 20); addStudent(&head, "李四", 21); addStudent(&head, "王五", 22); printStudents(head); findStudent(head, "李四"); findStudent(head, "赵六"); deleteStudent(&head, "李四"); printStudents(head); destroyStudents(&head); return 0; } ``` 这个例子中,我们定义了一个`Student`结构体,包含学生的姓名和年龄,并且有一个指向下一个学生的指针。我们可以使用`createStudent`函数创建一个新的学生节点,然后用`addStudent`函数将学生添加到链表中。`findStudent`函数用于查找指定姓名的学生,`deleteStudent`函数用于删除指定姓名的学生,`printStudents`函数用于打印所有学生信息,`destroyStudents`函数用于释放链表内存。 希望这个示例能够帮助你开始实现学生信息管理系统!如果你有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值