是否有一个标志使 istream 仅将制表符视为分隔符?

发布于 2024-12-31 23:01:23 字数 216 浏览 1 评论 0原文

我想让 istream 仅将制表符视为空白。因此,给定“{json : 5}\tblah”,我想将 json 加载到 obj1 中,并将“blah”加载到 obj2 中,代码如下:

is << obj1 << obj2

有没有办法在不将对象加载到字符串中的情况下执行此操作?

I want to make istream consider only tabs as whitespace. So, given "{json : 5}\tblah", I want to load json into obj1 and "blah" into obj2 with code like the following:

is << obj1 << obj2

Is there a way to do this without loading the objects into strings?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鯉魚旗 2025-01-07 23:01:23

是的,在本地集中,制表符是唯一具有空格属性的字符。

困难的部分:创建一个继承自 ctype 的 Facet。然后确保将所有字符设置为非空格(制表符除外)。

#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)

注意:甚至连换行符都不是上面的空白字符。因此,运算符 >> 将读取行尾并忽略它。

Yep in the local set the tab is the only character that has the space attribute.

The hard part: Create a facet that inherits from ctype. Then make sure you set all characters to be not whitespace (except tab).

#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];
};

The easy part: create a locale object that uses the facet and imbue the stream with it:

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";
    }
}

The result:

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

Note: Not even newline is not a whitespace character above. So the operator >> will read across the end of line and ignore it.

空心↖ 2025-01-07 23:01:23

std::getline 怎么样?

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

What about std::getline?

getline(getline(std::cin, obj1, '\t'), obj2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文