C语言实现简易文件管理系统,功能不多但是值得学习

该博客展示了用C语言实现的文件管理系统代码。定义了用户、文件和文件夹结构体,实现了初始化、添加文件和文件夹、打印目录、打开文件和文件夹等功能,还包含开始界面、主菜单和选择菜单等交互设计,最后给出了运行效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#define MAX_NameLength 20//文件名最长长度
#define MAX_ContentLength 200//文件内容最长长度
#define MAX_RouteLength 20//文件路径个数
#define STR "D"//一级目录名称
#define MAX_USERNAME_LEN 10//用户名长度
#define MAX_PASSWORD_LEN 10//用户密码长度
#define MAX_USERS_NUM 16//最多用户数量

typedef struct User {
    char username[MAX_USERNAME_LEN + 1];//用户名
    char password[MAX_PASSWORD_LEN + 1];//用户密码
}User;

typedef struct FileNode//文件结构体
{
    char fileName[MAX_NameLength];//文件名
    struct FileNode* next;//同级目录的下一个文件
    char content[MAX_ContentLength];//文件内容
}FileNode;

typedef struct FolderNode//文件夹结构体
{
    char folderName[MAX_NameLength];//文件夹名
    struct FolderNode* next;//同级目录的下一个文件夹
    struct FolderNode* nextFolder;//下一级目录的文件夹
    struct FolderNode* previous;//前一个文件夹结构体
    struct FileNode* nextFile;//下一级目录的文件
    struct FileNode* SameLevelFileHead;//同级文件头结点,只有头结点才有
    bool is_Head;//是否头结点
}FolderNode;

void initialFirstHead(FileNode** FirstFileHead, FolderNode** FirstFolderHead);//初始化一级目录头结点
void initial(FileNode** file, FolderNode** folder, FolderNode* head);//初始化文件夹链表的头结点、文件链表头结点
void AddFolder(FolderNode* head); //同级增加文件夹
void AddFile(FileNode* head);//同级增加文件
void PrintDirectory(FolderNode* folderHead, FileNode* fileHead);//打印文件目录
void OpenFile(FileNode* fileHead);//打印文件
void OpenFolder(FileNode** fileHead, FolderNode** folderHead);//打开文件夹
bool StartInterface();//开始界面
void PrintSystemName(FolderNode* folderHead);//打印当前路径
void MainMenu();//主菜单
void SelectMenu(FileNode** fileHead, FolderNode** folderHead);//选择菜单

void ClearScreen()//清屏
{
    system("cls"); //for Windows
    //system("clear"); //for Linux
}

void FreeBuffer() //吸收输入选项的回车
{
    while (getchar() != '\n') {//抵消输入选项时的回车
        continue;
    }
}

void AnyContinue() //按任意键继续
{
    printf("按任意键继续...\n");
    getchar();
}

void initialFirstHead(FileNode** FirstFileHead, FolderNode** FirstFolderHead)//初始化一级目录头结点
{
    *FirstFileHead = (FileNode*)malloc(sizeof(FileNode));
    (*FirstFileHead)->next = NULL;
    *FirstFolderHead = (FolderNode*)malloc(sizeof(FolderNode));
    (*FirstFolderHead)->next = NULL;
    (*FirstFolderHead)->nextFile = NULL;
    (*FirstFolderHead)->nextFolder = NULL;
    (*FirstFolderHead)->previous = NULL;
    (*FirstFolderHead)->is_Head = true;
    (*FirstFolderHead)->SameLevelFileHead = *FirstFileHead;
    strcpy((*FirstFolderHead)->folderName, STR);
}

void initial(FileNode** file, FolderNode** folder, FolderNode* head)//初始化文件夹链表的头结点、文件链表头结点
{
    *file = (FileNode*)malloc(sizeof(FileNode));
    (*file)->next = NULL;
    *folder = (FolderNode*)malloc(sizeof(FolderNode));
    (*folder)->next = NULL;
    (*folder)->nextFile = NULL;
    (*folder)->nextFolder = NULL;
    (*folder)->previous = head;
    head->nextFile = *file;
    head->nextFolder = *folder;
    (*folder)->is_Head = true;
    (*folder)->SameLevelFileHead = *file;
    strcpy((*folder)->folderName, head->folderName);
}

void AddFolder(FolderNode* head) //同级增加文件夹
{
    FolderNode* r = head;
    while (r->next != NULL) {
        r = r->next;
    }
    FolderNode* node = (FolderNode*)malloc(sizeof(FolderNode));
    node->next = NULL;
    node->nextFile = NULL;
    node->nextFolder = NULL;
    node->is_Head = false;
    node->previous = r;
    node->SameLevelFileHead = NULL;
    FreeBuffer();
    while (1) {// 输入并验证文件夹名
        printf("请输入文件夹名,限%d字符以内,按回车键结束输入:", MAX_NameLength);
        fgets(node->folderName, MAX_NameLength + 1, stdin);
        int len = strlen(node->folderName);
        if (node->folderName[len - 1] == '\n') {
            node->folderName[len - 1] = '\0';
        }
        if (strlen(node->folderName) == 0) {// 检查文件夹名是否符合规范
            printf("文件夹名不能为空,请重新输入!\n");
        }
        else if (strlen(node->folderName) > MAX_NameLength) {
            printf("文件夹名长度不能超过%d个字符,请重新输入!\n", MAX_NameLength);
        }
        else if (node->folderName[0] == ' ') {
            printf("文件夹名不能以空格开头,请重新输入!\n");
        }
        else {
            FolderNode* folder = head->next;
            while (folder) {// 检查文件夹名是否重复
                if (strcmp(node->folderName, folder->folderName) == 0) {
                    printf("已存在同名文件夹,请重新输入!\n");
                    break;
                }
                folder = folder->next;
            }
            if (!folder) {
                break;
            }
        }
    }
    printf("文件夹创建成功!\n");
    AnyContinue();
    r->next = node;
}

void AddFile(FileNode* head)//同级增加文件
{
    FileNode* r = head;
    while (r->next != NULL) {
        r = r->next;
    }
    FileNode* node = (FileNode*)malloc(sizeof(FileNode));
    node->next = NULL;
    FreeBuffer();
    while (1) {// 输入并验证文件名
        printf("请输入文件名,限%d字符以内,按回车键结束输入:", MAX_NameLength);
        fgets(node->fileName, MAX_NameLength + 1, stdin);
        int len = strlen(node->fileName);
        if (node->fileName[len - 1] == '\n') {
            node->fileName[len - 1] = '\0';
        }
        if (strlen(node->fileName) == 0) {// 检查文件名是否符合规范
            printf("文件名不能为空,请重新输入!\n");
        }
        else if (strlen(node->fileName) > MAX_NameLength) {
            printf("文件名长度不能超过%d个字符,请重新输入!\n", MAX_NameLength);
        }
        else if (node->fileName[0] == ' ') {
            printf("文件名不能以空格开头,请重新输入!\n");
        }
        else {
            FileNode* file = head->next;
            while (file) {// 检查文件名是否重复
                if (strcmp(node->fileName, file->fileName) == 0) {
                    printf("已存在同名文件,请重新输入!\n");
                    break;
                }
                file = file->next;
            }
            if (!file) {
                break;
            }
        }
    }
    while (1) {// 输入并验证文件内容
        printf("请输入文件内容,限%d字符以内,按回车键结束输入:\n", MAX_ContentLength);
        fgets(node->content, MAX_ContentLength + 1, stdin);
        int len = strlen(node->content);
        if (node->content[len - 1] == '\n') {
            node->content[len - 1] = '\0';
        }
        // 检查文件内容是否符合规范
        if (strlen(node->content) == 0) {
            printf("文件内容不能为空,请重新输入!\n");
        }
        else if (strlen(node->content) > MAX_ContentLength) {
            printf("文件内容长度不能超过%d个字符,请重新输入!\n", MAX_ContentLength);
        }
        else {
            break;
        }
    }
    r->next = node;// 将新文件插入文件链表末尾
    printf("文件创建成功!\n");
    AnyContinue();
}


void PrintDirectory(FolderNode* folderHead, FileNode* fileHead)//打印文件目录
{
    FolderNode* folder = folderHead;
    FileNode* file = fileHead;
    if (folder->next == NULL && file->next == NULL) {
        printf("\n当前目录为空,可新建文件或文件夹!\n\n");
    }
    else {
        int j = 1;
        printf("---文件名--------------------类型---------\n");
        while (folder->next != NULL) {
            printf("%d. %-25s 文件夹\n", j, folder->next->folderName);
            folder = folder->next;
            j++;
        }
        while (file->next != NULL) {
            printf("%d. %-25s 文件\n", j, file->next->fileName);
            file = file->next;
            j++;
        }
        j = 1;
    }
}

void OpenFile(FileNode* fileHead)//打印文件
{
    FreeBuffer();
    char temp[MAX_NameLength + 1];
    // 输入并验证文件名
    while (1) {
        printf("请输入要打开的文件名,按回车键结束输入:", MAX_NameLength);
        fgets(temp, MAX_NameLength + 1, stdin);
        int len = strlen(temp);
        if (temp[len - 1] == '\n') {
            temp[len - 1] = '\0';
        }
        // 检查文件名是否符合规范
        if (strlen(temp) == 0) {
            printf("文件名不能为空,请重新输入!\n");
        }
        else if (strlen(temp) > MAX_NameLength) {
            printf("文件名长度不能超过%d个字符,请重新输入!\n", MAX_NameLength);
        }
        else if (temp[0] == ' ') {
            printf("文件名不能以空格开头,请重新输入!\n");
        }
        else {
            FileNode* file = fileHead->next;
            // 检查文件名是否重复
            while (file) {
                if (strcmp(temp, file->fileName) == 0) {
                    ClearScreen();
                    printf("-------------------------------------------------\n");
                    printf("---------------------文件内容--------------------\n");
                    printf("-------------------------------------------------\n\n");
                    printf("%s\n", file->content);
                    break;
                }
                file = file->next;
            }
            if (!file) {
                printf("文件不存在!\n");
            }
            AnyContinue();
            break;
        }
    }
}

void OpenFolder(FileNode** fileHead, FolderNode** folderHead)//打开文件夹
{
    FreeBuffer();
    char temp[MAX_NameLength + 1];
    // 输入并验证文件夹名
    while (1) {
        printf("请输入要打开的文件夹名,按回车键结束输入:", MAX_NameLength);
        fgets(temp, MAX_NameLength + 1, stdin);
        int len = strlen(temp);
        if (temp[len - 1] == '\n') {
            temp[len - 1] = '\0';
        }

        // 检查文件名是否符合规范
        if (strlen(temp) == 0) {
            printf("文件名不能为空,请重新输入!\n");
        }
        else if (strlen(temp) > MAX_NameLength) {
            printf("文件名长度不能超过%d个字符,请重新输入!\n", MAX_NameLength);
        }
        else if (temp[0] == ' ') {
            printf("文件名不能以空格开头,请重新输入!\n");
        }
        else {
            FolderNode* folder = (*folderHead)->next;
            // 检查文件名是否重复
            while (folder) {
                if (strcmp(temp, folder->folderName) == 0) {
                    /*
                    * 全靠这几行代码,精华中的精华
                    * 通过修改指针实现
                    */
                    if (folder->nextFolder == NULL) {
                        initial(&folder->nextFile, &folder->nextFolder, folder);
                    }
                    *fileHead = folder->nextFile;
                    *folderHead = folder->nextFolder;
                    break;
                }
                folder = folder->next;
            }
            if (!folder) {
                printf("文件夹不存在!\n");
            }
            AnyContinue();
            break;
        }
    }
}

void DeleteFile(FileNode* head)//删除文件
{
    char node[MAX_NameLength + 1];
    FreeBuffer();
    // 输入并验证文件名
    while (1) {
        printf("请输入要删除的文件名,按回车键结束输入:", MAX_NameLength);
        fgets(node, MAX_NameLength + 1, stdin);
        int len = strlen(node);
        if (node[len - 1] == '\n') {
            node[len - 1] = '\0';
        }
        // 检查文件名是否符合规范
        if (strlen(node) == 0) {
            printf("文件名不能为空,请重新输入!\n");
        }
        else if (strlen(node) > MAX_NameLength) {
            printf("文件名长度不能超过%d个字符,请重新输入!\n", MAX_NameLength);
        }
        else if (node[0] == ' ') {
            printf("文件名不能以空格开头,请重新输入!\n");
        }
        else {
            FileNode* file = head->next;
            FileNode* r = head;
            // 检查文件名是否重复
            while (file) {
                if (strcmp(node, file->fileName) == 0) {
                    r->next = file->next;
                    free(file);
                    break;
                }
                file = file->next;
                r = r->next;
            }
            if (!file) {
                printf("文件不存在!\n");
            }
            AnyContinue();
            break;
        }
    }
}

void DeleteFolder(FolderNode* head)//删除文件夹
{
    char node[MAX_NameLength + 1];
    FreeBuffer();
    // 输入并验证文件夹名
    while (1) {
        printf("请输入要删除的文件夹名,按回车键结束输入:", MAX_NameLength);
        fgets(node, MAX_NameLength + 1, stdin);
        int len = strlen(node);
        if (node[len - 1] == '\n') {
            node[len - 1] = '\0';
        }
        // 检查文件名是否符合规范
        if (strlen(node) == 0) {
            printf("文件夹名不能为空,请重新输入!\n");
        }
        else if (strlen(node) > MAX_NameLength) {
            printf("文件夹名长度不能超过%d个字符,请重新输入!\n", MAX_NameLength);
        }
        else if (node[0] == ' ') {
            printf("文件夹名不能以空格开头,请重新输入!\n");
        }
        else {
            FolderNode* folder = head->next;
            FolderNode* r = head;
            // 检查文件名是否重复
            while (folder) {
                if (strcmp(node, folder->folderName) == 0) {
                    r->next = folder->next;
                    free(folder);
                    break;
                }
                folder = folder->next;
                r = r->next;
            }
            if (!folder) {
                printf("文件夹不存在!\n");
            }
            AnyContinue();
            break;
        }
    }
}


bool StartInterface()//开始界面
{
    ClearScreen();
    int choice = 0;
    int flag1 = 1;
    int flag2 = 0;
    int flag3 = 0;
    int flag4 = 0;
    int user_count = 0;        // 用户数量
    User users[MAX_USERS_NUM]; // 用户数组
    // 从文件中读取用户信息
    char username[MAX_USERNAME_LEN + 20];
    char password[MAX_PASSWORD_LEN + 20];
    FILE* fp = fopen("user_info.txt", "r");
    if (fp == NULL) {//没有user_info.txt就创建一个
        fp = fopen("user_info.txt", "w");
        if (fp != NULL) {
            fclose(fp);
            fp = fopen("user_info.txt", "r");
        }
    }
    while (!feof(fp)) {
        int res = fscanf(fp, "%s %s\n", username, password);
        if (res != 2) {
            break;
        }
        strcpy(users[user_count].username, username);
        strcpy(users[user_count].password, password);
        user_count++;
    }
    fclose(fp);
    do {
        if (flag1) {
            printf("1.注册\n");
            printf("2.登录\n");
            printf("0.退出\n");
            printf("---------------------\n");
            printf("请输入您的选择:");
        }
        flag1 = 1;
        scanf("%d", &choice);
        FreeBuffer();
        switch (choice)
        {
        case 1:// 注册
            // 用户数量不能超过上限
            if (user_count >= MAX_USERS_NUM) {
                printf("用户数量已达上限!\n");
                AnyContinue();
            }
            else {
                printf("用户名限%d字符,密码限%d字符,不含空格\n", MAX_USERNAME_LEN, MAX_PASSWORD_LEN);
                while (1) {
                    flag3 = 0;
                    printf("用户名: ");
                    fgets(username, MAX_USERNAME_LEN + 20, stdin);
                    int len = strlen(username);
                    if (username[len - 1] == '\n') {
                        username[len - 1] = '\0';
                    }
                    // 检查文件名是否符合规范
                    if (strlen(username) == 0) {
                        flag3 = 1;
                        printf("用户名不能为空,请重新输入!\n");
                    }
                    else if (strlen(username) > MAX_USERNAME_LEN) {
                        flag3 = 1;
                        printf("用户名长度不能超过%d个字符,请重新输入!\n", MAX_USERNAME_LEN);
                    }
                    else{
                        for (int i = 0; i < strlen(username); i++) {
                            if (isspace(username[i])) {
                                printf("用户名中不能包含空格,请重新输入!\n");
                                flag3 = 1;
                                break;
                            }
                        }
                    }
                    if(flag3==0) {
                        int flag = 1;
                        for (int i = 0; i < user_count; i++) {// 用户名不能重复
                            if (strcmp(users[i].username, username) == 0) {
                                flag = 0;
                                printf("用户名已存在!\n");
                            }
                        }
                        if (flag == 1) {
                            while (1) {
                                flag4 = 0;
                                printf("密码: ");
                                fgets(password, MAX_PASSWORD_LEN + 20, stdin);
                                int len = strlen(password);
                                if (password[len - 1] == '\n') {
                                    password[len - 1] = '\0';
                                }
                                // 检查文件名是否符合规范
                                if (strlen(password) == 0) {
                                    flag4 = 1;
                                    printf("文件夹名不能为空,请重新输入!\n");
                                }
                                else if (strlen(password) > MAX_PASSWORD_LEN) {
                                    flag4 = 1;
                                    printf("密码长度不能超过%d个字符,请重新输入!\n", MAX_PASSWORD_LEN);
                                }
                                else {
                                    for (int i = 0; i < strlen(password); i++) {
                                        if (isspace(password[i])) {
                                            printf("密码中不能包含空格,请重新输入!\n");
                                            flag4 = 1;
                                            break;
                                        }
                                    }
                                }
                                if (flag4 == 0) {
                                    break;
                                }
                            }
                            strcpy(users[user_count].username, username);
                            strcpy(users[user_count].password, password);
                            user_count++;
                            fp = fopen("user_info.txt", "w+");
                            for (int i = 0; i < user_count; i++) {
                                fprintf(fp, "%s %s\n", users[i].username, users[i].password);
                            }
                            fclose(fp);
                            printf("注册成功!\n");
                            AnyContinue();
                            break;
                        }
                        else {
                            printf("1重新输入,0退出注册:");
                            int c = 0;
                            while (1) {
                                scanf("%d", &c);
                                FreeBuffer();
                                if (c == 0 || c == 1) {
                                    break;
                                }
                                else {
                                    printf("无效的选项,请重新输入:");
                                }
                            }
                            if (c == 0) {
                                break;
                            }
                        }
                    }
                }
            }
            ClearScreen();
            break;
        case 2:    // 登录
            printf("请输入用户名和密码!\n");
            while (1) {
                printf("用户名: ");
                scanf("%s", username);
                printf("密码: ");
                scanf("%s", password);
                int found = 0;
                for (int i = 0; i < user_count; i++) {// 校验用户名和密码
                    if (strcmp(users[i].username, username) == 0 && strcmp(users[i].password, password) == 0) {
                        printf("登录成功!\n");
                        flag2 = 1;
                        FreeBuffer();
                        AnyContinue();
                        ClearScreen();
                        found = 1;
                        break;
                    }
                }
                if (!found) {
                    printf("用户名或密码错误!\n");
                    printf("1重新输入,0退出登录:");
                    int b = 0;
                    while (1) {
                        scanf("%d", &b);
                        if (b == 0 || b == 1) {
                            break;
                        }
                        else {
                            printf("无效的选项,请重新输入:");
                        }
                    }
                    if (b == 0) {
                        ClearScreen();
                        break;
                    }
                }
                else {
                    break;
                }
            }
            break;
        case 0:
            ClearScreen();
            printf("感谢您的使用!");
            break;
        default:
            printf("无效的选项,请重新输入:");
            flag1 = 0;
            break;
        }
    } while (choice != 0 && flag2 != 1);
    if (choice == 0) {
        return false;
    }else{
        return true;
    }
}

void PrintSystemName(FolderNode* folderHead)//打印当前路径
{
    printf("-------------------文件管理系统------------------\n");
    printf("-------------------------------------------------\n");
    printf("--当前路径:");

    FolderNode* folder = folderHead;
    char files[MAX_RouteLength][MAX_NameLength];/* 定义文件名二维数组,每行存储一个文件名 */
    int num_files = 0;
    while (1) {/* 遍历文件名数组,先进后出 */
        if (folder->previous == NULL) {
            strcpy(files[num_files], folder->folderName);
            num_files++;
            break;
        }
        if (folder->is_Head) {
            strcpy(files[num_files], folder->folderName);
            num_files++;
        }
        folder = folder->previous;
    }

    for (int i = num_files - 1; i >= 0; i--)
    {
        if (i == num_files - 1) {
            printf("%s:\\\\", files[i]);
        }
        else {
            printf("%s\\\\", files[i]);
        }
    }
    printf("\n---------------------------------------------------------\n");
}

void GoBack(FileNode** fileHead, FolderNode** folderHead)//返回上一级
{
    FreeBuffer();
    FolderNode* folder = *folderHead;
    if (folder->previous == NULL) {
        printf("已经为第一级目录!\n");
    }
    else {
        FolderNode* prevFolder = folder->previous;// 向前逐个找文件夹结构体
        while (1) {
            if (prevFolder->is_Head == true) {
                break;
            }
            prevFolder = prevFolder->previous;
        }// 此时 prevFolder 即为同级前一个文件夹的头结点
        *folderHead = prevFolder;
        *fileHead = prevFolder->SameLevelFileHead;
    }
    AnyContinue();
}


void MainMenu()//主菜单
{
    printf("-------------------------------------\n");
    printf("---1.新建文件------------\n");
    printf("---2.新建文件夹----------\n");
    printf("---3.打开文件------------\n");
    printf("---4.打开文件夹----------\n");
    printf("---5.删除文件------------\n");
    printf("---6.删除文件夹----------\n");
    printf("---7.返回上一级----------\n");
    printf("---8.用户退出------------\n");
    printf("---0.退出系统------------\n");
    printf("-------------------------------------\n");
}

void SelectMenu(FileNode** fileHead, FolderNode** folderHead)//选择菜单
{
    int flag2 = 0;
    if (StartInterface()) {
        int choice = 0;//选择
        int flag = 1;//无效的选项不需要再打印菜单
        do {
            if (flag) {
                PrintSystemName(*folderHead);
                PrintDirectory(*folderHead, *fileHead);
                MainMenu();
                printf("请输入您的选择:");
            }
            flag = 1;
            scanf("%d", &choice);
            switch (choice)
            {
            case 1:
                AddFile(*fileHead);
                ClearScreen();
                break;
            case 2:
                AddFolder(*folderHead);
                ClearScreen();
                break;
            case 3:
                OpenFile(*fileHead);
                ClearScreen();
                break;
            case 4:
                OpenFolder(fileHead, folderHead);
                ClearScreen();
                break;
            case 5:
                DeleteFile(*fileHead);
                ClearScreen();
                break;
            case 6:
                DeleteFolder(*folderHead);
                ClearScreen();
                break;
            case 7:
                GoBack(fileHead, folderHead);
                ClearScreen();
                break;
            case 8:
                ClearScreen();
                printf("用户登出成功!\n");
                FreeBuffer();
                AnyContinue();
                ClearScreen();
                if (!StartInterface()) {
                    flag2 = 1;
                }
                break;
            case 0:
                ClearScreen();
                printf("感谢您的使用!");
                break;
            default:
                printf("无效的选项,请重新输入:");
                flag = 0;
                break;
            }
        } while (choice != 0&&flag2==0);
        if (flag2 == 0) {
            ClearScreen();
            printf("感谢您的使用!");
        }
    }
}

int main()
{
    FileNode* FirstFileHead;//一级文件链表头结点
    FolderNode* FirstFolderHead;//一级文件夹链表头结点
    initialFirstHead(&FirstFileHead, &FirstFolderHead);
    SelectMenu(&FirstFileHead, &FirstFolderHead);
    return 0;
}

运行效果

具体功能如运行图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值