Facet ctype,do_is()和specializations

时间:2014-04-04 21:12:52

标签: c++ iostream

我派生了ctype类来构建我自己的方面,以覆盖其虚函数do_is()。我的目的是使流提取器忽略空格字符(并且仍然在制表字符上进行标记)。这个重写要求实施母班。但它只会与wchar_t一起编译。 ctype::do_is()模板值没有char的实现。对于gcc和VS 2010来说,这是真的。

这是我的代码;你只需要取消注释第5行就可以在两个版本之间进行测试。

#include <iostream>
#include <locale>
#include <sstream>

// #define WIDE_CHARACTERS

#ifdef WIDE_CHARACTERS
typedef wchar_t CharacterType;
std::basic_string<CharacterType> in = L"string1\tstring2 string3";
std::basic_ostream<CharacterType>& consoleOut = std::wcout;
#else
typedef char CharacterType;
std::basic_string<CharacterType> in = "string1\tstring2 string3";
std::basic_ostream<CharacterType>& consoleOut = std::cout;
#endif

struct csv_whitespace : std::ctype<CharacterType>
{
    bool do_is(mask m, char_type c) const
    {  
        if ((m & space) && c == ' ')
        {
            return false; // space will NOT be classified as whitespace
        }

        return ctype::do_is(m, c); // leave the rest to the parent class
    }
};

int main()
{
    std::basic_string<CharacterType> token;

    consoleOut << "locale with modified ctype:\n";
    std::basic_istringstream<CharacterType> s2(in);
    s2.imbue(std::locale(s2.getloc(), new csv_whitespace()));
    while (s2 >> token)
    {
        consoleOut << "  " << token << '\n';
    }
}

2 个答案:

答案 0 :(得分:1)

谢谢!

我从您提供的链接中执行了以下代码,这确实有效。

#include <iostream>
#include <vector>
#include <locale>
#include <sstream>

// This ctype facet declassifies spaces as whitespace
struct CSV_whitespace : std::ctype<char>
{
    static const mask* make_table()
    {
        // make a copy of the "C" locale table
        static std::vector<mask> v(classic_table(), classic_table() + table_size);

        // space will not be classified as whitespace
        v[' '] &= ~space;

        return &v[0];
    }

    CSV_whitespace(std::size_t refs = 0) : ctype(make_table(), false, refs) {}
};

int main()
{
    std::string token;

    std::string in = "string1\tstring2 string3";

    std::cout << "locale with modified ctype:\n";
    std::istringstream s(in);
    s.imbue(std::locale(s.getloc(), new CSV_whitespace()));
    while (s >> token)
    {
        std::cout << "  " << token << '\n';
    }
}

答案 1 :(得分:0)

窄字符流使用表查找进行分类(我认为是优化优势)。您的实现仅适用于char以外的字符类型。您可以在C++ reference page上看到他们如何使用该表对字符进行分类。