繁体   English   中英

使用 istream_iterator 从文件中读取 bitset

[英]Read bitset from file using istream_iterator

我正在尝试将文本文件读入 std::bitset-objects 的向量中。 该文件由 1 和空格(用于指示 0 或 false)组成,我试图通过重载输入运算符 >> 和使用 istream_iterators 来做到这一点。 我首先将字符串中的空格更改为 0,然后构造一个位,然后将其推送到包含该字符串的向量。 但是,当我打印 output 时,它看起来很奇怪,而且我读取的元素似乎多于文件中的行(位集向量长于行数)。 代码如下所示:

  
  template<long unsigned int N>
  std::istream& operator>>(std::istream& is, std::bitset<N>& b){
    std::string line;
    std::getline(is,line);
    for(unsigned long int i =0;i<N;++i){line[i]==' '? line[i]='0':'1';};
    std::cout << line << std::endl;
    b = std::bitset<N>(line);
    return is;
  }
 
 int main(){
  const unsigned long int N = 40;
  std::ifstream file("activities.txt");
  std::istream_iterator<std::bitset<N>> begin(file),end;
  std::vector<std::bitset<N>> bits;
  
  for(auto it = begin;it!=end;++it){
    bits.push_back(*it);
  }
  
  for(auto bit: bits){ std::cout << bit << std::endl;}
 }

我在不使用 istream_iterator 和 operator>> 重载的情况下成功地做了同样的事情,但我只是想弄清楚为什么这种方式不起作用。

有趣的问题。

发生这种情况的原因是std::bitset已经有一个被覆盖的提取运算符>> 请看这里 您可以读到它的行为类似于格式化输入 function。因此,它将读取到下一个空白,然后停止。 如果我们有一个“文件结尾”或直到它达到定义的std::bitset的长度,它将结束读取。

不小心你的源文件中有空格,它将作为这个格式化输入 function 的分隔符,并且不会导致任何问题。

实际上,您应该在std::vector中看到很多“位集”,它们都由许多开头的前导“0”和结尾的几个不同长度的“1”组成。

这是读取许多“1”岛并用“0”填充左侧字符串的结果,因此最终的位集有 40 个字符。

如果你想让 C++ 调用你的 function,你需要打开std -命名空间。 虽然可以做到,但强烈建议不要这样做,模板特化除外。 看:

不推荐

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <bitset>
#include <vector>

constexpr unsigned long int N = 40;
namespace std {
    template<long unsigned int N>
    std::istream& operator>>(std::istream& is, std::bitset<N>& b) {
        std::string line;
        std::getline(is, line);
        for (unsigned long int i = 0; i < N; ++i) { line[i] == ' ' ? line[i] = '0' : '1'; };
        std::cout << line << std::endl;
        b = std::bitset<N>(line);
        return is;
    }
}

int main() {

    std::ifstream file("activities.txt");
    std::istream_iterator<std::bitset<N>> begin(file), end;
    std::vector<std::bitset<N>> bits;

    for (auto it = begin; it != end; ++it) {
        bits.push_back(*it);
    }

    for (auto& bit : bits) { std::cout << bit << std::endl; }
}

这基本上可以工作。 但是,不应使用。 此外,在我看来,通过与“N”而不是“line.length()”进行比较, >>运算符的 for 循环中存在语义错误,后者会更好。 因为,如果一行超过40个字符,空格将不会被转换,停留在' '(空格)并导致无效输入的异常。

更正这一点(无论如何,一行中较长的字符串将被截断)并使用“std”命名空间中允许的模板特化,您可以这样写:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <bitset>
#include <vector>

constexpr unsigned long int N = 40;
namespace std {

    template<>
    std::istream& operator>>(std::istream& is, std::bitset<N>& b) {
        std::string line;
        std::getline(is, line);
        for (unsigned long int i = 0; i < line.length(); ++i) { line[i] == ' ' ? line[i] = '0' : '1'; };
        //std::cout << line << std::endl;
        b = std::bitset<N>(line);
        return is;
    }
}

int main() {

    std::ifstream file("activities.txt");
    std::istream_iterator<std::bitset<N>> begin(file), end;
    std::vector<std::bitset<N>> bits;

    for (auto it = begin; it != end; ++it) {
        bits.push_back(*it);
    }

    for (auto& bit : bits) { std::cout << bit << std::endl; }
}

这行得通。


通过利用std::bitset构造函数 3可以将空格解释为 0,您可以让您的生活变得更加简单。

并且,请使用std::vector s range constructor (number 5)

这样,代码将更加简单:

#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <bitset>
#include <vector>

constexpr unsigned long int N = 40;
namespace std {

    template<>
    std::istream& operator>>(std::istream& is, std::bitset<N>& b) {
        std::string line;
        std::getline(is, line);
        b = std::bitset<N>(line, 0, N, ' ', '1');
        return is;
    }
}

int main() {

    std::ifstream file("activities.txt");

    std::vector<std::bitset<N>> bits(std::istream_iterator<std::bitset<N>>(file), {});

    for (auto& bit : bits) { std::cout << bit << std::endl; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM