2014-11-16 9 views
3

오른쪽 맞춤으로 문자열과 정수 값의 서식을 지정하기 만하면됩니다. 정수 값 앞에 공백이 오지 않으면 문제가 없습니다.std : out을 사용하여 텍스트의 서식을 지정하는 방법 setfill std :: setw std : 한 패딩 공간으로 오른쪽

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을 사용하지 않으므로 이전에 공백 문자를 값에 결합하지 않고이를 수행하는 간단한 방법이 있습니까?

답변

1

가장 간단한 방법은처럼 출력 스트림에()는 표준 : 이제 stringstream로 ""가치를 작성하고 그 결과 STR을 작성하는 것입니다 :

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

그리고 여기에 전체 과잉 온다. 접두사가 붙은 템플릿 클래스로, 두 개의 생성자 인수 prefix,val을 하나의 문자열로 묶어 인쇄 할 수 있습니다. 숫자 형식이며, 정밀도는 최종 출력 스트림에서 가져옵니다. ints, float, strings 및 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; 
} 
+0

감사합니다, 나는 다른 방법이 없다는 것을 두려워하지만. 어느 누구도 아이디어를 생각해 내지 않으면 (과잉 살상) 나는 당신의 해결책을 받아 들일 것입니다. 유니 코드 지원이 필요하다는 것을 잊어 버렸지 만, 그것은 실제로 문제가 아닙니다. – seizu

+0

@seizu 더 많은 템플릿 마법이 필요합니다. ostream을 basic_ostream 및 basic_string 등으로 변환하거나 간단한 문자열 스트림 솔루션으로 이동하십시오. – Oncaphillis

0

@Oncaphillis thx 소스 코드 조각을 위해, 나는 그것을 내 필요에 맞게 조금만 변형시킨다. 방금 값을 변환하는 함수를 작성했습니다. std :: to_string은 C++ 11 표준에서 사용되므로 _to_string/_to_wstring을 대신 사용하기로 결정했습니다. 까다로운 부분은 "wcout"을 Windows 콘솔의 UNICODE와 함께 사용하는 것이 었습니다. 나는 그것을 실제로 관리하지 못 했으므로 해결 방법을 찾아야했습니다. 어쨌든 예 : 인쇄 키릴 문자는 콘솔 글꼴을 Consolas 또는 Lucida으로 변경해야합니다.

#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