2010-06-08 2 views
8

Ребятам было бы трудно написать coutn, который в основном помещал символ новой строки в конец ввода. Во время работы с консолью (это все, что я могу сделать в данный момент) мне очень сложно писать «\ n» каждый раз, когда я хочу, чтобы линия была новой строкой.
Возможно, это уже реализовано?Лучше cout a.k.a coutn;

+2

Что за утомительное использование '\ n' или' endl', когда вы хотите, чтобы выводилась новая строка? –

+2

Два персонажа .... утомительно? –

+2

@James Довольно утомительно, что я должен это написать. Я не знаю, как большинство пользователей, но когда у меня есть строка, начинающаяся с cout почти в 100% случаев, эта строка заканчивается на \ n, поэтому было бы неплохо, если бы мне не приходилось писать ее каждый раз. Вместо этого я бы хотел ввести coutn. –

ответ

11

Чтобы обойти множественные инъекции в одной строке, вы можете использовать временный объект. Этот временный объект добавит '\ n' в свой деструктор.

struct coutn { 
    coutn(): os(cout) {} 
    ~coutn() { os << '\n'; } 
    template <typename T> 
     coutn & operator<<(T const & x) { os << x; return *this; } 
private: 
    ostream &os; 
}; 

coutn() << "Hello " << "World" << "!"; 

В конце концов, мне интересно, если это на самом деле coutnлучше?

+0

+1: Соблюдение желания, несмотря на это, это лучший способ выполнить это. –

+0

+1 Это была та же идея, что и у меня (за исключением того, что вы отправили 20 секунд передо мной) – Yacoby

+5

Хм ... кажется странным заменять два символа «\ n» тремя «n» (...) на ответ, вопрос изначально просят что-то глупое) –

1

Способ, которым работают потоки, заключается в том, что они добавляют одну вещь, а затем возвращаются.

так вы уверены, что хотите делать то, что вы просите?

Например:

< < сек "а" < < "б";

Поставил бы:

в
б

Конечно, вы можете найти способ с какой оберткой, но дополнительными накладными расходами, понесенных и уменьшенной читаемостью кода я не думаю, что это стоило того. Большинство кодеров знакомы со стандартным C++. Большинство кодеров не знакомы с вашим coutn и как он работает.

+0

@Bondy -1 Нет, вы НЕПРАВИЛЬНО. Вы используете n \ n вместо endl. В большинстве случаев все равно. –

+2

std :: endl и '\ n' - это две разные вещи. std :: endl также очищает поток, который не всегда нужен. – Yacoby

+0

Это ужасный совет. 'std :: endl' провоцирует поток к выходу (что эквивалентно' std :: cout.flush() '), что означает, что вы теряете преимущество буферизации. Вы используете только 'std :: endl', когда хотите« мгновенную »обратную связь, остальное время вы используете' \ n', потому что вам нужен только символ новой строки. –

2

Грубо:

struct StreamFilterN 
{ 
    ostream & os; 
    StreamFilterN(ostream & os_) : os(os_) {} 

    template <typename T> 
    StreamFilterN & operator<<(T const & x) { os << x << "\n"; return *this; } 
} 


StreamFilterN coutn(cout); 
coutn << "Hello world"; 
coutn << "Yeah, like."; 

(я не уверен, если это работает отлично, но это поможет вам начать)

+1

У нас была такая же идея ... хотя в вашем ответе нет '' \ n''? –

+0

+1 Даже если там должно быть os << '\ n'; прежде чем возвращать поток снова, это решение, которое я считаю самым приятным. – Christian

+0

Я бы добавил «явный» в конструктор – sellibitze

4

Ну, первое очевидно, что было бы реализовать какой-то обертки вокруг это:

class Print 
{ 
public: 
    explicit Print(std::ostream& stream = std::cout): mStream(stream) {} 
    ~Print() { mStream << '\n'; } 

    template <class T> 
    Print& operator<<(T const& t) { mStream << t; return *this; } 

private: 
    std::ostream& mStream; 
}; 

Использование, как например:

int main(int argc, char* argv[]) 
{ 
    Object object; 
    Print() << "My new object value: " << object; 

    std::ofstream file("file.log"); 
    Print(file) << "My new object value: " << object; 
} 

Легко, Peasy.

+4

Да. Давайте заменим утомительные два дополнительных символа на заголовочный файл, две функции, функцию шаблона, класс, а затем потребуем больше двух символов, если кто захочет его использовать: \ –

+0

Да, почему бы и нет? Во всяком случае это необходимо: #define coutn Распечатать() для заполнения. – Shiroko

+0

Не забудьте '#define coutn Print()' – Gabe

1

Приходите один человек. Вы должны признать, что новые строки C++ слишком многословны. Посмотрите на C#, D, Java, Python, Ruby, я должен продолжать? Я не думаю, что вы должны реализовать coutn. Я думаю, вам будет лучше после D's example с write, writeln, writef, и writefln функции вариационного шаблона.

В любом случае, вот как это сделать без макросов и без необходимости явно создавать временные файлы.

class coutn_t 
{ 
private: 
    class newliner 
    { 
    public: 
     explicit newliner(std::ostream & out=std::cout) : m_out(out) { } 

     template<typename T> 
     newliner& operator<<(const T& t) 
     { 
     m_out << t; 
     return *this; 
     } 
     ~newliner() { m_out << std::endl; } 
    private: 
     std::ostream & m_out; 
    }; 
public: 
    // NOTE: these return by value. Only one newliner will be 
    // destructed however as RVO will eliminate the copy. 

    newliner operator()(std::ostream& out) 
    { return newliner(out); } 

    template< typename T > 
    newliner operator<<(const T& t) 
    { 
     std::cout << t; 
     return newliner(std::cout); 
    } 
}; 

coutn_t coutn; 

coutn << "Hello World!"; 

coutn << "Hello " << "World" << '!'; 

std::ofstream file("ouput.txt"); 
coutn(file) << "Hello World" << " via file"; 

Комплексное решение будет иметь, чтобы добавить больше перегрузки для operator<< для обработки потоковых манипуляторов (std::hex и т.д.). Возвращаемые функции newliners должны всегда быть встроенными, чтобы разрешать RVO.

Смежные вопросы