C语言文件管理系统

在学完C语言后,自己闲的没事做的,主要就是模拟电脑的磁盘的创建文件/文件夹、删除之类的,主要写的是实现逻辑,作为大作业什么的也不错,如果有大作业程序需求,可以私信我

(*>.<*)(*>.<*)

如果使用的是Visual Studio 2022,记得在项目属性中禁用警告4996

如果能帮助您,还请点个赞,谢谢!(*>.<*)

#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//最多用户数量
/*
*本系统实现了用户注册、登录,将用户名、密码存放在文件里
* 模拟了电脑D盘的文件结构
*/
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("------欢迎使用二级文件管理模拟系统!------\n");
			printf("------------------------------------------\n");
			printf("-----------1.注册----------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("---------------------------------------------------------\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.新建文件----------2.新建文件夹--\n");
	printf("---3.打开文件----------4.打开文件夹--\n");
	printf("---5.删除文件----------6.删除文件夹--\n");
	printf("---7.返回上一级--------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;
}

运行截图:

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值