使用 istream_iterator 从文件中读取位集
Read bitset from file using istream_iterator
我正在尝试将文本文件读入 std::bitset 对象的向量中。该文件由 1 和空格(用于指示 0 或 false)组成,我试图通过重载输入运算符 >> 并使用 istream_iterators 来做到这一点。我首先将字符串中的空格更改为 0,然后构造一个位,然后将其推送到包含该字符串的向量。但是,当我打印输出时,输出看起来很奇怪,似乎我读取的元素多于文件中的行(位集的向量长于行数)。代码如下所示:
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 和重载运算符>>的情况下成功地做了同样的事情,但我只是想弄清楚为什么这种方法不起作用。
有趣的问题。
发生这种情况的原因是 std::bitset
已经有一个被覆盖的提取运算符 >>
。请参阅 here。你可以读到它的行为就像一个格式化的输入函数。所以,它会一直读到下一个白色 space 然后停止。如果我们有一个“文件结尾”或直到它达到定义的 std::bitset
.
的长度,它将结束读取
不小心你的源文件中有 spaces,它将作为这个格式化输入函数的分隔符,不会导致任何问题。
实际上,您应该在 std::vector
中看到很多“位集”,所有这些都由许多开头的前导“0”和结尾的几个不同长度的“1”组成。
这是读了很多'1'岛,然后用'0'填充左边的字符串的结果,这样最后的bitset有40个字符。
如果你想让C++调用你的函数,你需要打开std
-namespace。虽然可以做到,但强烈建议不要这样做,模板特化除外。参见:
不推荐:
#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; }
}
这基本上可以工作。但是,不应使用。此外,在我看来,>>
-运算符的 for 循环中存在语义错误,通过与“N”而不是“line.length()”进行比较,后者会更好。因为,如果一行超过 40 个字符,space 将不会被转换,停留在 ' ' (space) 并导致无效输入异常。
更正(在任何情况下,一行中较长的字符串将被截断)并在“std”名称中使用允许的模板特化space,你可以写:
#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
s constructor number 3 可以将 spaces 解释为 0es,您可以让生活变得更简单。
并且,请使用 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; }
}
我正在尝试将文本文件读入 std::bitset 对象的向量中。该文件由 1 和空格(用于指示 0 或 false)组成,我试图通过重载输入运算符 >> 并使用 istream_iterators 来做到这一点。我首先将字符串中的空格更改为 0,然后构造一个位,然后将其推送到包含该字符串的向量。但是,当我打印输出时,输出看起来很奇怪,似乎我读取的元素多于文件中的行(位集的向量长于行数)。代码如下所示:
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 和重载运算符>>的情况下成功地做了同样的事情,但我只是想弄清楚为什么这种方法不起作用。
有趣的问题。
发生这种情况的原因是 std::bitset
已经有一个被覆盖的提取运算符 >>
。请参阅 here。你可以读到它的行为就像一个格式化的输入函数。所以,它会一直读到下一个白色 space 然后停止。如果我们有一个“文件结尾”或直到它达到定义的 std::bitset
.
不小心你的源文件中有 spaces,它将作为这个格式化输入函数的分隔符,不会导致任何问题。
实际上,您应该在 std::vector
中看到很多“位集”,所有这些都由许多开头的前导“0”和结尾的几个不同长度的“1”组成。
这是读了很多'1'岛,然后用'0'填充左边的字符串的结果,这样最后的bitset有40个字符。
如果你想让C++调用你的函数,你需要打开std
-namespace。虽然可以做到,但强烈建议不要这样做,模板特化除外。参见:
不推荐:
#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; }
}
这基本上可以工作。但是,不应使用。此外,在我看来,>>
-运算符的 for 循环中存在语义错误,通过与“N”而不是“line.length()”进行比较,后者会更好。因为,如果一行超过 40 个字符,space 将不会被转换,停留在 ' ' (space) 并导致无效输入异常。
更正(在任何情况下,一行中较长的字符串将被截断)并在“std”名称中使用允许的模板特化space,你可以写:
#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
s constructor number 3 可以将 spaces 解释为 0es,您可以让生活变得更简单。
并且,请使用 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; }
}