【问题标题】:How to format text using std:out setfill std::setw std:right with one padding space如何使用带有一个填充空间的 std:out setfill std::setw std:right 格式化文本
【发布时间】:2014-11-16 16:53:29
【问题描述】:

我只想用右对齐格式化一个字符串和一个整数值。 如果在整数值之前没有前导空格,这样做没有问题。

bytes.....................123981
total bytes..............1030131 

但它应该是这样的:

bytes ................... 123981
total bytes ............ 1030131

很遗憾,下面的示例不起作用,因为 setw(右对齐)仅与下一个流元素相关。

int iBytes = 123981;
int iTotalBytes = 1030131;
cout << setfill('.');
cout << right;
cout << "bytes " << setw(20) << " " << iBytes << endl;
cout << "total bytes " << setw(14) << " " << iTotalBytes << endl;

我几乎从不使用 std::cout,那么有没有一种简单的方法可以做到这一点,而无需事先将空格字符加入到值中?

【问题讨论】:

    标签: c++ unicode cout windows-console setw


    【解决方案1】:

    最简单的方法是将您的“”和值写入 std::stringstream 并将生成的 str() 写入输出流,例如:

    std::stringstream ss;
    ss << " " << iBytes;
    cout << "bytes " << setw(20) << ss.str() << endl;
    

    这里完全是矫枉过正。一个可以打印的模板类前缀,并将两个构造函数参数prefix,val 捆绑到一个要打印的字符串中。数字格式,精度取自最终输出流。适用于整数、浮点数、字符串和 const char *。并且应该与具有有效输出运算符的每个 arg 一起使用。

    #include <fstream> 
    #include <iostream> 
    #include <iomanip> 
    #include <sstream> 
    
    using  namespace std; 
    
    template<class T> 
    class prefixed_base  { 
    public: 
        prefixed_base(const std::string & prefix,const T val) : _p(prefix),_t(val) { 
        } 
    protected: 
        std::string _p; 
        T           _t; 
    }; 
    
    // Specialization for const char *
    template<> 
    class prefixed_base<const char*>  { 
    public: 
        prefixed_base(const std::string & prefix,const char * val) : _p(prefix),_t(val) { 
        } 
    protected: 
        std::string _p; 
        std::string _t; 
    }; 
    
    template<class T> 
    class prefixed : public  prefixed_base<T> { 
    private: 
        typedef prefixed_base<T> super; 
    public: 
        prefixed(const std::string & prefix,const T val) : super(prefix,val) { 
        } 
    
        // Output the prefixed value to an ostream
        // Write into a stringstream and copy most of the
        // formats from os.
    
        std::ostream & operator()(std::ostream & os) const { 
            std::stringstream ss; 
    
            // We 'inherit' all formats from the 
            // target stream except with. This Way we 
            // keep informations like hex,dec,fixed,precision 
    
            ss.copyfmt(os); 
            ss << std::setw(0); 
            ss << super::_p; 
    
            ss.copyfmt(os); 
            ss << std::setw(0); 
            ss << super::_t; 
    
            return os << ss.str(); 
        } 
    }; 
    
    // Output operator for class prefixed
    template<class T> 
    std::ostream & operator<<(std::ostream & os,const prefixed<T> & p) { 
        return p(os); 
    } 
    
    // This function can be used directly for output like os << with_prefix(" ",33.3)
    template<class T> 
    prefixed<T>    with_prefix(const std::string & p,const T  v) { 
        return prefixed<T>(p,v); 
    } 
    
    int main() { 
        int iBytes = 123981; 
        int iTotalBytes = 1030131; 
        cout << setfill('.'); 
        cout << right; 
    
        cout << "bytes " << setw(20) << with_prefix(" ",iBytes) << endl; 
        cout << "total bytes " << setw(14) << with_prefix(" ",iTotalBytes) << endl; 
    
        cout << "bla#1 "       << setw(20) <<  std::fixed << std::setprecision(9) << with_prefix(" ",220.55)      << endl; 
        cout << "blablabla#2 " << setw(14) <<  std::hex << with_prefix(" ",iTotalBytes) << endl; 
    } 
    

    【讨论】:

    • 感谢您的贡献,虽然我担心没有其他办法。如果没有人提出一个想法(不那么矫枉过正),我想我会接受你的解决方案。我忘了提到我需要 UNICODE 支持,但这不是问题。
    • @seizu 这将涉及更多的模板魔法。将 ostream 转换为 basic_ostream 并将字符串转换为 basic_string 等...或者使用简单的 stringstream 解决方案。
    【解决方案2】:

    @Oncaphillis 感谢这段源代码,我根据自己的需要对其进行了一些调整。我刚刚写了一个函数来转换值。 std::to_string 被 C++11 标准使用,所以我决定改用 _to_string/_to_wstring。棘手的部分是让 "wcout" 在 Windows 控制台上使用 UNICODE。我并没有真正管理它,所以我不得不做一个解决方法。无论如何打印例如西里尔字符您必须将控制台字体更改为 ConsolasLucida

    #include <windows.h>
    #include <tchar.h>
    #include <iostream>
    #include <iomanip>
    #include <sstream>
    
    using namespace std;
    
    #if defined(UNICODE) || defined(_UNICODE)
    
        #define _tcout std::wcout
        #define _to_tstring _to_wstring
    
        template <typename T>std::wstring _to_wstring(const T& value) {
            std::wostringstream wos;
            wos.copyfmt(std::wcout);
            wos << value;
            return wos.str();
        }
    #else
        #define _tcout std::cout
        #define _to_tstring _to_string
    
        template <typename T> std::string _to_string(const T& value) {
            std::ostringstream os;
            os.copyfmt(std::cout);
            os << value;
            return os.str();
        }
    #endif
    
    int _tmain(int argc, _TCHAR* argv[]) {
        int iBytes = 123981; 
        int iTotalBytes = 1030131; 
    
    #if defined(UNICODE) || defined(_UNICODE)
        wostringstream  newCoutBuffer;
        wstreambuf*     oldCoutBuffer = _tcout.rdbuf(newCoutBuffer.rdbuf()); // redirect cout buffer
    #endif
    
        _tcout.imbue(std::locale("German"));  // enable thousand separator
        _tcout.precision(0);
        _tcout << setfill(_T('.')) << right << fixed;
    
        _tcout << _T("bytes ")          << setw(20) << _T(" ") + _to_tstring(iBytes) << endl;
        _tcout << _T("bytes total ")    << setw(14) << _T(" ") + _to_tstring(iTotalBytes) << endl;
        _tcout << _T("bla bla ")        << fixed << setprecision(9); _tcout << setw(18) << _T(" ") +  _to_tstring(0.1337) << endl; 
        _tcout << _T("Милые женщины ")  << hex; _tcout << setw(12) << _T(" ") +  _to_tstring(iTotalBytes) << endl; 
        _tcout << _T("retries ")        << dec; _tcout << setw(18) << _T(" ") + _to_tstring(2) + _T(" of ") +  _to_tstring(20) << endl; 
    
    #if defined(UNICODE) || defined(_UNICODE)
        DWORD dwWritten;
        WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), newCoutBuffer.str().c_str(),newCoutBuffer.tellp(),&dwWritten,NULL);
        _tcout.rdbuf(oldCoutBuffer);
    #endif
    
        return 0;
    }
    

    输出:

    bytes ............ 123.981
    bytes total .... 1.030.131
    bla bla ...... 0,133700000
    Милые женщины ..... fb.7f3
    retries .......... 2 of 20
    

    【讨论】:

      猜你喜欢
      • 2013-09-23
      • 2017-07-20
      • 2016-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-10
      相关资源
      最近更新 更多