upd:2025/10
- 初步完成了虚拟的文件夹及文件目录管理,主要功能有:创建虚拟文件夹、显示路径、创建文件、列出当前路径下文件(夹)、转到特定目录。
upd:2025/11/19
- 初步实现了与 \(\operatorname {windows}\) 的真实接口,现在可以真实地在该 \(\operatorname {exe}\) 下创建文件夹与文件。
upd:2025/11/20
- 我们实现了编辑文件和保存并退出。现存问题为:编辑文本的时候,文本量小时闪屏问题不严重,文本量超过1000后闪屏问题较为严重(模拟高频率输入时,若写小说等还好)。
upd:2025/11/21
upd:2025/11/24
- 准备了一个 \(\operatorname {4K}\) 小游戏,准备明天加入这个系统里面供游玩 ^_^。
upd:2025/11/25
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
/**
* command:
* cd [dirname]
* to shift to a name_given dir
* mkdir [dirname]
* create a new dir under current dir
* (&md)
* touch [filename]
* create a new file under current file
* (&touhc)
* ls dir
* list the dir under current dir in specific order
* (&ld)
* ls file
* list the file under current dir
* (&lf)
* shut
* shut to have a good day without IT productions
* ret
* directly return to the Desktop
* don't ask me why i develop this command
* just because IIII HATEEEE inputing "Desktop"!!!!!
* cls
* just run system("cls") and then
* edit
* key in a filename to edit it
* press Alt+F to quit
* game
* to play game
* using F,G,H,J,and O+K to quit
* */
//-----------------文本编辑模块全局变量--------------
string EXE_DIR;
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD originalConsoleMode; //save original console mode
CONSOLE_CURSOR_INFO originalCursorInfo;
//---------------------------------------------------
// ---------------------- 获取exe运行目录 ------------------
string getExeDir() {
char exePath[MAX_PATH];
// 获取exe完整路径(比如 D:\project\file_manager.exe)
GetModuleFileNameA(NULL, exePath, MAX_PATH);
// 找到最后一个反斜杠,截取目录部分(比如 D:\project)
string path(exePath);
size_t pos = path.find_last_of("\\/");
if (pos != string::npos) {
path = path.substr(0, pos);
}
return path;
}
// ---------------------------------------------------------
int dircnt=1; //the number of dir
int now=1; //the dir's ID which you are now
int fa[100010]; //fa for Union-Find
map<string,int>mp; //give it a name turned out an ID
struct directory{
string dirname; //its name
int dep; //the dep in the dir_tree
vector<int>son; //its son_dir
//give it a name turned out an ID of file
map<string,int>mp_file;
//its son_file
vector<string>son_file;
int filecnt=0; //the number of file
};
directory a[100010]; //struct for dirs
struct file{
string filename;
};
file b[100010]; //struct for file
int tfc=0; //overall file count
//for overall file conduction
map<pair<int,string> ,int>tmf;
deque<int>pos; // your current path
int pos_size=1; // the size of path
//-----------------辅助函数:构建真实文件路径--------
string buildRealPath() {
deque<int> temp_pos = pos;
string real_path = EXE_DIR; // 基于exe运行目录
// 跳过虚拟根目录“Desktop”(因为它对应exe目录,无需拼接)
temp_pos.pop_front(); // 移除虚拟根的Desktop(pos队列第一个元素是Desktop的ID)
// 拼接后续虚拟目录(比如虚拟路径Desktop/dir1 → 真实路径exe_dir/dir1)
while (!temp_pos.empty()) {
int dir_id = temp_pos.front();
temp_pos.pop_front();
real_path += "\\"; // Windows路径用反斜杠
real_path += a[dir_id].dirname;
}
return real_path;
}
static void SetPos(int x,int y){
COORD point={x,y};
HANDLE HOutput= GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(HOutput,point);
}
//upd:2025/11/19
//---------------------------------------------------
//------------------控制台控制函数-------------------
//保存控制台原始配置(编辑前调用)
void saveConsoleConfig() {
GetConsoleMode(hStdin, &originalConsoleMode); // 保存控制台模式
GetConsoleCursorInfo(hStdout, &originalCursorInfo); // 新增:保存默认光标状态
}
//设置为编辑模式(无回显无行缓冲)
void setEditMode(){
DWORD editMode = originalConsoleMode;
editMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); // 关闭行缓冲和回显
editMode |= ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS; // 支持方向键
editMode &= ~ENABLE_QUICK_EDIT_MODE; // 新增:禁用快速编辑模式(减少花屏)
SetConsoleMode(hStdin, editMode);
SetConsoleOutputCP(936);
SetConsoleCP(936);
}
// 设置光标可见性(编辑时显示,退出时恢复)
void setCursorVisibility(bool visible) {
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(hStdout, &cursorInfo); // 获取当前光标信息
if (visible) {
// cursorInfo.bVisible = TRUE; // 光标可见
cursorInfo.dwSize = 10; // 光标大小(1-100,20是适中大小)
} else {
cursorInfo.bVisible = originalCursorInfo.bVisible; // 恢复默认可见性
cursorInfo.dwSize = originalCursorInfo.dwSize; // 恢复默认大小
}
SetConsoleCursorInfo(hStdout, &cursorInfo); // 应用设置
}
//回复控制台原始模式(编辑后调用,不影响原有系统)
void restoreConsoleConfig(){
SetConsoleMode(hStdin,originalConsoleMode);
SetConsoleOutputCP(CP_ACP);
SetConsoleCP(CP_ACP);
}
//设置光标位置
void clearScreen(){
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdout, &csbi);
DWORD dwSize = csbi.dwSize.X * csbi.dwSize.Y;
DWORD dwWritten;
// 1. 填充空格覆盖屏幕(清除文字)
// system("cls");
FillConsoleOutputCharacter(hStdout, ' ', dwSize, {0, 0}, &dwWritten);
// 2. 强制设置文本属性为「黑底白字」(修复花屏)
// 0x07 是 Windows 控制台默认属性:FOREGROUND_WHITE | BACKGROUND_BLACK
FillConsoleOutputAttribute(hStdout, 0x07, dwSize, {0, 0}, &dwWritten);
// SetCursorPos(0, 0);
}
//upd:2025/11/19
//---------------------------------------------------
//-----------------文件读写函数----------------------
bool readFile(const string &real_file_path ,vector<string>&lines){
ifstream file(real_file_path,ios::in);
if(!file.is_open())return false;
lines.clear();
string line;
while(getline(file,line)){
lines.push_back(line);
}
file.close();
if(lines.empty())lines.emplace_back("");
return true;
}
bool saveFile(const string &real_file_path,const vector<string>&lines){
ofstream file_for_now(real_file_path,ios::out | ios::trunc);
if(!file_for_now.is_open())return false;
for(size_t i=0;i<lines.size();i++){
file_for_now<<lines[i];
if(i!=lines.size()-1){
file_for_now<<endl;
}
}
file_for_now.close();
return true;
}
//upd:2025/11/19
//---------------------------------------------------
//-----------------文本显示和编辑函数----------------
void displayText(const vector<string>&lines){
clearScreen();
SetPos(0,0);
int lineCount=lines.size();
for(int i=0;i<lineCount;i++){
cout<<lines[i];
if(i!=lineCount-1){
cout<<'\n';
}
}
cout.flush();
// for(const auto&line:lines){
// cout<<line<<endl;
// }
}
//upd:2025/11/20
bool editTextCore(const string &real_file_path){
vector<string>lines;
if(!readFile(real_file_path,lines)){
cout<<"Sorry for failing to get the file!"<<endl;
system("pause > nul");
return false;
}
int cursorX=0;
int cursorY=0;
cursorY=min(cursorY,static_cast<int>(lines.size())-1);
bool isEditing=true;
bool saveSuccess=false;
saveConsoleConfig();
setEditMode();
setCursorVisibility(true);
displayText(lines);
SetCursorPos(cursorX,cursorY);
INPUT_RECORD inputRecord;
DWORD readCount;
while(isEditing){
ReadConsoleInput(hStdin,&inputRecord,1,&readCount);
if(inputRecord.EventType != KEY_EVENT || !inputRecord.Event.KeyEvent.bKeyDown){
continue;
}
KEY_EVENT_RECORD key=inputRecord.Event.KeyEvent;
//Alt+F save and quit
if((key.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) and key.wVirtualKeyCode == 0x46){
saveSuccess = saveFile(real_file_path,lines);
SetCursorPos(0,static_cast<int>(lines.size()+1));
clearScreen();
SetPos(0,0);
cout<<(saveSuccess?" [ Edit Success ] Successfully saved the file!":" [ Edit Fail ] Failed to save the file!")<<endl;
isEditing = false;
break;
}
switch(key.wVirtualKeyCode){
case VK_LEFT: // 左箭头
if(cursorX > 0)cursorX--;
break;
case VK_RIGHT: // 右箭头
if(cursorX<static_cast<int>(lines[cursorY].size()))cursorX++;
break;
case VK_UP: // 上箭头
if(cursorY>0){
cursorY--;
cursorX=min(cursorX,static_cast<int>(lines[cursorY].size()));
}
break;
case VK_DOWN: // 下箭头
if (cursorY < static_cast<int>(lines.size()) - 1) {
cursorY++;
cursorX = min(cursorX, static_cast<int>(lines[cursorY].size()));
}
break;
case VK_BACK:
if (cursorX > 0) {
lines[cursorY].erase(cursorX - 1, 1);
cursorX--;
displayText(lines);
} else if (cursorY > 0) {
cursorX = static_cast<int>(lines[cursorY - 1].size());
lines[cursorY - 1] += lines[cursorY];
lines.erase(lines.begin() + cursorY);
cursorY--;
displayText(lines);
}
break;
case VK_DELETE:
if (cursorX < static_cast<int>(lines[cursorY].size())) {
lines[cursorY].erase(cursorX, 1);
displayText(lines);
} else if (cursorY < static_cast<int>(lines.size()) - 1) {
lines[cursorY] += lines[cursorY + 1];
lines.erase(lines.begin() + cursorY + 1);
displayText(lines);
}
break;
case VK_RETURN:
{
string prev_line = lines[cursorY].substr(0, cursorX);
string next_line = lines[cursorY].substr(cursorX);
lines[cursorY] = prev_line;
lines.insert(lines.begin() + cursorY + 1, next_line);
cursorY++;
cursorX = 0;
displayText(lines);
// SetCursorPos(cursorX,cursorY);
break;
}
case VK_TAB:
{
lines[cursorY].insert(cursorX," ");
cursorX+=4;
displayText(lines);
break;
}
default:
if (key.uChar.AsciiChar != 0 && isprint(key.uChar.AsciiChar)) {
lines[cursorY].insert(cursorX, 1, key.uChar.AsciiChar);
cursorX++;
displayText(lines);
// SetCursorPos(cursorX,cursorY);
}
break;
}
SetPos(cursorX,cursorY);
}
// 恢复控制台模式
setCursorVisibility(false);
restoreConsoleConfig();
cout << "Enter any key to return to the file manager simulator..." << endl;
system("pause > nul");
return saveSuccess;
}
// 对外暴露的编辑入口(对接你的文件管理系统)
void editFile() {
string filename;
cout<<"input the file to edit:";
cin >> filename;
// 1. 检查当前目录是否存在该文件(用你系统的内存记录判断)
if (!a[now].mp_file[filename]) {
cout<<"Sorry , there's no file named \" "<<filename<<" \" !"<<endl;
// cout<<"错误:当前目录下没有名为 \""<<filename<<"\" 的文件!"<<endl;
system("pause > nul");
return;
}
string real_file_path = buildRealPath() + "\\" + filename;
cout << "real file path:" << real_file_path << endl; // 新增:打印真实路径,方便确认
cout << "Entering Edit MODE ( Alt + F to save&quit) ..." << endl;
system("pause > nul");
editTextCore(real_file_path);
}
//---------------------------------------------------
void mkdir(){//"mkdir"
string new_name;
cin>>new_name;
if(mp[new_name]){//SPJ for [under]
cout<<"already have this directory!"<<endl;
return;
}
dircnt++;
mp[new_name]=dircnt; //ID
fa[ dircnt ] = now; //son and father
a[now].son.push_back(dircnt); //contain ID
a[dircnt].dep=a[now].dep+1; //dep
a[dircnt].dirname=new_name; //dir_name
//upd:2025/11/19 create a real diretory
string real_dir_path = buildRealPath() + "\\" + new_name;
// Windows API:创建目录(支持多级目录,需要设置CREATE_NEW_CONSOLE?不,用CREATE_DIRECTORY)
BOOL success = CreateDirectoryA(real_dir_path.c_str(), NULL);
if (success || GetLastError() == ERROR_ALREADY_EXISTS) {
cout << "Successfully make a directory named\"" << new_name << "\"" << endl;
} else {
cout << "Failed to make directory \"" << new_name << "\"! Error code: " << GetLastError() << endl;
}
}
int find_dep(int x,int to_dep){
if(a[x].dep==to_dep)return x;
return find_dep(fa[x],to_dep);
}
void change_dir(){//"cd"
string to_name;
cin>>to_name;
if(mp[to_name]==0){//SPJ for [under] invalid case
cout<<"you don't have such a directory ,which named \""<<to_name<<"\""<<endl;
return;
}
int to=mp[to_name],to_dep=a[to].dep;
now=to;
cout<<"Loading..."<<endl;
pos.clear();//as you see
pos_size=0;
for(int i=1;i<=to_dep;i++){//start from Desktop (time_eff not good(no care))
pos.push_back(find_dep(to,i));
pos_size++;
//dont forget pos_size
//cout<<"id:"<<find_dep(to,i)<<" and dir_name:"<<a[find_dep(to,i)].dirname<<endl;
////test [up];
}
cout<<"Successfully changed to \""<<to_name<<"\""<<endl;
}
void ret(){//"ret"
string to_name="Desktop";
now=1;
cout<<"Loading..."<<endl;
pos.clear();
pos_size=1;
pos.push_back(1);
cout<<"Successfully changed to \""<<to_name<<"\""<<endl;
}
int overall_now;
void list_dir(int now,int blk){//"ls dir"
cout<<a[now].dirname;
if(a[now].son.empty() and now == overall_now){
cout<<endl;
return;
}
if(a[now].son.empty())return;
cout<<"--";
// int delta=0/*,cnt=1*/;
// for(auto v:a[now].son)delta=max(delta,int(a[v].dirname.size())+2);
// that's not true[up]
for(int i=0;i<(int)a[now].son.size();i++){
if(i==(int)a[now].son.size()-1)cout<<"|-";
else cout<<"| ";
int v=a[now].son[i];
list_dir(v,blk+(int)a[v].dirname.size()+4);
if(i==(int)a[now].son.size()-1)continue;
else cout<<endl<<string(blk,' ');
}
cout<<endl;
return ;
}
void list_fl(int now){//"ls file"
printf("LISTING...:\n");
if((int)a[now].son_file.size()==0){
cout<<"However , you have no file under this directory... :("<<endl;
return;
}
for(auto s:a[now].son_file){
cout<<string(5,' ')<<s<<endl;
}
cout<<"total:"<<a[now].filecnt<<endl;
return;
}
void touch(int now,string new_name){
if(a[now].mp_file[new_name])
{//SPJ
cout<<"Already have such a file named \""<<new_name<<"\""<<endl;
// printf("Already have such a file named \"")//fail...
return;
}
a[now].mp_file[new_name]=++a[now].filecnt; //for dir
a[now].son_file.push_back(new_name); //for dir's filr's name(for ls fl)
tmf[make_pair(now,new_name)]=++tfc; //for allover
b[tfc].filename=new_name; //contain its name
//-------upd:2025/11/19
string real_file_path = buildRealPath() + "\\" + new_name;
ofstream real_file(real_file_path); // 创建空文件
if (real_file.is_open()) {
real_file.close();
printf("Successully created a file named \"%s\"\n", new_name.c_str());
} else {
printf("Failed to create file \"%s\"!\n", new_name.c_str());
}
}
void init_system(){//as you see
EXE_DIR = getExeDir(); // 初始化exe运行目录
for (int i=0;i<=100009;i++)fa[i]=i; //Union-find
mp["Desktop"]=1; //desk_id
a[1].dirname="Desktop"; //desk_name
a[1].dep=1; //desk_dep
now=1; //cur_pos
pos.push_back(1); //cur_path
SetConsoleOutputCP(936); // 中文编码
SetConsoleCP(936);
cout<<"<Desktop>:";
}
void print_path(){
cout<<"<";
for(int i=1;i<=pos_size;i++){
cout<<a[pos.front()].dirname;
pos.push_back(pos.front());
pos.pop_front();
if(i!=pos_size)cout<<"/";
//SPJ
//using a deque to turn it aside to output
//your current path
}
cout<<">:";
}
struct _4Kgame{
struct node{
bool _1,_2,_3,_4;
};
deque<node>q;
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
void init(){
srand(time(NULL));
for (int i = 1; i <= 10; i++) {
BackToRandom:;
node now = {0, 0, 0, 0};
if (rand() % 4 == 0) now._1 = 1;
if (rand() % 4 == 0) now._2 = 1;
if (rand() % 4 == 0) now._3 = 1;
if (rand() % 4 == 0) now._4 = 1;
if(!now._1 and !now._2 and !now._3 and !now._4)goto BackToRandom;
q.push_back(now);
}
}
void flsh() {
system("cls");
cout<<"Press O+K to exit"<<endl;
for (int i = 9; i >= 0; i--) {
cout << " ";
node now = q[i];
if (now._1) cout << "O ";
else cout << " ";
if (now._2) cout << "O ";
else cout << " ";
if (now._3) cout << "O ";
else cout << " ";
if (now._4) cout << "O ";
else cout << " ";
cout << endl;
}
cout << "-------------" << endl;
}
int check() {
node now = q[0];
bool f = KEY_DOWN('F');
bool g = KEY_DOWN('G');
bool h = KEY_DOWN('H');
bool j = KEY_DOWN('J');
bool o = KEY_DOWN('O');
bool k = KEY_DOWN('K');
Sleep(20);
if(f)cout<<"F";
if(g)cout<<"G";
if(h)cout<<"H";
if(j)cout<<"J";
if(o)cout<<"O";
if(k)cout<<"K";
if(o==1 and k==1){
return -1;
}
if(now._1==f and now._2==g and now._3==h and now._4==j){
return 1;
}else return 0;
}
void solve(){
init();flsh();
while (1) {
int cn=check();
if (cn==1) {
q.pop_front();
Back_to_random_solve:;
node now={0, 0, 0, 0};
if(rand()%4==0)now._1=1;
if(rand()%4==0)now._2=1;
if(rand()%4==0)now._3=1;
if(rand()%4==0)now._4=1;
if(!now._1 and !now._2 and !now._3 and !now._4)goto Back_to_random_solve;
q.push_back(now);
flsh();
}
if(cn==0)continue;
if(cn==-1)return;
Sleep(70);
}
}
}_4K;
struct PassSystem{
map<string,bool>Username;
map<pair<string,string>,bool>Password;
string User1="Noivelist";
string Password1="SJSsjs090121";
string User2="shanxinhanshifanbotaobaba";
string Password2="54188";
void init_User(string User,string pw_u){
Username[User]=true;
Password[make_pair(User,pw_u)]=true;
}
void Log(){
init_User(User1,Password1);
init_User(User2,Password2);
bool is_Passed=false;
while(!is_Passed){
string name_now;
cout<<"Please key in the username:";
cin>>name_now;
if(Username[name_now]){
string pw_now;
cout<<"Now key in the password:";
cin>>pw_now;
if(Password[make_pair(name_now,pw_now)]){
cout<<"Login Successfully!"<<endl;
return;
}
else cout<<"Wrond Password!"<<endl;
}
else cout<<"Username not exist!"<<endl;
}
}
}Login;
int main(){
Login.Log();
init_system();
while(1){
string tmp;
cin>>tmp;
if(isdigit(tmp[0])){
cout<<tmp<<endl;
print_path();
}
if(!isdigit(tmp[0])){
if(tmp=="ret"){
ret();
print_path();
continue;
}
if(tmp=="mkdir" or tmp=="md"){
mkdir();
print_path();
continue;
}
if(tmp=="cd"){
change_dir();
print_path();
continue;
}
if(tmp=="ls"){
string ty;
cin>>ty;
if(ty=="dir") overall_now=now,list_dir(now,a[now].dirname.size()+2);
if(ty=="file") list_fl(now);
print_path();
continue;
}
if(tmp=="ld"){
overall_now=now,list_dir(now,a[now].dirname.size()+2);
print_path();
continue;
}
if(tmp=="lf"){
list_fl(now);
print_path();
continue;
}
if(tmp=="touch" or tmp=="touhc"){
string ty;
cin>>ty;
touch(now,ty);
print_path();
continue;
}
if(tmp=="shut"){
cout<<endl<<"Shut down the system successfully!"<<endl;
cout<<"Have a good day!"<<endl;
exit(0);
}
if(tmp=="cls"){
system("cls");
print_path();
continue;
}
if(tmp=="edit"){
editFile();
print_path();
continue;
}
if(tmp=="game"){
_4K.solve();
system("cls");
print_path();
continue;
}
cout<<"Such Command is not exist!"<<endl;
print_path();
}
}
return 0;
}
/**
* g++ a.cxx
* ./a.out
*
*
**/