算法竞赛入门经典 每日一题(UVa10966)------你值得尝试

本文档介绍了如何使用自定义函数处理文件系统操作,如cd、touch、mkdir、find和ls,以及命令行参数解析和命令管道。通过实例演示了如何在命令行环境中管理文件和目录,包括创建、查找、遍历和格式化输出。
摘要由CSDN通过智能技术生成

 

typedef unsigned long long LL;
typedef vector<int> VI;
typedef vector<string> VS;

const string ERROR_BAD_USAGE = "bad usage\n";
const string ERROR_NO_COMMAND = "no such command\n";
const string ERROR_DIR_NOT_FOUND = "path not found\n";
const string ERROR_DIR_FOUND = "a directory with the same name exists\n";
const string ERROR_DIR_OR_FILE_FOUND = "file or directory with the same name exists\n";
const string ERROR_FILE_NOT_FOUND = "file not found\n";
const string ERROR_EMPTY = "[empty]\n";


VS split(string s, char delim=' ') {
  if(delim != ' ')
    for(int i = 0; i < s.length(); i++) if(s[i] == delim) s[i] = ' ';
  stringstream ss(s);
  VS ret;
  string x;
  while(ss >> x) ret.push_back(x);
  return ret;
}


int get_int(string s, LL& v) {
  stringstream ss(s);
  if(ss >> v) return 1;
  return 0;
}

string trim(string s) {
  int L, R;
  for(L = 0; L < s.length(); L++) if(!isspace(s[L])) break;
  for(R = s.length()-1; R > L; R--) if(!isspace(s[R])) break;
  return s.substr(L, R-L+1);
}

struct File {
  int parent;
  string name;
  string fullpath;
  LL size;
  bool dir;
  bool hidden;
  vector<int> subdir;
  File(int parent=0, string name="", LL size=0, bool dir=true, bool hidden=false):parent(parent),name(name),size(size),dir(dir),hidden(hidden) {}
};

vector<File> fs;
int curDir;


bool comp(const int& x, const int& y) {
  return fs[x].fullpath < fs[y].fullpath;
}


bool comps(const int& x, const int& y) {
  return fs[x].size < fs[y].size || (fs[x].size == fs[y].size && fs[x].fullpath < fs[y].fullpath);
}


bool compS(const int& x, const int& y) {
  return fs[x].size > fs[y].size || (fs[x].size == fs[y].size && fs[x].fullpath < fs[y].fullpath);
}


int findFileInDirectory(int node, string name) {
  VI& subdir = fs[node].subdir;
  for(int i = 0; i < subdir.size(); i++)
    if(fs[subdir[i]].name == name) return subdir[i];
  return -1;
}


string joinPath(string path, string name) {
  if(path[path.size()-1] != '/') path += "/";
  return path + name;
}


string getAbsolutePath(int node) {
  if(!node) return "/";
  return joinPath(getAbsolutePath(fs[node].parent), fs[node].name);
}


int createFileInDirectory(int node, string name, LL size, bool dir, bool hidden) {
  fs.push_back(File(node, name, size, dir, hidden));
  int x = fs.size()-1;
  fs[x].fullpath = joinPath(getAbsolutePath(node), name);
  fs[node].subdir.push_back(x);
  return x;
}


int getDirNode(string path) {
  if(!path.length()) return curDir;
  int node = curDir;
  if(path[0] == '/') node = 0;
  VS dirs = split(path, '/');
  for(int i = 0; i < dirs.size(); i++) {
    if(dirs[i] == ".") continue;
    else if(dirs[i] == "..") {
      if(!node) return -1;
      node = fs[node].parent;
    } else {
      int x = findFileInDirectory(node, dirs[i]);
      if(x == -1 || !fs[x].dir) return -1;
      node = x;
    }
  }
  return node;
}


int isValidFileName(string name) {
  if(name.length() == 0 || name.length() > 255) return 0;
  if(name == "." || name.find("..") != string::npos) return 0;
  for(int i = 0; i < name.length(); i++)
    if(!isdigit(name[i]) && !isalpha(name[i]) && name[i] != '.') return 0;
  return 1;
}


int splitFileName(string fullpath, string& filename) {
  int n = fullpath.length();
  int x = n;
  for(int i = fullpath.length()-1; i >= 0; i--) {
    if(fullpath[i] == '/') { // the last '/'
      filename = fullpath.substr(i+1);
      string dir = fullpath.substr(0, i);
      if(dir == "") return 0;
      return getDirNode(dir);
    }
  }
  filename = fullpath;
  return curDir;
}


void newSession() { fs.clear(); fs.push_back(File()); curDir = 0; }


void findFileEx(VI& out, int node, string filename, bool recur, bool hidden, bool f=true, bool d=true) {
  VI& subdir = fs[node].subdir;
  for(int i = 0; i < subdir.size(); i++) {
    int x = subdir[i];
    if(fs[x].dir && recur) findFileEx(out, x, filename, recur, hidden, f, d);
    if(fs[x].hidden && !hidden) continue;
    if(filename == "" || fs[x].name == filename) {
      if((fs[x].dir && d) || (!fs[x].dir && f)) out.push_back(x);
    }
  }
}


string formatFiles(const VI& out) {
  stringstream ss;
  for(int i = 0; i < out.size(); i++) {
    ss << fs[out[i]].fullpath << " " << fs[out[i]].size;
    if(fs[out[i]].hidden) ss << " " << "hidden";
    if(fs[out[i]].dir) ss << " " << "dir";
    ss << "\n";
  }
  return ss.str();
}


bool parseArgs(VS params, VS& args, bool* sw, LL &v) {
  LL v2;
  for(int i = 0; i < params.size(); i++)
    if(params[i][0] == '-') {
      if(isalpha(params[i][1])) sw[params[i][1]] = 1;
      else if(get_int(params[i].substr(1), v2)) v = v2;
      else return false;
    }
    else args.push_back(params[i]);
  return true;
}


string runCommand(const VS& cmd) {
  VS params(cmd.begin()+1, cmd.end()), args;
  bool sw[256];
  LL v = 0;
  memset(sw, 0, sizeof(sw));
  if(!parseArgs(params, args, sw, v)) return ERROR_BAD_USAGE;
  
  int node;
  string filename;
  if(cmd[0] == "cd") {
    if(args.size() != 1) return ERROR_BAD_USAGE;
    if((node = getDirNode(args[0])) == -1) return ERROR_DIR_NOT_FOUND;
    curDir = node;
    return "";
  } else if(cmd[0] == "touch") {
    if(args.size() != 1) return ERROR_BAD_USAGE;
    if((node = splitFileName(args[0], filename)) == -1) return ERROR_DIR_NOT_FOUND;
    if(!isValidFileName(filename)) return ERROR_BAD_USAGE; //!

    int x = findFileInDirectory(node, filename);
    if(x != -1 && fs[x].dir) return ERROR_DIR_FOUND;
    if(x == -1) createFileInDirectory(node, filename, v, false, sw['h']);
    else { fs[x].size = v; fs[x].hidden = sw['h']; }
    return "";
  }
  if(cmd[0] == "mkdir") {
    if(args.size() != 1) return ERROR_BAD_USAGE;
    if((node = splitFileName(args[0], filename)) == -1) return ERROR_DIR_NOT_FOUND;
    if(!isValidFileName(filename)) return ERROR_BAD_USAGE;

    int x = findFileInDirectory(node, filename);
    if(x != -1) return ERROR_DIR_OR_FILE_FOUND;
    createFileInDirectory(node, filename, 0, true, sw['h']);
    return "";
  }
  if(cmd[0] == "find") {
    if(args.size() != 1) return ERROR_BAD_USAGE;
    if((node = splitFileName(args[0], filename)) == -1) return ERROR_DIR_NOT_FOUND;
    
    VI out;
    findFileEx(out, node, filename, sw['r'], sw['h']);
    if(out.size() == 0) return ERROR_FILE_NOT_FOUND;
    sort(out.begin(), out.end(), comp);
    return formatFiles(out);
  }
  if(cmd[0] == "ls") {
    if(args.size() > 1) return ERROR_BAD_USAGE;
    node = curDir;
    if(args.size() == 1) if((node = getDirNode(args[0])) == -1) return ERROR_DIR_NOT_FOUND;
    
    VI out;
    findFileEx(out, node, "", sw['r'], sw['h'], !sw['d'], !sw['f']);
    if(out.size() == 0) return ERROR_EMPTY;
    if(sw['s']) sort(out.begin(), out.end(), comps);
    else if(sw['S']) sort(out.begin(), out.end(), compS);
    else sort(out.begin(), out.end(), comp);
    return formatFiles(out);
  }
  if(cmd[0] == "pwd") {
    if(args.size() != 0) return ERROR_BAD_USAGE;
    return getAbsolutePath(curDir) + "\n";
  }
  if(cmd[0] == "exit") {
    if(args.size() != 0) return ERROR_BAD_USAGE;
    newSession();
    return "";
  }
  if(cmd[0] == "grep") return ERROR_BAD_USAGE;
  return ERROR_NO_COMMAND;
}


string runCommandLine(string cmd) {
  
  int n = cmd.length();
  int start = 0, inq = 0;
  VS commands;
  for(int i = 0; i <= n; i++)
    if(i == n || (cmd[i] == '|' && !inq))  { commands.push_back(cmd.substr(start, i-start)); start = i+1; }
    else if(cmd[i] == '"') inq = !inq;
  if(!commands.size()) return "";

  
  string lastoutput = runCommand(split(commands[0]));
  string line, s, ret;
  
  for(int i = 1; i < commands.size(); i++) {
    stringstream ss(commands[i]);
    if(!(ss >> s) || s != "grep") return ERROR_BAD_USAGE;
    getline(ss, s);
    s = trim(s);
    if(s.length() < 2 || s[0] != '"' || s[s.length()-1] != '"') return ERROR_BAD_USAGE;
    s = s.substr(1, s.length()-2);
    
    stringstream input(lastoutput);
    ret = "";
    while(getline(input, line)) {
      if(line.find(s) != string::npos) ret += line + "\n";
    }
    lastoutput = ret;
  }
  return lastoutput;
}

int main() {
  string cmd;
  newSession();
  while(getline(cin, cmd)) {
    cout << runCommandLine(cmd);
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭晋龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值