【问题标题】:std::map with Filename as key and Filedescriptor as Valuestd::map 以 Filename 作为键, Filedescriptor 作为 Value
【发布时间】:2023-03-16 21:15:01
【问题描述】:

我正在遍历一个向量,向量中的每个条目都必须根据条目写入文件。

假设向量 {File A, File B, File C, File A....}

因此,打开了多个文件描述符,我将它们存储在 std::map:

键 = 文件名,值 = 文件描述符。请参阅下面的代码。

当在地图中找不到文件名时,我会在地图中插入一对数据(文件名、文件描述符)。编译器抛出错误。在代码后面查看错误详情。

std::map <std::string, std::ofstream> filemap; // maintains filename for each item in the list.

std::vector <std::string> items;

for (i=0 ; i < items.size() ; i++) {

  if (keyfilemap.find(items[i]) == keyfilemap.end()) {
      std::ofstream ofs (items(i), std::ofstream::out);
      ofs << key.first << "-" << key.second << std::endl;
      // **Compiler throws an error here.**
      keyfilemap.insert(std::make_pair(filename, ofs));
        
  }
  else 
     keyfilemap[filename] << key.first << "-" << key.second << std::endl;
}

编译器错误。

/usr/include/c++/7/bits/stl_pair.h:529:14: error: no matching function for call to 'std::pair<std::__cxx11::basic_string<char>, std::basic_ofstream<char> >::pair(std::__cxx11::basic_string<char>&, std::basic_ofstream<char>&)'
       return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));

【问题讨论】:

  • 请提供minimal reproducible example。当前代码似乎不完整,存在未定义符号错误。
  • std::make_pair(filename, ofs) 创建ofs副本。如前所述,不能复制。
  • 您在上面的代码中有文件名。 items[i], items(ii) 和 filename...哪个是正确的?
  • 如何使用移动?我在下面尝试过,但没有成功。
  • keyfilemap.insert(std::move(std::make_pair(filename, ofs)));

标签: c++ c++11


【解决方案1】:

C++ 流类不可复制,但您在为insert() 构建std::pair 时尝试进行复制。这就是代码无法编译的原因。

您必须直接在地图内构造std::ofstream 对象,或者至少使用移动语义将所有权转移到地图中,例如:

std::map<std::string, std::ofstream> filemap;
std::vector<std::string> items;
...
for (const auto &filename : items) {
  auto iter = filemap.find(filename);
    if (iter == filemap.end()) {
        iter = filemap.emplace(filename, filename).first;
        // or:
        // iter = filemap.emplace(make_pair(filename, ofstream(filename))).first;
        // or:
        // std::ofstream ofs(filename);
        // iter = filemap.insert(std::make_pair(filename, std::move(ofs))).first; 
    }
    iter->second << key.first << "-" << key.second << std::endl;
}

或者,让std::map默认为你构造std::ofstream对象,然后你可以在需要时open()它们,例如:

std::map<std::string, std::ofstream> filemap;
std::vector<std::string> items;
...
for (const auto &filename : items) {
    auto &ofs = filemap[filename];
    if (!ofs.is_open()) {
        ofs.open(filename);
    }
    ofs << key.first << "-" << key.second << std::endl;
}

【讨论】:

    【解决方案2】:

    这也许是您想要实现的目标吗?:

    #include <fstream>
    #include <string>
    #include <unordered_map>
    
    int main()
    {
        std::unordered_map<std::string, std::ios_base::openmode> fname_to_fstream_pairs = {{"vacation.png", std::ofstream::out}, {"diary.txt", std::ofstream::in}};
    
        auto const& fname_to_fstream_pair = fname_to_fstream_pairs.find("vacation.png");
    
        if (fname_to_fstream_pair != std::end(fname_to_fstream_pairs))
        {
            std::ofstream ofs(fname_to_fstream_pair->first, fname_to_fstream_pair->second);
            ofs << "The vacation was great!";
        }
    
        return 0;
    }
    

    std::end 表示超出容器末尾的元素。 所以,通常it == std::end(v) 不是你想要的。

    PS:哦,你不应该那样写照片。这只是一个愚蠢的例子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-06
      • 2011-06-23
      • 1970-01-01
      • 2015-03-04
      • 2010-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多