[英]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.