Есть ли флаг, чтобы istream рассматривал только вкладки как разделители? - PullRequest
1 голос
/ 31 января 2012

Я хочу, чтобы istream рассматривал только табуляцию как пробел. Итак, учитывая "{json: 5} \ tblah", я хочу загрузить json в obj1 и "blah" в obj2 с кодом, подобным следующему:

is << obj1 << obj2

Есть ли способ сделать это без загрузки объектов в строки?

Ответы [ 2 ]

1 голос
/ 01 февраля 2012

Да в локальном наборе вкладка является единственным символом, который имеет атрибут пробела.

Сложная часть: создайте фасет, который наследуется от ctype.Затем убедитесь, что все символы не пропущены (кроме табуляции).

#include <locale>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>    

// This is my facet:
// It is designed to treat only <tab> as whitespace
class TabSepFacet: public std::ctype<char>
{
    public:
        typedef std::ctype<char>   base;
        typedef base::char_type    char_type;

        TabSepFacet(std::locale const& l) : base(table)
        {
            // Get the ctype facet of the current locale
            std::ctype<char> const&  defaultCType = std::use_facet<std::ctype<char> >(l);

            // Copy the default flags for each character from the current facet
            static char data[256];
            for(int loop = 0; loop < 256; ++loop) {data[loop] = loop;}
            defaultCType.is(data, data+256, table);

            // Remove the other spaces
            for(int loop = 0; loop < 256; ++loop)
            {
                // If the space flag is set then XOR it out.
                if (table[loop] & base::space)
                {   table[loop] ^= base::space;
                }
            }
            // Only a tab is a space
            table['\t'] |= base::space;
        }
    private:
        base::mask table[256];
};

Простая часть: создайте объект языкового стандарта, который использует фасет, и наполните им поток:

int main()
{
    // Create a stream (Create the locale) then imbue the stream.
    std::stringstream data("This is a\tTab");
    const std::locale tabSepLocale(data.getloc(), new TabSepFacet(data.getloc()));
    data.imbue(tabSepLocale);

    // Note: If it is a file stream then imbue the stream BEFORE opening a file,
    // otherwise the imbue is silently ignored on some systems.


    // Now you can use the stream like normal; your locale defines what 
    // is whitespace, so the operator `>>` will split on tab.
    std::string   word;
    while(data >> word)
    {
        std::cout << "Word(" << word << ")\n";
    }
}

Результат:

> g++ tab.cpp
> ./a.out
Word(This is a)
Word(Tab)

Примечание: Даже символ перевода строки не является пробелом выше.Поэтому оператор >> будет читать через конец строки и игнорировать его.

0 голосов
/ 31 января 2012

А как же std::getline?

getline(getline(std::cin, obj1, '\t'), obj2);
...