如何轻松缩进输出到ofstream?

Wil*_*mKF 17 c++ stream ofstream

是否有一种简单的方法可以将输出缩进到ofstream对象?我有一个C++字符数组,它是null终止并包含换行符.我想将它输出到流中,但是用两个空格缩进每一行.有没有一种简单的方法可以使用流操纵器来执行此操作,例如您可以使用特殊指令更改整数输出的基础,或者我是否必须手动处理数组并在检测到的每个换行符时手动插入额外的空格?

看起来像string :: right()操纵器是关闭的:

http://www.cplusplus.com/reference/iostream/manipulators/right/

谢谢.

-威廉

Mar*_*ork 21

这是使用方面的完美情况.

codecvt facet的自定义版本可以嵌入到流中.

所以你的用法看起来像这样:

int main()
{
    /* Imbue std::cout before it is used */
    std::ios::sync_with_stdio(false);
    std::cout.imbue(std::locale(std::locale::classic(), new IndentFacet()));

    std::cout << "Line 1\nLine 2\nLine 3\n";

    /* You must imbue a file stream before it is opened. */
    std::ofstream       data;
    data.imbue(indentLocale);
    data.open("PLOP");

    data << "Loki\nUses Locale\nTo do something silly\n";
}
Run Code Online (Sandbox Code Playgroud)

方面的定义稍微复杂一些.
但重点是使用facet的人不需要知道格式化的任何信息.应用格式不依赖于流的使用方式.

#include <locale>
#include <algorithm>
#include <iostream>
#include <fstream>

class IndentFacet: public std::codecvt<char,char,std::mbstate_t>
{
  public:
   explicit IndentFacet(size_t ref = 0): std::codecvt<char,char,std::mbstate_t>(ref)    {}

    typedef std::codecvt_base::result               result;
    typedef std::codecvt<char,char,std::mbstate_t>  parent;
    typedef parent::intern_type                     intern_type;
    typedef parent::extern_type                     extern_type;
    typedef parent::state_type                      state_type;

    int&    state(state_type& s) const          {return *reinterpret_cast<int*>(&s);}
  protected:
    virtual result do_out(state_type& tabNeeded,
                         const intern_type* rStart, const intern_type*  rEnd, const intern_type*&   rNewStart,
                         extern_type*       wStart, extern_type*        wEnd, extern_type*&         wNewStart) const
    {
        result  res = std::codecvt_base::noconv;

        for(;(rStart < rEnd) && (wStart < wEnd);++rStart,++wStart)
        {
            // 0 indicates that the last character seen was a newline.
            // thus we will print a tab before it. Ignore it the next
            // character is also a newline
            if ((state(tabNeeded) == 0) && (*rStart != '\n'))
            {
                res                 = std::codecvt_base::ok;
                state(tabNeeded)    = 1;
                *wStart             = '\t';
                ++wStart;
                if (wStart == wEnd)
                {
                    res     = std::codecvt_base::partial;
                    break;
                }
            }
            // Copy the next character.
            *wStart         = *rStart;

            // If the character copied was a '\n' mark that state
            if (*rStart == '\n')
            {
                state(tabNeeded)    = 0;
            }
        }

        if (rStart != rEnd)
        {
            res = std::codecvt_base::partial;
        }
        rNewStart   = rStart;
        wNewStart   = wStart;

        return res;
    }

    // Override so the do_out() virtual function is called.
    virtual bool do_always_noconv() const throw()
    {
        return false;   // Sometime we add extra tabs
    }

};
Run Code Online (Sandbox Code Playgroud)

请参阅:Tom的笔记如下