Đây là tình huống hoàn hảo để sử dụng một khía cạnh.
Phiên bản tùy chỉnh của khía cạnh codecvt có thể được nhúng vào luồng.
Vì vậy, việc sử dụng của bạn sẽ trông như thế này:
int main()
{
/* Imbue std::cout before it is used */
std::ios::sync_with_stdio(false);
std::cout.imbue(std::locale(std::locale::classic(), new IndentFacet()));
std::cout << "Line 1\nLine 2\nLine 3\n";
/* You must imbue a file stream before it is opened. */
std::ofstream data;
data.imbue(indentLocale);
data.open("PLOP");
data << "Loki\nUses Locale\nTo do something silly\n";
}
Định nghĩa của các khía cạnh là hơi phức tạp.
Nhưng toàn bộ vấn đề là ai đó sử dụng khía cạnh không cần biết gì về định dạng. Định dạng được áp dụng độc lập với cách sử dụng luồng.
#include <locale>
#include <algorithm>
#include <iostream>
#include <fstream>
class IndentFacet: public std::codecvt<char,char,std::mbstate_t>
{
public:
explicit IndentFacet(size_t ref = 0): std::codecvt<char,char,std::mbstate_t>(ref) {}
typedef std::codecvt_base::result result;
typedef std::codecvt<char,char,std::mbstate_t> parent;
typedef parent::intern_type intern_type;
typedef parent::extern_type extern_type;
typedef parent::state_type state_type;
int& state(state_type& s) const {return *reinterpret_cast<int*>(&s);}
protected:
virtual result do_out(state_type& tabNeeded,
const intern_type* rStart, const intern_type* rEnd, const intern_type*& rNewStart,
extern_type* wStart, extern_type* wEnd, extern_type*& wNewStart) const
{
result res = std::codecvt_base::noconv;
for(;(rStart < rEnd) && (wStart < wEnd);++rStart,++wStart)
{
// 0 indicates that the last character seen was a newline.
// thus we will print a tab before it. Ignore it the next
// character is also a newline
if ((state(tabNeeded) == 0) && (*rStart != '\n'))
{
res = std::codecvt_base::ok;
state(tabNeeded) = 1;
*wStart = '\t';
++wStart;
if (wStart == wEnd)
{
res = std::codecvt_base::partial;
break;
}
}
// Copy the next character.
*wStart = *rStart;
// If the character copied was a '\n' mark that state
if (*rStart == '\n')
{
state(tabNeeded) = 0;
}
}
if (rStart != rEnd)
{
res = std::codecvt_base::partial;
}
rNewStart = rStart;
wNewStart = wStart;
return res;
}
// Override so the do_out() virtual function is called.
virtual bool do_always_noconv() const throw()
{
return false; // Sometime we add extra tabs
}
};
Xem: Tom's notes below
Nguồn
2009-09-09 04:52:42
có lẽ đã đến lúc ai đó viết thư viện cho điều này :) – xtofl
Đã có sẵn. Nó được gọi là một khía cạnh. Nó được sử dụng để định dạng đầu ra luồng. Do đó, người dùng luồng chỉ có thể xuất dữ liệu như bình thường. Các khía cạnh sau đó có thể thực hiện bất kỳ định dạng độc lập (do đó định dạng đầu ra có thể được thay đổi chỉ bằng cách thay đổi khía cạnh mà dòng sử dụng mà không thay đổi mã tạo ra đầu ra). –