有一种简单的方式缩进输出要使用ofstream对象?我有一个C ++字符数组为空终止并且包括换行。我想其输出到流,但与缩进两个空格的每一行。有没有一种简单的方法来做到这一点与流操纵像你可以用特殊的指令整数输出的基改流或做我必须手动处理阵列,并在每个换行符手动插入额外的空格检测?

好像字符串::右()操纵器靠近:

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

感谢。

- 威廉

有帮助吗?

解决方案

这是使用小面的理想情况。

的codecvt小面的定制版本可以浸透到流。

所以,您的使用情况是这样的:

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

小面的定义是略微复杂的。结果 但整个点是使用方面并不需要了解格式化任何人。格式化是如何的流正被使用的应用的独立的。

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

};

请参阅:低于

汤姆的笔记

其他提示

嗯,这不是我要找的答案,但如果没有这样的答案,这里是一个办法做到这一点手动:

void
indentedOutput(ostream &outStream, const char *message, bool &newline)
{
  while (char cur = *message) {
    if (newline) {
      outStream << "  ";
      newline = false;
    }
    outStream << cur;
    if (cur == '\n') {
      newline = true;
    }
    ++message;
  }
}

一个的方式来增加这样的特征将是写一个过滤流缓冲(即,转发IO操作到另一个流缓冲但操纵数据流缓冲转移),其添加压痕作为其滤波操作的一部分。我给写的流缓冲这里一个例子,升压提供的以帮助在该

如果你的情况,溢出()成员将简单地测试“\ n”和然后添加缩进刚过如果需要的话(你在indentedOuput功能都做什么,例外的是newline将是流缓冲的成员)。你也许可以有一个设置,以增加或减少缩进大小(可能通过操纵访问,机械手会做一个dynamic_cast的,以确保关联到流的流缓冲类型正确的;有一种机制来添加用户数据流 - basic_ios :: xalloc,iword和PWORD - 。但在这里,我们要采取行动的streambuf)

我有很好的成功与马丁的的codecvt方面的基础的建议,但我用它的std ::在OSX COUT有问题,因为在默认情况下此流使用基于basic_streambuf流缓冲其忽略魔方面。以下行开关的std :: cout和朋友使用基于basic_filebuf流缓冲,这将使用充满小面。

std::ios::sync_with_stdio(false);

使用相关联的副作用,这是iostream标准流对象可在标准C流中的独立操作。

另外要注意的是,因为这方面没有一个静态的std ::区域:: ID,这意味着调用的std :: has_facet 上总是返回true的语言环境。添加一个std ::意味着当地:: ID的是没有使用的小,因为basic_filebuf长相基类模板。

我广义洛基Astarti的解决方案将工作与任意缩进层次。该解决方案有一个很好的,易于使用的界面,但实际实施是一个有点腥。它可以在github中找到: https://github.com/spacemoose/ostream_indenter

有一个在GitHub库更为复杂的演示,但给出:

#include "indent_facet.hpp"

/// This probably has to be called once for every program:
// http://stackoverflow.com/questions/26387054/how-can-i-use-stdimbue-to-set-the-locale-for-stdwcout
std::ios_base::sync_with_stdio(false);

// This is the demo code:
std::cout << "I want to push indentation levels:\n" << indent_manip::push
          << "To arbitrary depths\n" << indent_manip::push
          << "and pop them\n" << indent_manip::pop
          << "back down\n" << indent_manip::pop
          << "like this.\n" << indent_manip::pop;

}

它产生以下输出:

I want to push indentation levels:
    To arbitrary depths
        and pop them
    back down
like this.

我希望任何反馈作为对代码的效用。

有没有简单的方法,但很多人都写了复杂 的方式来实现这一目标。 读取,从而很好地解释了这篇文章 话题。 这里是另一篇文章,不幸的是,在德国。但 它的源代码应该帮助你。

例如可以编写它记录递归结构的功能。递归的每个层次的缩进被增加:

std::ostream& operator<<(std::ostream& stream, Parameter* rp) 
{
    stream << "Parameter: " << std::endl;

    // Get current indent
    int w = format::get_indent(stream);

    stream << "Name: "  << rp->getName();
    // ... log other attributes as well

    if ( rp->hasParameters() )
    {
        stream << "subparameter (" << rp->getNumParameters() << "):\n";

        // Change indent for sub-levels in the hierarchy
        stream << format::indent(w+4);

        // write sub parameters        
        stream << rp->getParameters();
    }

    // Now reset indent
    stream << format::indent(w);

    return stream; 

}

简单空白操纵

struct Whitespace
{
    Whitespace(int n)
        : n(n)
    {
    }
    int n;
};

std::ostream& operator<<(std::ostream& stream, const Whitespace &ws)
{
    for(int i = 0; i < ws.n; i++)
    {
        stream << " ";
    }
    return stream;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top