【问题标题】:Conditional printing and counting over std::map with restrictions有限制的条件打印和计数 std::map
【发布时间】:2019-12-01 06:57:54
【问题描述】:

我目前正在学习 C++17,作为练习使用标准库以习惯使用这些功能的一部分,我们遇到了挑战:

  1. 迭代std::map<std::string, size_t>(也称为std::map<file_name, file_size>
  2. 打印空文件名size_t == 0 并返回其计数
  3. 打印不为空的文件名size_t != 0 并返回其计数
  4. 从地图中删除 std::pairs whose size_t == 0

限制:

  1. 只能使用标题:<vector><map><string><algorithm><functional>

  2. 无法定义复杂类型或模板

  3. 无法使用. (member access), -> (member access via pointer), * (dereference) operators

  4. 不能使用for, while, do-while nor if-else, switch 和其他条件句

  5. 可以使用std::for_each等函数模板的函数来遍历元素集合

  6. 没有 lambdas

  7. 没有std::coutstd::cerrstd::ostream

  8. 没有自动类型

  9. 可以使用其他函数,只要它们包含在限制 #1 中描述的标头中

允许使用这些功能:

void print(const std::string& str)
{
    std::cout << str << std::endl;
}
std::string split(const std::pair<std::string, size_t> &r)
{
    std::string name;
    std::tie(name, std::ignore) = r;
    return name;
}
bool checkEmpty(const std::pair<std::string, size_t>& r, bool trueIfIsNot
)
{
    file_size size;
    std::tie(std::ignore, size) = r;
    bool result = (size == 0);
    if (trueIfIsNot)
    {
        result = !result;
    }
    return result;
}

我已经开始欣赏在我之前的帖子中使用std::bindstd::for_each。这一次,我如何添加谓词和条件来修改输出而不使用限制 #4 规定的语法?

我目前正在考虑使用std::transform()std::copy_if() 等。我对标准库的许多功能有一些了解,但我认为我在语法方面很弱,无法理解事物如何协同工作,所以我不知道如何使用它们。

【问题讨论】:

    标签: c++ c++17 predicate stdmap c++-standard-library


    【解决方案1】:

    对于 2,3 任务你可以做:

    • 使用vector,初始大小为地图大小
    • 使用copy_if根据条件从地图复制元素
    • 使用for_each 有界split/print
    • 返回项数作为向量中第一项和最后一项之间的差异

    代码:

    int task2and3(const std::map<std::string,int>& m, bool trueIfIsNot)
    {
        std::vector<std::pair<std::string,int>> vec(m.size());
        auto firstPastEnd = std::copy_if(m.begin(),m.end(),vec.begin(),
            std::bind(checkEmpty,std::placeholders::_1,trueIfIsNot));
    
        std::for_each(vec.begin(), firstPastEnd, 
            std::bind(print,std::bind(split,std::placeholders::_1)));
    
        return firstPastEnd - vec.begin();
    }
    

    trueIfIsNot 表示要打印哪些对(值为 0 或其他值)。


    要执行第 4 项任务,您还可以使用 vector 来存储 map 的项目。要从地图中删除元素,您可以遍历向量中的这些项目(使用for_each)并调用map::erase 方法。因为这个函数成员有重载,你需要正确地转换它以通过key_type 指示删除元素的方法。使用split 从pair 中获取这个key_type

    void task4(std::map<std::string,int>& m)
    {
        std::vector<std::pair<std::string,int>> vec(m.size());
        auto firstPastEnd = std::copy_if(m.begin(),m.end(),vec.begin(),std::bind(checkEmpty,std::placeholders::_1,false));
    
        using sizeType = std::map<std::string,int>::size_type;
        using keyType = std::map<std::string,int>::key_type;
    
        for_each(vec.begin(), firstPastEnd, 
            std::bind( static_cast<sizeType (std::map<std::string,int>::*)(const keyType&) >(&std::map<std::string,int>::erase),
            &m,
            std::bind(split,std::placeholders::_1)) );
    }
    

    Full demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-16
      • 2014-11-10
      • 1970-01-01
      相关资源
      最近更新 更多