第一次通过csdn到github学习的一个项目,由于时间问题,没有完全实现,对原作者的代码进行了改进
原作者博客:https://blog.csdn.net/nk_test/article/details/50389128
github地址:
https://github.com/Tachone/FileSystem
原作者的代码实现的功能:
void do_Help()
{
cout << "Login userName pwd 用户登陆" << endl;
cout << "Logout 用户登出" << endl;
cout << "Register usrName pwd 用户注册" << endl;
cout << "Passwd oldPwd newPwd 修改用户口令" << endl;
cout << "Open filename mode 打开文件" << endl;
cout << "Close filename 关闭文件" << endl;
cout << "Create filename mode 建立文件" << endl;
cout << "Delete filename 删除文件" << endl;
cout << "Write filename buffer nbytes 写文件" << endl;
cout << "Read filename buffer nbytes 读文件" << endl;
cout << "dir 列出该用户下所有文件" << endl;
cout << "Chmod filename mode 改变文件权限" << endl;
cout << "Chown filename new_owner 改变文件拥有者" << endl;
cout << "Mv srcFile desFile 改变文件名" << endl;
cout << "Copy srcFile desFile 文件拷贝" << endl;
cout << "Type filename 显示文件内容" << endl;
cout << "Exit 退出程序" << endl;
cout << "sysc 同步到磁盘 " << endl;
}
我的代码实现功能:
void Help() {
printf("欢迎使用由广大菜鸟完成的二级文件目录系统!\n");
printf("******************************************\n");
printf("Loin 用户登陆\n");
printf("Logout 用户登出\n");
printf("Exit 退出系统\n");
printf("Create xx.format mode 创建文件\n");
printf("Write xx.format 填写文件\n");
printf("Delete xx.format 删除文件\n");
printf("open xx.format 打开文件\n");
printf("Read xx.format nbytes 查看文件\n");
printf("ReadAll xx.format 查看全部\n");
printf("Close 关闭文件\n");
printf("dir 查看目录\n");
printf("Register userName userPwd 登记用户\n");
printf("******************************************\n");
}
1、代码区域:
1.1、 fileSystemStruct.h
#pragma once
#ifndef _FILESYSTEMSTRUCT_H_
#define _FILESYSTEMSTRUCT_H_
/*
以一个文本文件disk.txt模拟硬盘,设定硬盘容量分为100个物理块,每个物理块的大小512字节(为了测试方便,最后67个数据块每一个的大小为256字节),盘块之间用(‘\n’)分割。
因此一个盘块:512字节数据+1字节(‘\n’)分割符=513字节,则disk.txt 长度=51300(100×513)+1字节(文件结束符)=51301字节。
100块盘块的分布:
1#: MFD块,存放MFD信息;
2-17#: UFD块,存放UFD信息;
18-33#: UOF块,存放UOF信息;
其余物理块用于存放文件内容(1行1个磁盘)。
*/
// 主文件目录 32B 1#盘块
typedef struct mfd
{
char usrName[14];
char usrPwd[14];
int link; //该用户的UFD所在的盘号 4B
}MFD;
// 用户文件目录 46B 2-17#盘块
typedef struct ufd
{
char creator[14]; //创建用户名
char filename[14]; //文件名14B
int mode; // 文件权限0 - readonly; 1 - writeonly; 2 - read / write 3 - private
int length; //文件长度(以字节数计算)
int addr; //该文件的第1个文件块对应的物理块号
}UFD;
// 用户已打开表:32B 18-33# 盘块
typedef struct uof
{
char creator[14]; //创建用户名
char filename[14];
int mode; //文件属性
int state; //0建立,1打开
int read_point; //读写指针
int write_point;
}UOF;
// 数据块 : 256B 34-100# 盘块
typedef struct cluster
{
int nowNum; // 物理块号
int nextcluster; // 指向下一个物理块
int has_data; // 判断是否有数据
char data[256]; // 数据
}Cluster;
typedef void(*func)(char**,int);
typedef struct hand
{
const char* pname;
func handler;
}HAND_TO;
#endif
1.2、main.cpp
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<conio.h>
#include "fileSystemStruct.h"
#define MAX_USER_NUM 10
#define MAX_FILE_NUM 10
#define MAX_CLUSTER_NUM 67
#define MAX_TRYLOGIN_TIME 3
const int COMMAND_LEN = 200; //命令行最大长度
const int COMMAND_NUM = 12; //命令条数
using namespace std;
vector<MFD>UserInfo; //所有的用户
vector <vector<UFD> > FileInfo; //所有文件信息
vector<vector<UOF> > FileState; //所用用户打开的文件
vector<Cluster> FileCluster; //磁盘块
int curID = 0; //默认第0号用户
int readingState = 0; //文件阅读
int openingState = 0; //文件打开
void Help(); //帮助
void initFileFromRom(); //从文件中读取
void outToFile(); //保存到文件
void split(char* src, const char* separator, char** dest, int* num); //以某个字符串对字符串分割成数组
void shell(); //终端
void handle(char* ); //选择函数并处理
void doLogin(char**,int); //登录
void doLogout(char**,int); //退出
void doCreate(char**,int); //创建文件
void doWrite(char**, int); //写文件
void doDelete(char**, int); //删除文件
void doOpen(char**, int); //查看文件
void doDir(char**, int); //查看目录
void doRead(char**, int); //查看部分
void doReadAll(char**, int); //查看全部
void doClose(char**, int); //关闭文件
void doRegister(char**, int); //注册用户
HAND_TO handlerlist[] =
{
{ "Login", doLogin},
{"Logout",doLogout},
{"Create",doCreate},
{"Delete",doDelete},
{"Write",doWrite},
{"open",doOpen},
{"dir",doDir},
{"Read",doRead},
{"ReadAll",doReadAll},
{"Close",doClose},
{"Register",doRegister}
};
int main() {
initFileFromRom(); //从文件中读取
Help();
shell();
outToFile();
}
void Help() {
printf("欢迎使用由广大菜鸟完成的二级文件目录系统!\n");
printf("******************************************\n");
printf("Loin 用户登陆\n");
printf("Logout 用户登出\n");
printf("Exit 退出系统\n");
printf("Create xx.format mode 创建文件\n");
printf("Write xx.format 填写文件\n");
printf("Delete xx.format 删除文件\n");
printf("open xx.format 打开文件\n");
printf("Read xx.format nbytes 查看文件\n");
printf("ReadAll xx.format 查看全部\n");
printf("Close 关闭文件\n");
printf("dir 查看目录\n");
printf("Register userName userPwd 登记用户\n");
printf("******************************************\n");
}
void initFileFromRom() {
FILE* file;
errno_t err;
if ((err = fopen_s(&file,"disk.txt", "r")) != 0) { // 打开文件成功返回0,失败返回非0。
fopen_s(&file, "disk.txt", "w");
fclose(file);
return;
}
// 读入用户信息
int userCount; /*用户个数*/
fscanf_s(file,"%d",&userCount);
int i = 0,ret=0,j=0;
MFD userItem;
while( ( i<userCount) && (ret =fscanf_s(file, "%s %s %d",userItem.usrName,sizeof(userItem.usrName),userItem.usrPwd,sizeof(userItem.usrPwd),&userItem.link))!=-1 )
{
/* 这里获取的字符串,如果缺少长度的话,会出现运行时错误 */
i += 1;
UserInfo.push_back(userItem);
}
// 初始化文件信息
/* char creator[14];
char filename[14];
int mode;
int length;
int addr;
*/
UFD fileInput;
fileInput.addr = 0;
strcpy_s(fileInput.filename,"");
fileInput.length = 0;
fileInput.mode = 0; // 文件权限0 - readonly; 1 - writeonly; 2 - read / write
vector<UFD>singleFileInfo;
vector<UOF>singleFileState;
for (j = 0; j < userCount; j++) {
FileInfo.push_back(singleFileInfo);
FileState.push_back(singleFileState);
}
int ufd_count;
for ( j = 0; j < userCount; j++) {
fscanf_s(file, "%d", &ufd_count);
i = 0;
while( (i<ufd_count) &&
((ret = fscanf_s(file,"%s %s %d %d %d",
fileInput.creator, sizeof(fileInput.creator),
fileInput.filename,sizeof(fileInput.filename),
&fileInput.mode,
&fileInput.length, &fileInput.addr
))!= -1 ) )
{
i++;
FileInfo[j].push_back(fileInput);
}
}
/* char filename[14];
int mode;
int state; //0建立,1打开
int read_poit; //读写指针
int write_poit;
*/
UOF stateInput;
strcpy_s(stateInput.filename, "");
stateInput.mode = 0; // 文件权限0 - readonly; 1 - writeonly; 2 - read / write
stateInput.read_point = stateInput.write_point = 0;
stateInput.state = 0; //0建立,1打开
for (j = 0; j < userCount; j++) {
int uof_count;
fscanf_s(file, "%d", &uof_count);
i = 0;
while ((i < uof_count) &&
((ret = fscanf_s(file, "%s %s %d %d %d %d",
stateInput.creator, sizeof(stateInput.creator),
stateInput.filename, sizeof(stateInput.filename),
&stateInput.mode, &stateInput.state,
&stateInput.read_point, &stateInput.write_point
)) != -1))
{
i++;
FileState[j].push_back(stateInput);
}
}
/*
int Num; // 物理块号
long nextcluster; // 指向下一个物理块
int has_data; // 判断是否有数据
char data[256]; // 数据
*/
char tmpBuffer[256];
i = 0;
Cluster clusterInput;
char c;
while (i < MAX_CLUSTER_NUM) {
memset(tmpBuffer, 0, sizeof(tmpBuffer));
if ((ret = fscanf_s(file,"%d %d", &clusterInput.nextcluster, &clusterInput.has_data))!=-1 ) {
if (clusterInput.has_data == 1) {
fscanf_s(file, "%c",&c ); /* 去掉一个空格*/
fgets(tmpBuffer,256,file);
}
strcpy_s(clusterInput.data,tmpBuffer);
FileCluster.push_back(clusterInput);
}
else {//初始化
clusterInput.nextcluster = i;
if (clusterInput.nextcluster >= MAX_CLUSTER_NUM)
clusterInput.nextcluster = 0;
clusterInput.has_data = 0;
strcpy_s(clusterInput.data, tmpBuffer);
FileCluster.push_back(clusterInput);
}
i++;
}
fclose(file);
}
void outToFile() {
FILE* file;
errno_t err;
if ((err = fopen_s(&file, "disk.txt", "w")) != 0) { // 打开文件成功返回0,失败返回非0。
printf("打开文件异常\n");
return;
}
fprintf(file,"%d ",UserInfo.size());
for (int i = 0; i < UserInfo.size(); i++)
fprintf(file, "%s %s %d%c", UserInfo[i].usrName, UserInfo[i].usrPwd, UserInfo[i].link, ' ');
fprintf(file, "\n");
/*
char filename[14];
int mode;
int length;
int addr;
*/
for (int i = 0; i < FileInfo.size(); i++)
{
fprintf(file, "%d%c", FileInfo[i].size(), ' ');
for (int j = 0; j < FileInfo[i].size(); j++)
{
fprintf(file, "%s %s %d %d %d%c", FileInfo[i][j].creator, FileInfo[i][j].filename, FileInfo[i][j].mode, FileInfo[i][j].length, FileInfo[i][j].addr, ' ');
}
fprintf(file, "\n");
}
/*char filename[14];
int mode;
int state; //0建立,1打开
int read_poit; //读写指针
int write_poit;*/
for (int i = 0; i < FileState.size(); i++)
{
fprintf(file, "%d%c", FileState[i].size(), ' ');
for (int j = 0; j < FileState[i].size(); j++)
{
fprintf(file, "%s %s %d %d %d %d%c", FileState[i][j].creator,FileState[i][j].filename, FileState[i][j].mode, FileState[i][j].state, FileState[i][j].read_point, FileState[i][j].write_point, ' ');
}
fprintf(file, "\n");
}
/*int num;
int next_num;
int is_data;
char data[256];*/
for (int i = 0; i < FileCluster.size(); i++)
{
fprintf(file, "%d %d%c", FileCluster[i].nextcluster, FileCluster[i].has_data, ' ');
fputs(FileCluster[i].data, file); //和下面的一样都可以的
//fprintf(file, "%s", FileCluster[i].data);
fprintf(file, "\n");
}
fclose(file);
}
void shell() {
char commandInput[COMMAND_LEN];
while(true) {
printf("system@%s:~$ ",UserInfo[curID].usrName);
gets_s(commandInput);
while ((strcmp(commandInput, "") == 0) || (strcmp(commandInput, "\n") == 0))
gets_s(commandInput);
if(strcmp(commandInput, "Exit") == 0)
return;
handle(commandInput);
}
}
void split(char* src, const char* separator, char** dest, int* num) {
/*
src 源字符串的首地址(buf的地址)
separator 指定的分割字符
dest 接收子字符串的数组
num 分割后子字符串的个数
*/
char* pNext;
char *buf;
int count = 0;
if (src == NULL || strlen(src) == 0) //如果传入的地址为空或长度为0,直接终止
return;
if (separator == NULL || strlen(separator) == 0) //如未指定分割的字符串,直接终止
return;
pNext = (char*)strtok_s(src, separator,&buf); //必须使用(char *)进行强制类型转换(虽然不写有的编译器中不会出现指针错误)
while (pNext != NULL) {
*dest++ = pNext;
++count;
pNext = (char*)strtok_s(NULL, separator,&buf); //必须使用(char *)进行强制类型转换
}
*num = count;
}
void handle(char * commandInput) {
char* args[3];
int num;
split(commandInput, " ", args, &num);
if (num > 3) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
for (int i = 0; i < COMMAND_NUM-1; i++) {
if (strcmp(args[0], handlerlist[i].pname) == 0) {
handlerlist[i].handler(args,num);
return;
}
}
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("查无这条命令哦\n");
}
void doLogin(char**args,int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num > 1) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
int index = 0,sign=-1;
int tryTime = MAX_TRYLOGIN_TIME;
char ch, input_pwd[14],pwd[14],name[14];
printf("system@%s:~$ Input your Name:", UserInfo[curID].usrName);
scanf_s("%s",name,14);
for (int i = 0; i < UserInfo.size(); i++) {
if (strcmp(UserInfo[i].usrName, name) == 0) {
strcpy_s(pwd, UserInfo[i].usrPwd);
sign = i;
}
}
if (sign == -1) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("该用户不存在\n");
return;
}
while (tryTime--) {
index = 0;
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("Input your password:");
while ((ch = _getch()) != '\r') {
if (ch == '\b' && index > 0) {
printf("\b \b"); //空格+\b 是为了覆盖掉原来的字符
index--;
}
else if (ch != '\b') {
input_pwd[index++] = ch;
}
}
input_pwd[index] = '\0';
if (strcmp(input_pwd, pwd) == 0) {
printf("\nsystem@%s:~$ ", UserInfo[curID].usrName);
printf("密码正确\n");
curID = sign;
return;
}
else {
printf("\nsystem@%s:~$ ", UserInfo[curID].usrName);
printf("密码不正确,请重试\n");
}
}
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("连续输入3次密码都不正确\n");
}
void doLogout(char** args,int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num > 1) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
curID = 0;
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("退出成功\n");
return;
}
void doCreate(char**args,int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 3) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
//printf("system@%s:~$ ", UserInfo[curID].usrName);
//printf("fileName=%s , mode=%s\n", args[1], args[2]);
if (FileInfo[curID].size() >= MAX_FILE_NUM) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("该用户已经到达文件上限\n");
return;
}
int isRepeat = 0,free = 0;
for (int i = 0; i < FileInfo[curID].size(); i++) {
if (strcmp(FileInfo[curID][i].filename, args[1]) == 0) {
isRepeat = 1;
break;
}
}
if (isRepeat) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("文件重名\n");
return;
}
UFD fileInput;
strcpy_s(fileInput.creator,UserInfo[curID].usrName);
strcpy_s(fileInput.filename, strlen(args[1])+1,args[1] );
fileInput.mode = atoi(args[2]);
fileInput.length = 0;
//查找空闲的磁盘块存储
for (int i = 0; i < FileCluster.size(); i++) {
if (FileCluster[i].has_data == 0) { //盘内没有数据
fileInput.addr = i;
FileCluster[i].has_data = 1;
free = 1;
break;
}
}
if (!free) {
printf("system@%s:~$ 文件失败,没有空闲空间\n", UserInfo[curID].usrName);
return;
}
FileInfo[curID].push_back(fileInput);
printf("system@%s:~$ 文件创建成功\n", UserInfo[curID].usrName);
//状态栏
UOF StateInput;
strcpy_s(StateInput.creator,UserInfo[curID].usrName);
strcpy_s(StateInput.filename,strlen(args[1])+1,args[1] );
StateInput.mode = fileInput.mode;
StateInput.read_point = StateInput.write_point = 0;
StateInput.state = 0;
FileState[curID].push_back(StateInput);
}
void doWrite(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 2) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
char buf[1024],ch;
char fileName[14];
int exist = 0;
int indexState = -1; //FileState[curID][]中的序号
int indexInfo = -1; //FileInfo[curID][]的序号
int address; //文件对应起始的物理块
int i;
strcpy_s(fileName, strlen(args[1])+1, args[1]);
for (i = 0; i < FileInfo[curID].size(); i++) {
if (strcmp(FileInfo[curID][i].filename, fileName) == 0) {
if ((FileInfo[curID][i].mode == 0) || strcmp(FileInfo[curID][i].creator, UserInfo[curID].usrName) != 0 && FileState[curID][i].mode == 3) {
printf("system@%s:~$ 当前用户对%s文件没有写的权限\n", UserInfo[curID].usrName, fileName);
return;
}
exist = 1;
address = FileInfo[curID][i].addr;
indexInfo = i;
break;
}
}
if (!exist) {
printf("system@%s:~$ %s文件不存在\n", UserInfo[curID].usrName, fileName);
return;
}
for (i = 0; i < FileState[curID].size(); i++) {
if (strcmp(FileState[curID][i].filename,fileName) == 0) {
indexState = i;
break;
}
}
if (indexState == -1) { //代表fileState找不到vector<UOF>对象
UOF tmp;
strcpy_s(tmp.creator, FileInfo[curID][indexInfo].creator);
strcpy_s(tmp.filename, FileInfo[curID][indexInfo].filename);
tmp.mode = FileInfo[curID][indexInfo].mode;
tmp.read_point = tmp.write_point = 0;
tmp.state = 0;
FileState[curID].push_back(tmp);
for (i = 0; i < FileState[curID].size(); i++) {
if (strcmp(FileState[curID][i].filename, fileName) == 0) {
indexState = i;
break;
}
}
}
printf("====进入写文件状态,使用ctrl+s退出写状态====\n");
int needNewDiskNum=0;
vector<char>textList;
while ((ch =getchar() )!=(char)19) {
textList.push_back(ch);
}
int txtSize= textList.size();
int wbegin = FileState[curID][indexState].write_point;
while (FileCluster[address].nextcluster != address) {//最后一个磁盘的下一个指向自己
address = FileCluster[address].nextcluster;
}
/* 计算需要的磁盘数量 */
vector<int>newSpaceIndexList;
if (txtSize <= 256 - wbegin) { //判断是否足够插入原来的磁盘
needNewDiskNum = 0;
}
else {
needNewDiskNum =ceil( (txtSize - (256 - wbegin))*1.0 / 256);
}
newSpaceIndexList.push_back(address);
/* 最先适应算法,选择足够的磁盘 */
for (i = 0; i < FileCluster.size(); i++) {
if (newSpaceIndexList.size() == needNewDiskNum + 1)
break;
if (FileCluster[i].has_data == 0) {
newSpaceIndexList.push_back(i);
FileCluster[i].has_data = 1;
}
}
/* 修改选中磁盘的下一个 */
for (int k = 0; k < newSpaceIndexList.size()-1; i++) {
FileCluster[newSpaceIndexList[k]].nextcluster = newSpaceIndexList[k + 1];
}
/* 填入信息到磁盘 */
for (i = 0; i < txtSize; i++) {
if (wbegin == 256) {
wbegin = 0;
address = FileCluster[address].nextcluster;
}
FileCluster[address].data[wbegin] = textList[i];
wbegin++;
}
FileCluster[address].data[wbegin] = '\0';
wbegin++;
FileInfo[curID][indexInfo].length = txtSize;
/* 更新写指针 */
FileState[curID][indexState].write_point = wbegin;
printf("========退出写文件状态,且保存磁盘=========\n");
}
void doDelete(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 2) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
char fileName[14];
strcpy_s(fileName, strlen(args[1]) + 1, args[1]);
int exist = 0,i=0,tmp=-1;
for (i = 0; i < FileInfo.size(); i++) {
if (strcmp(FileInfo[curID][i].filename, fileName) == 0) {
if (strcmp(FileInfo[curID][i].creator, UserInfo[curID].usrName) != 0) {
printf("system@%s:~$ 当前用户对该文件没有删除的权限\n", UserInfo[curID].usrName);
return;
}
exist = 1;
break;
}
}
if (!exist) {
printf("system@%s:~$ 文件不存在\n", UserInfo[curID].usrName);
return;
}
int address;//文件存放的磁盘起始块号
int index;
/* 清除用户文件信息 */
for (i = 0; i < FileInfo[curID].size(); i++) {
if (strcmp(fileName, FileInfo[curID][i].filename) == 0) {
address = FileInfo[curID][i].addr;
index = i;
break;
}
}
vector <UFD> ::iterator iter = FileInfo[curID].begin() + index;
FileInfo[curID].erase(iter);
/* 清除磁盘记录 */
/* 获取磁盘写的长度*/
for (i = 0; i < FileState[curID].size(); i++) {
if (strcmp(fileName, FileState[curID][i].filename) == 0) {
index = i;
break;
}
}
while (1) {
if (FileCluster[address].nextcluster == address) { //最后一块
for (i = 0; i < FileState[curID][index].write_point; i++) {
FileCluster[address].data[i] = 0;
}
FileCluster[address].has_data = 0;
FileCluster[address].nextcluster = address;
break;
}
else {
for (i = 0; i < 256; i++) {
FileCluster[address].data[i] = 0;
}
FileCluster[address].has_data = 0;
tmp = address;
address = FileCluster[address].nextcluster;
FileCluster[tmp].nextcluster = tmp;
}
}
vector <UOF> ::iterator iter1 = FileState[curID].begin() + index;
FileState[curID].erase(iter1);
}
void doDir(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 1) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
if (FileInfo[curID].size() == 0) {
return;
}
printf("system@%s:~$ 目录内容如下;\n", UserInfo[curID].usrName);
for (int i = 0; i < FileInfo[curID].size(); i++)
{
if(i==0)
printf("%s %s\n", FileInfo[curID][i].filename,FileInfo[curID][i].creator);
else
printf("\t\t\t%s %s\n", FileInfo[curID][i].filename, FileInfo[curID][i].creator);
}
printf("\n");
}
void doOpen(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 2) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
/* 判断是否有权限 */
int exit = 0,i=0,j=0;
for (i = 0; i < FileState[curID].size(); i++) {
if (strcmp(FileState[curID][i].filename, args[1])==0) {
exit = 1;
FileState[curID][i].state = 1;//打开状态
break;
}
}
UOF tmp;
if (!exit) { //需要在UFD中打开
for (j = 0; j < FileInfo[curID].size(); j++) {
if (strcmp( FileInfo[curID][j].filename, args[1])==0) {
exit = 1;
strcpy_s(tmp.creator, FileInfo[curID][j].creator);
strcpy_s(tmp.filename, args[1]);
tmp.mode = FileInfo[curID][j].mode;
tmp.read_point = tmp.write_point = 0;
tmp.state = 1;
FileState[curID].push_back(tmp);
break;
}
}
}
if (!exit) {
printf("system@%s:~$ 文件不存在\n", UserInfo[curID].usrName);
return;
}
/* 判断权限 */
if (strcmp(FileState[curID][i].creator,UserInfo[curID].usrName) != 0 && FileState[curID][i].mode ==3 ) {
printf("system@%s:~$ 当前用户对该文件没有访问的权限\n", UserInfo[curID].usrName);
return;
}
openingState = 1;
}
void doReadAll(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 2) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
int length=0;
for (int i = 0; i < FileInfo[curID].size(); i++) {
if (strcmp(FileInfo[curID][i].filename, args[1]) == 0) {
length = FileInfo[curID][i].length;
break;
}
}
char* Args[3],tmp[14];
Args[0] = args[0];
Args[1] = args[1];
_itoa_s(length,tmp,10);
Args[2] = tmp;
doRead( Args, num+1);
}
void doRead(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num != 3) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
/* 判断是否有权限 */
int exit = 0, i = 0, address = -1, index = -1, length = atoi(args[2]);
for (i = 0; i < FileState[curID].size(); i++) {
if (strcmp(FileState[curID][i].filename, args[1])==0) {
/* 判断权限 */
if (strcmp(FileState[curID][i].creator, UserInfo[curID].usrName) != 0 && FileState[curID][i].mode == 3) {
printf("system@%s:~$ 当前用户对该文件没有访问的权限\n", UserInfo[curID].usrName);
return;
}
/* 判断权限 */
if (FileState[curID][i].mode == 1) {
printf("system@%s:~$ 当前用户对该文件没有读的权限\n", UserInfo[curID].usrName);
return;
}
if (FileState[curID][i].state != 1) {
printf("system@%s:~$ 该文件没有打开,请打开后再进行读操作\n", UserInfo[curID].usrName);
return;
}
exit = 1;
FileState[curID][i].state = 1;//打开状态
index = i;
break;
}
}
if (!exit) {
printf("system@%s:~$ 文件不存在或没打开\n", UserInfo[curID].usrName);
return;
}
readingState = 1;
for (i = 0; i < FileInfo[curID].size(); i++) {
if (strcmp(FileInfo[curID][i].filename, args[1]) == 0) {
address = FileInfo[curID][i].addr;
if (FileInfo[curID][i].length == 0) {
return;
}
break;
}
}
if (FileInfo[curID][i].length == FileState[curID][index].read_point) { //防止上次读完后不能选择重新开始读
FileState[curID][index].read_point = 0;
}
int rbegin = FileState[curID][index].read_point;
int readedDisk = rbegin / 256; //读过的磁盘数
for (i = 0; i < readedDisk; i++) {
address = FileCluster[address].nextcluster;
}
vector<char>textList;
for (i = 0; i < length; i++) {
if (rbegin % 256 == 255) {
address = FileCluster[address].nextcluster;
}
textList.push_back(FileCluster[address].data[i%256]);
rbegin++;
}
FileState[curID][index].read_point = rbegin;
for (int i = 0; i < length; i++) {
printf("%c", textList[i]);
}
printf("\n");
}
void doClose(char** args, int num) {
if (!openingState) {
printf("system@%s:~$ 没有打开的文件\n", UserInfo[curID].usrName);
return;
}
readingState = 0;
openingState = 0;
if (num != 2) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
vector<UOF>::iterator it;
int flag = 0;
for (it = FileState[curID].begin(); it != FileState[curID].end(); it++) {
if (strcmp(args[1], (*it).filename) == 0 ) {
if ((*it).state == 1) {
flag = 1;
FileState[curID].erase(it);
printf("system@%s:~$ 该文件已经关闭\n", UserInfo[curID].usrName);
return;
}
else {
printf("system@%s:~$ 该文件没有打开\n", UserInfo[curID].usrName);
return;
}
}
}
if (!flag) {
printf("system@%s:~$ 该目录下没有这个文件\n", UserInfo[curID].usrName);
return;
}
}
void doRegister(char** args, int num) {
if (readingState) {
printf("system@%s:~$ 有文件在进行写操作,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
else if (openingState) {
printf("system@%s:~$ 有文件已经打开,请关闭后再进行其他操作\n", UserInfo[curID].usrName);
return;
}
if (num !=3 ) {
printf("system@%s:~$ ", UserInfo[curID].usrName);
printf("参数错误哦\n");
return;
}
if (UserInfo.size() > MAX_USER_NUM) {
printf("system@%s:~$ 用户人数已满,无法注册\n", UserInfo[curID].usrName);
return;
}
int i = 0;
for (i = 0; i < UserInfo.size(); i++) {
if (strcmp(args[1], UserInfo[i].usrName) == 0) {
printf("system@%s:~$ 用户重名,无法注册\n", UserInfo[curID].usrName);
return;
}
}
MFD userInput;
strcpy_s(userInput.usrName,args[1] );
strcpy_s(userInput.usrPwd, args[2]);
userInput.link = UserInfo.size();
UserInfo.push_back(userInput);
//为新的用户开辟空间
vector<UFD>t;
FileInfo.push_back(t);
vector<UOF>temp;
FileState.push_back(temp);
printf("system@%s:~$ 用户创建成功\n", UserInfo[curID].usrName);
return;
}
2、学习到新知识分享
2.1、函数指针的使用–C的进阶
typedef void(*func)(char**,int);
typedef struct hand
{
const char* pname;
func handler;
}HAND_TO;
HAND_TO handlerlist[] =
{
{ "Login", doLogin},
{"Logout",doLogout},
{"Create",doCreate},
{"Delete",doDelete},
{"Write",doWrite},
{"open",doOpen},
{"dir",doDir},
{"Read",doRead},
{"ReadAll",doReadAll},
{"Close",doClose},
{"Register",doRegister}
};
for (int i = 0; i < COMMAND_NUM-1; i++) {
if (strcmp(args[0], handlerlist[i].pname) == 0) {
handlerlist[i].handler(args,num);
return;
}
}
通过这种方式可以节省if-else ,switch代码量,而且非常容易增删
2.2、用户登录密码不回显
我另一篇博客提到2种方法
C语言分别实现在Linux和window的输入不回显
2.3、终端获取多个参数,并存储于二级数组
void split(char* src, const char* separator, char** dest, int* num) {
/*
src 源字符串的首地址(buf的地址)
separator 指定的分割字符
dest 接收子字符串的数组
num 分割后子字符串的个数
*/
char* pNext;
char *buf;
int count = 0;
if (src == NULL || strlen(src) == 0) //如果传入的地址为空或长度为0,直接终止
return;
if (separator == NULL || strlen(separator) == 0) //如未指定分割的字符串,直接终止
return;
pNext = (char*)strtok_s(src, separator,&buf); //必须使用(char *)进行强制类型转换(虽然不写有的编译器中不会出现指针错误)
while (pNext != NULL) {
*dest++ = pNext;
++count;
pNext = (char*)strtok_s(NULL, separator,&buf); //必须使用(char *)进行强制类型转换
}
*num = count;
}
//使用案例
char* args[3];
int num;
split(commandInput, " ", args, &num);
2.4、模拟终端输入并保存后退出
非常简单,就是判断输入的字符是否为目的退出字符
ctrl+s =(char)19
char ch;
vector<char>textList;
while ((ch =getchar() )!=(char)19) {
textList.push_back(ch);
}
可以同行也可以不同行
ctrl+z=(char)-1
vectortextList;
char ch;
printf("%c", NULL);
while ((ch = getchar()) != (char)-1) {
textList.push_back(ch);
}
for (int i = 0; i < textList.size(); i++) {
printf("%c",textList[i]);
}
可以换行,但不能同行
这个ctrl+z的原因暂时还没找到。