2013-02-13 7 views
9

Я рефакторинга некоторые унаследованного кода, который использует printf с лонги строк (без фактического форматирования), чтобы распечатать обычные текстовые заголовки таблицы, которые выглядит умозрительно, как это:центр текст фиксированной ширины поля с потоковыми манипуляторов в C++

| Table | Column | Header | 

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

printf("| Table | Column | Header |"); 

Я хотел бы произвести выше с кодом к действию :

outputStream << "|" << std::setw(10) << std::center << "Table" 
      << "|" << std::setw(10) << std::center << "Column" 
      << "|" << std::setw(9) << std::center << "Header" 
      << "|" << std::endl; 

, который не компилируется, поскольку <iomanip> имеет потоковые манипуляторы std::left, std::right и std::internal, но, кажется, не имеют каких-либо std::center. Есть ли чистый способ сделать это уже в стандартных библиотеках C++, или мне придется вручную вычислить необходимый интервал?


Несмотря на то, что это более многословным, чем код C, это будет менее многословным в долгосрочной перспективе из числа printf заявлений и количества инфиксальный дублирования в их строках. Он также будет более расширяемым и поддерживаемым.

ответ

7

Вот вспомогательный класс, который выполнить то, что вы хотите:

#include <string> 
#include <iostream> 
#include <iomanip> 

template<typename charT, typename traits = std::char_traits<charT> > 
class center_helper { 
    std::basic_string<charT, traits> str_; 
public: 
    center_helper(std::basic_string<charT, traits> str) : str_(str) {} 
    template<typename a, typename b> 
    friend std::basic_ostream<a, b>& operator<<(std::basic_ostream<a, b>& s, const center_helper<a, b>& c); 
}; 

template<typename charT, typename traits = std::char_traits<charT> > 
center_helper<charT, traits> centered(std::basic_string<charT, traits> str) { 
    return center_helper<charT, traits>(str); 
} 

// redeclare for std::string directly so we can support anything that implicitly converts to std::string 
center_helper<std::string::value_type, std::string::traits_type> centered(const std::string& str) { 
    return center_helper<std::string::value_type, std::string::traits_type>(str); 
} 

template<typename charT, typename traits> 
std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& s, const center_helper<charT, traits>& c) { 
    std::streamsize w = s.width(); 
    if (w > c.str_.length()) { 
     std::streamsize left = (w + c.str_.length())/2; 
     s.width(left); 
     s << c.str_; 
     s.width(w - left); 
     s << ""; 
    } else { 
     s << c.str_; 
    } 
    return s; 
} 

Он используется просто позвонив по телефону centered("String"), например, так:

int main(int argc, char *argv[]) { 
    std::cout << "|" << std::setw(10) << centered("Table") 
       << "|" << std::setw(10) << centered("Column") 
       << "|" << std::setw(9) << centered("Header") << "|" 
       << std::endl; 
} 
+2

Ah !! Мне нравится это. Очень умно. –

+0

+1. Я протестировал его здесь: [test-code] (http://stacked-crooked.com/view?id=f4728b397853f9c9d788f268d121b466) – Nawaz

+1

Это хорошо только для C++ 0x? В MSVS 2010 я получаю «аргументы шаблона по умолчанию разрешены только для шаблона класса». Согласно [этому ответу SO] (http://stackoverflow.com/questions/2447458/default-template-arguments-for-function-templates) это было исправлено в C++ 0x. –

3

Нет std::center манипулятор. Я боюсь, что вы должны сделать это сами. Вы можете написать вспомогательную функцию для вычисления пробелов, заданных шириной и строкой, чтобы уменьшить усилия.

Вот пример того, как может выглядеть вспомогательная функция. Требуется некоторая работа, чтобы сделать ее более эффективной и т. Д.

string helper(int width, const string& str) { 
    int len = str.length(); 
    if(width < len) { return str; } 

    int diff = width - len; 
    int pad1 = diff/2; 
    int pad2 = diff - pad1; 
    return string(pad1, ' ') + str + string(pad2, ' '); 
} 
3

Боюсь, что вам придется делать это вручную. Но дело не в том, что сложно, если вы работаете со строками. Что-то вроде:

должен сделать трюк.

0

вы могли бы использовать библиотеку Ncurses ... это своего рода испуга и вы должны добавить «-L NCURSES» к вашей команде компиляции (g ++ -L NCURSES yourProgram.cpp), и она будет работать, плюс вы сможете делать цвета и другие «классные» вещи [cool for CLI в любом случае]. просто прочитал руководство, центрирование материала довольно просто. http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

+1

извините ... -lncurses - это флаг. я не использовал ncurses в годах – jEXEy

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

  • Нет связанных вопросов^_^