查看: 3680| 回复: 8
跳转到指定楼层
上一主题 下一主题
收起左侧

[学C/C++] 求问airbnb题库的file system这题follow up的c++写法

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
如题~file system这题的follow up是要写一个watch函数来call back,感觉大家大部分都是java选手,java可以用runnable来实现,c++虽然也有这个东西,但是我试着实现的时候总是有bug。
求问地里是否有准备空气床家的c++选手,这个watch函数具体要怎么实现呢,谢谢大家了!给大家加米!

评分

参与人数 2大米 +3 收起 理由
14417335 + 2
安吉拉鸡 + 1 赞一个

查看全部评分


上一篇:刷题应该用什么语言,回复的加米
下一篇:关于条件判断时的<或者<=
🔗
magicsets 2018-11-11 16:39:50 | 只看该作者
全局:
我根据搜到的地里帖子的描述写了一份代码,不过不太确定原题的一些细节要求,楼主可以参考着看一下Callback部分的处理..

编译要用C++14,也就是加上 -std=c++14 的flag

  1. #include <iostream>
  2. #include <memory>
  3. #include <sstream>
  4. #include <string>
  5. #include <unordered_map>
  6. #include <utility>
  7. #include <vector>

  8. #define DISALLOW_COPY_AND_ASSIGN(classname) \
  9.   classname(const classname &orig) = delete;\
  10.   classname & operator=(const classname &rhs) = delete

  11. typedef std::string ValueType;
  12. typedef std::shared_ptr<ValueType> ValueTypePtr;

  13. class FileSystemDirectory;

  14. inline std::string ToString(const ValueTypePtr &value) {
  15.   if (value == nullptr) {
  16.     return "NULL";
  17.   }
  18.   std::ostringstream oss;
  19.   oss << *value;
  20.   return oss.str();
  21. }

  22. // 文件系统Event类型
  23. enum class FileSystemEventType {
  24.   kCreate = 0,
  25.   kSetValue
  26. };

  27. // 文件系统Event接口
  28. class FileSystemEvent {
  29. public:
  30.   FileSystemEventType getType() const {
  31.     return type_;
  32.   }

  33.   const FileSystemDirectory& getDirectory() const {
  34.     return directory_;
  35.   }

  36. protected:
  37.   FileSystemEvent(const FileSystemEventType &type,
  38.                   const FileSystemDirectory &directory)
  39.       : type_(type),
  40.         directory_(directory) {}

  41. private:
  42.   const FileSystemEventType type_;
  43.   const FileSystemDirectory &directory_;

  44.   DISALLOW_COPY_AND_ASSIGN(FileSystemEvent);
  45. };

  46. // 文件系统的Create Event
  47. class FileSystemEventCreate : public FileSystemEvent {
  48. public:
  49.   explicit FileSystemEventCreate(const FileSystemDirectory &directory)
  50.       : FileSystemEvent(FileSystemEventType::kCreate, directory) {}

  51. private:
  52.   DISALLOW_COPY_AND_ASSIGN(FileSystemEventCreate);
  53. };

  54. // 文件系统的SetValue Event
  55. class FileSystemEventSetValue : public FileSystemEvent {
  56. public:
  57.   FileSystemEventSetValue(const FileSystemDirectory &directory,
  58.                           const ValueTypePtr &old_value,
  59.                           const ValueTypePtr &new_value)
  60.       : FileSystemEvent(FileSystemEventType::kSetValue, directory),
  61.         old_value_(old_value),
  62.         new_value_(new_value) {}

  63.   const ValueTypePtr& getOldValue() const {
  64.     return old_value_;
  65.   }

  66.   const ValueTypePtr& getNewValue() const {
  67.     return new_value_;
  68.   }

  69. private:
  70.   const ValueTypePtr old_value_;
  71.   const ValueTypePtr new_value_;

  72.   DISALLOW_COPY_AND_ASSIGN(FileSystemEventSetValue);
  73. };

  74. // 文件系统Event Callback接口定义
  75. class FileSystemEventCallback {
  76. public:
  77.   virtual ~FileSystemEventCallback() {}

  78.   virtual void invoke(const FileSystemEvent &event) = 0;
  79. };

  80. // 方便in-place定义Callback的Lambda Wrapper
  81. template <typename Callback>
  82. class FileSystemEventLambdaCallback : public FileSystemEventCallback {
  83. public:
  84.   explicit FileSystemEventLambdaCallback(const Callback &callback)
  85.       : callback_(callback) {}

  86.   void invoke(const FileSystemEvent &event) override {
  87.     callback_(event);
  88.   }

  89. private:
  90.   const Callback callback_;

  91.   DISALLOW_COPY_AND_ASSIGN(FileSystemEventLambdaCallback);
  92. };

  93. // 单个文件系统节点
  94. class FileSystemDirectory {
  95. public:
  96.   FileSystemDirectory(const FileSystemDirectory *parent,
  97.                       const std::string &directory_name)
  98.       : parent_(parent),
  99.         directory_name_(directory_name) {}

  100.   bool create(const std::vector<std::string> &path_components,
  101.               const std::size_t component_index,
  102.               const bool recursive) {
  103.     if (component_index >= path_components.size()) {
  104.       return true;
  105.     }
  106.     const std::string &child_name = path_components[component_index];
  107.     const auto it = children_.find(child_name);
  108.     FileSystemDirectory *child;
  109.     if (it != children_.end()) {
  110.       child = it->second.get();
  111.     } else {
  112.       if (!recursive && component_index + 1 < path_components.size()) {
  113.         return false;
  114.       }
  115.       child = new FileSystemDirectory(this, child_name);
  116.       children_.emplace(child_name, std::unique_ptr<FileSystemDirectory>(child));
  117.       for (const auto &callback : callbacks_) {
  118.         FileSystemEventCreate event(*child);
  119.         callback->invoke(event);
  120.       }
  121.     }
  122.     return child->create(path_components, component_index + 1, recursive);
  123.   }

  124.   ValueTypePtr getValue(const std::vector<std::string> &path_components,
  125.                         const std::size_t component_index) {
  126.     if (component_index < path_components.size()) {
  127.       const auto it = children_.find(path_components[component_index]);
  128.       if (it == children_.end()) {
  129.         return nullptr;
  130.       }
  131.       return it->second->getValue(path_components, component_index + 1);
  132.     }
  133.     return value_;
  134.   }

  135.   template <typename ValueReference>
  136.   bool setValue(const std::vector<std::string> &path_components,
  137.                 const std::size_t component_index,
  138.                 ValueReference &&new_value) {
  139.     if (component_index < path_components.size()) {
  140.       const auto it = children_.find(path_components[component_index]);
  141.       if (it == children_.end()) {
  142.         return false;
  143.       }
  144.       return it->second->setValue(path_components,
  145.                                   component_index + 1,
  146.                                   std::forward<ValueReference>(new_value));
  147.     }
  148.     const ValueTypePtr old_value = value_;
  149.     value_ = std::make_shared<ValueType>(std::forward<ValueReference>(new_value));
  150.     for (const auto &callback : callbacks_) {
  151.       FileSystemEventSetValue event(*this, old_value, value_);
  152.       callback->invoke(event);
  153.     }
  154.     return true;
  155.   }

  156.   bool registerCallback(const std::vector<std::string> &path_components,
  157.                         const std::size_t component_index,
  158.                         FileSystemEventCallback *callback) {
  159.     if (component_index < path_components.size()) {
  160.       const auto it = children_.find(path_components[component_index]);
  161.       if (it == children_.end()) {
  162.         return false;
  163.       }
  164.       return it->second->registerCallback(path_components,
  165.                                           component_index + 1,
  166.                                           callback);
  167.     }
  168.     callbacks_.emplace_back(callback);
  169.     return true;
  170.   }

  171.   const FileSystemDirectory* getParent() const {
  172.     return parent_;
  173.   }

  174.   const std::string& getName() const {
  175.     return directory_name_;
  176.   }

  177.   std::string getPath() const {
  178.     std::string path;
  179.     if (parent_ != nullptr) {
  180.       path = parent_->getPath();
  181.     }
  182.     // The checking is for special handling of the root directory (i.e. '/').
  183.     if (path.empty() || path.back() != '/') {
  184.       path.push_back('/');
  185.     }
  186.     path.append(directory_name_);
  187.     return path;
  188.   }

  189. private:
  190.   const FileSystemDirectory *parent_;
  191.   std::string directory_name_;
  192.   ValueTypePtr value_;
  193.   std::unordered_map<std::string, std::unique_ptr<FileSystemDirectory>> children_;
  194.   std::vector<std::unique_ptr<FileSystemEventCallback>> callbacks_;

  195.   DISALLOW_COPY_AND_ASSIGN(FileSystemDirectory);
  196. };

  197. // 文件系统的主要代码
  198. class FileSystem {
  199. public:
  200.   FileSystem()
  201.       : root_(std::make_unique<FileSystemDirectory>(nullptr, "")) {}

  202.   // recursive为true时为递归创建,类似linux下面的mkdir -p命令
  203.   bool create(const std::string &path, const bool recursive = false) {
  204.     std::vector<std::string> components;
  205.     const bool valid = SplitPathComponents(path, &components);
  206.     if (components.empty()) {
  207.       // Cannot re-create the root directory.
  208.       return false;
  209.     }
  210.     return valid && root_->create(components,
  211.                                   0 /* component_index */,
  212.                                   recursive);
  213.   }

  214.   ValueTypePtr getValue(const std::string &path) {
  215.     std::vector<std::string> components;
  216.     if (!SplitPathComponents(path, &components)) {
  217.       return nullptr;
  218.     }
  219.     return root_->getValue(components, 0 /* component_index */);
  220.   }

  221.   template <typename ValueReference>
  222.   bool setValue(const std::string &path, ValueReference &&new_value) {
  223.     std::vector<std::string> components;
  224.     if (!SplitPathComponents(path, &components)) {
  225.       return nullptr;
  226.     }
  227.     return root_->setValue(components,
  228.                            0 /* component_index */,
  229.                            std::forward<ValueReference>(new_value));
  230.   }

  231.   bool registerCallback(const std::string &path,
  232.                         FileSystemEventCallback *callback) {
  233.     std::vector<std::string> components;
  234.     if (!SplitPathComponents(path, &components)) {
  235.       return false;
  236.     }
  237.     return root_->registerCallback(components,
  238.                                    0 /* component_index */,
  239.                                    callback);
  240.   }

  241.   template <typename Callback>
  242.   bool registerLambdaCallback(const std::string &path,
  243.                               const Callback &callback) {
  244.     return registerCallback(
  245.         path, new FileSystemEventLambdaCallback<Callback>(callback));
  246.   }

  247. private:
  248.   static bool SplitPathComponents(const std::string &path,
  249.                                   std::vector<std::string> *components) {
  250.     // State machine.
  251.     const int kInit = 0;
  252.     const int kDelimiter = 1;
  253.     const int kName = 2;

  254.     std::string component;
  255.     int state = 0;
  256.     for (const char c : path) {
  257.       switch (state) {
  258.         case kInit:
  259.           if (c == '/') {
  260.             state = kDelimiter;
  261.           } else if (c != ' ' && c != '\t') {
  262.             // Invalid path expression.
  263.             return false;
  264.           }
  265.           break;
  266.         case kDelimiter:
  267.           if (c != '/') {
  268.             state = kName;
  269.             component.push_back(c);
  270.           }
  271.           break;
  272.         case kName:
  273.           if (c != '/') {
  274.             component.push_back(c);
  275.           } else {
  276.             components->emplace_back(std::move(component));
  277.             component.clear();
  278.             state = kDelimiter;
  279.           }
  280.           break;
  281.       }
  282.     }
  283.     // Last component.
  284.     if (state == kName) {
  285.       components->emplace_back(std::move(component));
  286.     }
  287.     return true;
  288.   }

  289.   std::unique_ptr<FileSystemDirectory> root_;

  290.   DISALLOW_COPY_AND_ASSIGN(FileSystem);
  291. };

  292. std::string FormatEventMessage(const FileSystemEvent &event) {
  293.   std::ostringstream oss;
  294.   switch (event.getType()) {
  295.     case FileSystemEventType::kCreate: {
  296.       const FileSystemDirectory &directory = event.getDirectory();
  297.       oss << "A new directory with name \"" << directory.getName() << "\""
  298.           << " has been created under path "
  299.           << directory.getParent()->getPath();
  300.       break;
  301.     }
  302.     case FileSystemEventType::kSetValue: {
  303.       const FileSystemEventSetValue &set_value_event =
  304.           static_cast<const FileSystemEventSetValue&>(event);
  305.       oss << "The value for "
  306.           << event.getDirectory().getPath()
  307.           << " has been changed from "
  308.           << ToString(set_value_event.getOldValue())
  309.           << " to "
  310.           << ToString(set_value_event.getNewValue());
  311.       break;
  312.     }
  313.     default:
  314.       break;
  315.   }
  316.   return oss.str();
  317. }


  318. int main(int argc, char *argv[]) {
  319.   auto callback_1 = [](const FileSystemEvent &event) {
  320.     std::cout << "Callback 1 has been triggered! The file system event is:\n"
  321.               << "********\n* "
  322.               << FormatEventMessage(event)
  323.               << "\n\n";
  324.   };

  325.   auto callback_2 = [](const FileSystemEvent &event) {
  326.     std::cout << "Callback 2 has been triggered! The file system event is:\n"
  327.               << "********\n* "
  328.               << FormatEventMessage(event)
  329.               << "\n\n";
  330.   };

  331.   FileSystem fs;

  332.   fs.create("/a");
  333.   fs.create("/a/b");

  334.   fs.registerLambdaCallback("/a", callback_1);
  335.   fs.create("/a/c");

  336. // Output:
  337. //
  338. // Callback 1 has been triggered! The file system event is:
  339. // ********
  340. // * A new directory with name "c" has been created under path /a
  341. //

  342.   fs.registerLambdaCallback("/a/c", callback_1);
  343.   fs.registerLambdaCallback("/a/c", callback_2);

  344.   fs.setValue("/a", "123");
  345.   fs.setValue("/a/c", "456");
  346.   fs.setValue("/a", "789");

  347. // Output:
  348. //
  349. // Callback 1 has been triggered! The file system event is:
  350. // ********
  351. // * The value for /a has been changed from NULL to 123
  352. //
  353. // Callback 1 has been triggered! The file system event is:
  354. // ********
  355. // * The value for /a/c has been changed from NULL to 456
  356. //
  357. // Callback 2 has been triggered! The file system event is:
  358. // ********
  359. // * The value for /a/c has been changed from NULL to 456
  360. //
  361. // Callback 1 has been triggered! The file system event is:
  362. // ********
  363. // * The value for /a has been changed from 123 to 789
  364. //

  365.   std::cout << ToString(fs.getValue("/a")) << "\n";
  366.   std::cout << ToString(fs.getValue("/a/b")) << "\n";
  367.   std::cout << ToString(fs.getValue("/a/c")) << "\n";
  368.   std::cout << ToString(fs.getValue("/a/d")) << "\n";

  369. // Output
  370. //
  371. // 789
  372. // NULL
  373. // 456
  374. // NULL
  375. //
  376. }
复制代码

评分

参与人数 2大米 +6 收起 理由
biorainy + 1 赞一个
快乐源泉虎东东 + 5 很有用的信息!

查看全部评分

回复

使用道具 举报

🔗
stellari 2018-11-11 18:15:44 | 只看该作者
全局:
题目没有什么特殊要求的话,callback用std::function实现就可以吧。
回复

使用道具 举报

🔗
 楼主| 快乐源泉虎东东 2018-11-12 02:58:45 | 只看该作者
全局:
magicsets 发表于 2018-11-11 16:39
我根据搜到的地里帖子的描述写了一份代码,不过不太确定原题的一些细节要求,楼主可以参考着看一下Callback ...

感谢层主!我参考一下~
回复

使用道具 举报

🔗
csehao 2019-1-28 06:09:30 | 只看该作者
全局:
magicsets 发表于 2018-11-11 16:39
我根据搜到的地里帖子的描述写了一份代码,不过不太确定原题的一些细节要求,楼主可以参考着看一下Callback ...

为什么能写出这么大一堆...
回复

使用道具 举报

全局:
这道题是oa吗?onsite 白板要从一楼写到三楼那么高吧… 他家onsite是whiteboard还是敲键盘啊
回复

使用道具 举报

全局:
不是吧  45~60分钟写 三百多行?
回复

使用道具 举报

🔗
softarts 2019-4-2 11:34:45 | 只看该作者
全局:
用bind,function,lambda之类
回复

使用道具 举报

🔗
mingyEx 2021-10-17 17:01:37 | 只看该作者
全局:
请问这是第几题,LeetCode 588吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表