簡體   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