C++ 是否可以将 fstream 对象设置为在每次调用 << 时自动写入换行符?

C++ Can an fstream object be set to automatically write a newline on each call to <<?

我创建了一个 fstream 对象来将信息写入文件。 我将字符串写入新文件,如

fStreamObject << "New message.\n";

因为我希望每个 << 都在下一行打印一个字符串。

我希望能够设置一个属性并像

一样拨打电话
fstreamObject << "New message.";

这会将字符串写入下一行。

是否有 flags/settings 允许这样做的 fstream 对象?

我见过不同的文件模式(即 ofstream::in、ofstream::out 等),但找不到自动写入新行的文件模式。另外,我不想编写自己的解决方案。我希望能够使用内置功能。

不,标准 流中没有那种易于配置的功能。

您可能必须将流类型和 fiddle 子类化为 operator<< 才能使其按您想要的方式工作,或者使用某种描述的辅助函数来实现:

fstreamObject << nl("New message.");

(但这并不比只在其中放置 \n 更容易(无论如何对于字符串)。

不,C++ 流不允许这样做。
无法决定一个插入停止和下一个插入开始的位置。
例如,对于自定义类型,它们的流插入器通常被实现为对其他流插入器和成员函数的调用。

可以做的唯一事情就是编写您自己的 class,它委托给您选择的流,然后执行此操作。
不过,那是严格有限的用途。

struct alwaysenter {
     std::ostream& o;
     template<class X> alwaysenter& operator<<(X&& x) {
         o<<std::forward<X>(x);
         return *this;
     }
};

这取决于你所说的 "setting the stream" 是什么意思。如果我们认为这相当广泛,那么答案恰好是 "yes"!

方法如下:

  1. 创建一个流缓冲区,每次刷新时插入一个换行符,即调用 sync() 时。否则它只会转发字符。
  2. 更改文件流的流缓冲区以将此流缓冲区过滤用于文件流的流缓冲区。
  3. 设置标志std::ios_base::unitbuf,在每次[正确编写的]输出操作后导致刷新。

下面是执行此操作的示例代码:

#include <iostream>

class newlinebuf
    : public std::streambuf {
    std::ostream*   stream;
    std::streambuf* sbuf;
    int overflow(int c) { return this->sbuf->sputc(c); }
    int sync() {
        return (this->sbuf->sputc('\n') == std::char_traits::eof() 
                || this->sbuf->pubsync() == -1)? -1: 0;
    }
public:
    newlinebuf(std::ostream& stream)
        : stream(&stream)
        , sbuf(stream.rdbuf(this)) {
        stream << std::unitbuf;
    }
    ~newlinebuf() { this->stream->rdbuf(this->sbuf); }
};

int main() {
    newlinebuf sbuf(std::cout);

    std::cout << "hello" << "world";
}

虽然这种方法有效,但我建议反对使用它!问题是所有复合输出运算符,即那些使用多个输出运算符来完成工作的运算符,都会导致多个换行符。我不知道可以做些什么来防止这种行为。标准库中没有任何东西可以仅配置流来执行此操作:您需要以某种方式插入换行符。