Replace cout<<“string” with cout<<“string”<<endl in cpp

故事扮演 提交于 2019-12-13 09:02:45

问题


I want to replace each cout occurring in a program with same but concatenated with endl. I'm trying to use macros for this but unable to figure that out how to do that. Please help!

Is there a way to get complete line written in program and just concat << endl with it? Note if endl is already written by programmer, no endl will be concatenated.

If any other better method possible, please suggest.


回答1:


Unfortunately, this is possible. But in no sense can I condone it.

#include <iostream>

namespace std
{
class not_actually_cout{};

template<typename T>
not_actually_cout& operator<< (not_actually_cout& stream, const T & v)
{
    std::cout << v << std::endl;
    return stream;
}

not_actually_cout not_actually_cout_instance;
}

#define cout not_actually_cout_instance

int main(void)
{
    cout << "why god why";
    cout << "please no";
    return 0;
}

Outputs:

why god why
please no



回答2:


Just make a function template:

template<typename T>
void printLn(T const & v, std::ostream & os = std::cout)
{
    os << v << std::endl;
}

If you wanna get fancy with it and allow multiple arguments, and C++11 is available to you:

void printLn(std::ostream & os)
{
    os << std::endl;
}

template<typename T, typename... Args>
void printLn(std::ostream & os, T const & v, Args&&... args)
{
    os << v;
    printLn(os, std::forward<Args>(args)...);
}



回答3:


What are you really interested in? The newline after each output operation or the flush? Note that the flush is really expensive, though.

The easiest way to have a flush injected after each output operation is to set the flags std::ios_base::unitbuf (this is the default setting for std::cerr):

std::cout << std::unitbuf;

After this operation, you'll get a flush after each individual output operation, e.g.

std::cout << "hello" << ' ' << "world\n";

would cause three flushes. To automatically also insert a newline, you could set up a filtering stream buffer which adds a newline (optionally if there wasn't one) upon flushing the stream. This would amount to overwriting the overflow() and sync() functions of a std::streambuf and installing the corresponding stream buffer into std::cout in addition to setting std::unitbuf. With these changes, no source change would be needed.

The code below demonstrates a corresponding filtering stream buffer:

#include <iostream>
#include <streambuf>

class newlinebuf
    : public std::streambuf
{
    enum { s_size = 64 };
    std::ostream&   d_stream;
    std::streambuf* d_sbuf;
    char            d_buffer[s_size];
public:
    newlinebuf(std::ostream& stream)
        : d_stream(stream)
        , d_sbuf(stream.rdbuf(this))
    {
        this->setp(this->d_buffer, this->d_buffer + s_size - 1);
    }
    ~newlinebuf() {
        if (this->d_stream.rdbuf() == this) {
            this->d_stream.rdbuf(this->d_sbuf);
        }
    }
    int overflow(int c) { // clear the buffer without flushing
        std::streamsize size(this->pptr() - this->pbase());
        std::streamsize n(this->d_sbuf->sputn(this->pbase(), size));
        if (n == 0) { // no progress => error
            return std::char_traits<char>::eof();
        }
        std::copy(this->pbase() + n, this->pbase() + size, this->pbase());
        this->setp(this->d_buffer, this->d_buffer + s_size);
        this->pbump(size - n);
        if (c != std::char_traits<char>::eof()) {
            *this->pptr() = std::char_traits<char>::to_char_type(c);
            this->pbump(1);
        }
        return std::char_traits<char>::not_eof(c);
    }
    int sync() {
        if (this->pptr() == this->pbase() || this->pptr()[-1] != '\n') {
            *this->pptr() = '\n';
            this->pbump(1);
        }
        return this->overflow(std::char_traits<char>::eof())
            == std::char_traits<char>::eof()? -1: 0;
    }
};

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

    std::cout << "hello" << "_" << "world\n" << "next line";
}

Based on the comment I realize that this is probably not what you want but I'm not aware of a portable technique which just uses the preprocessor and/or the compiler to add newlines.




回答4:


Try to use regular expressions. All modern languages has support for them.

Also, for example, if your program not so big, you can try to use SublimeText editor. It has very smart tools for replacement, which supports regex.



来源:https://stackoverflow.com/questions/19103683/replace-coutstring-with-coutstringendl-in-cpp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!