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