文字じゃねぇ

comment で istream に std::noskipws manipulator を流し込むか std::istream::unsetf() に std::ios_base::skipws を指定しろと教えてもらったので ( http://togetter.com/li/30132 ) そっちで。ありがとう id:melpon と zakkas783 さん。

自前 library に raw_type を追加してみた。

char は character の略なんだなぁとつくづく思う瞬間。

#include <algorithm>
#include <iostream>
#include <iterator>
#include <fstream>

int main(const int argc, const char* const argv[]) {
    if (argc < 3) {
        std::cerr << "specify two file\n";
        return 1;
    }

    std::ifstream fin(argv[1], std::ios_base::binary);
    if (!fin.good()) {
        std::cerr << "bad file: " << argv[1] << "\n";
        return 1;
    }
    std::ofstream fout(argv[2], std::ios_base::binary | std::ios_base::trunc);

    std::istream_iterator<char> iitr(fin), end;
    std::ostream_iterator<char> oitr(fout);
    std::copy(iitr, end, oitr);

    return 0;
}

上記の code は ( ちょっと回りくどいけど ) command line に指定した file を copy する処理「だと思って書いたもの」。ところが実際にこれを実行すると空白文字 ( 多分 printable じゃないものも ) が飛ばされて copy される。これは default の抽出子 ( operator>>() ) がそういったものをはじく処理をしているからだと思うんだけど ( つまり fin から読み込まれる時点でもうダメ ) これはつまり char 型は文字型であって access しやすい data の最小単位ではないということだよな。

で、これを何とかしたい。というわけで以下のような型を定義することで何とかしてみた。

struct raw_type { char c; };
std::istream& operator >>(std::istream& in, raw_type& r) {
    return in.get(r.c);
}
std::ostream& operator <<(std::ostream& out, const raw_type& r) {
    return out.put(r.c);
}

これで以下の code が意図通りに動く。

    std::istream_iterator<raw_type> iitr(fin), end;
    std::ostream_iterator<raw_type> oitr(fout);
    std::copy(iitr, end, oitr);

typedef だと char 用の抽出子が呼ばれてしまってどうにもならんのでガワをかぶせてみたんだけどこれもうちっと smart に何とかならんもんかな。