ファイルストリームから読み取るように「cin」をリダイレクトしましたcin.rdbug(inF.rdbug())
抽出演算子を使用すると、空白文字に達するまで読み取ります。
別の区切り文字を使用することはできますか? cplusplus.comのapiを調べましたが、何も見つかりませんでした。
cin
または他の std::istream
のワード間区切り文字を変更することは、 std::ios_base::imbue
を使用して可能です。 カスタムを追加するには ctype
facet
。
/ etc/passwd形式のファイルを読み取る場合、次のプログラムは各:
区切りのWordを個別に読み取ります。
#include <locale>
#include <iostream>
struct colon_is_space : std::ctype<char> {
colon_is_space() : std::ctype<char>(get_table()) {}
static mask const* get_table()
{
static mask rc[table_size];
rc[':'] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
int main() {
using std::string;
using std::cin;
using std::locale;
cin.imbue(locale(cin.getloc(), new colon_is_space));
string Word;
while(cin >> Word) {
std::cout << Word << "\n";
}
}
文字列の場合、 std::getline
異なる区切り文字を使用して読み込むオーバーロード。
数字の抽出では、区切り文字は実際には「空白」ではなく、数字で無効な文字です。
これは Robᵩ の答えの改善です。なぜなら、それは正しいものだからです(受け入れられなかったことに失望しています)。
必要なことは、ctype
が調べる配列を変更して、区切り文字を決定することです。
最も簡単なケースでは、独自に作成できます。
const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};
私のマシンでは'\n'
は10です。配列の要素に区切り値ctype_base::space
を設定しました。 ctype
で初期化されたfoo
は、'\n'
または' '
ではなく、'\t'
でのみ区切られます。
ctype
に渡される配列は、区切り文字だけでなく、文字、数字、記号、およびストリーミングに必要なその他のジャンクも定義するため、これが問題になります。 ( Ben Voigt の答えはこれに触れる。)だから私たちが本当にやりたいことはmodifya mask
、ゼロから作成しないでください。
これは次のように実現できます。
const auto temp = ctype<char>::classic_table();
vector<ctype<char>::mask> bar(temp, temp + ctype<char>::table_size);
bar[' '] ^= ctype_base::space;
bar['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
bar[':'] |= ctype_base::space;
ctype
で初期化されたbar
は、'\n'
および':'
で区切られますが、' '
または'\t'
では区切られません。
次のようにカスタムcin
を使用するために、istream
または他のctype
をセットアップします。
cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));
ctype
sを切り替えることもでき、動作は途中で変更されます:
cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));
デフォルトの動作に戻す必要がある場合は、次のようにします。
cin.imbue(locale(cin.getloc(), new ctype<char>));
これはJonの答えの改善であり、 cppreference.com の例です。したがって、これは両方と同じ前提に従いますが、それらをパラメーター化された区切り文字と組み合わせます。
struct delimiter_ctype : std::ctype<char> {
static const mask* make_table(std::string delims)
{
// make a copy of the "C" locale table
static std::vector<mask> v(classic_table(), classic_table() + table_size);
for(mask m : v){
m &= ~space;
}
for(char d : delims){
v[d] |= space;
}
return &v[0];
}
delimiter_ctype(std::string delims, ::size_t refs = 0) : ctype(make_table(delims), false, refs) {}
};
乾杯!