juillet
2008
Avec les MFC nous disposons d’une méthode Format pour la classe CString,
Celle-ci fonctionne comme la fonction sprintf,ou vsprintf du C.
Comment rajouter une telle fonctionnalité sur la classe string ou wstring ?
On peut utiliser BOOST qui fournit la bibliothèque Boost Format , qui autorise (entre autre) les spécifications de formats comme printf du C.
Voir : Les conversions numériques en C,C++,C++/CLI
Ou alors on peut réaliser sa propre méthode comme suit :
Le code ci-dessous permet de disposer de cette même fonctionnalité pour la classe string ou wstring.
Au final deux modes d’utilisations possibles:
-Utiliser une fonction globale en multi-bytes et Unicode.
-Étendre la classe string ou wstring grâce à une extension à base de template.
#include <stdarg.h>
std::string FormatString( const char *szFormat, va_list &arg_ptr )
{
if(szFormat==NULL) AfxThrowUserException();
std::string strRet;
int nSize=_vscprintf(szFormat,arg_ptr)+1;
char *szRet= new char[nSize];
vsprintf_s( szRet,nSize,szFormat,arg_ptr);
strRet.assign(szRet);
delete []szRet;
return strRet;
}
std::string FormatString( const char *szFormat, ... )
{
if(szFormat==NULL) AfxThrowUserException();
std::string strRet;
va_list arg_ptr;
va_start(arg_ptr,szFormat);
strRet.swap(FormatString( szFormat,arg_ptr ));
va_end(arg_ptr);
return strRet;
}
std::wstring FormatString(const wchar_t *szFormat,va_list &arg_ptr )
{
if(szFormat==NULL) AfxThrowUserException();
std::wstring strRet;
int nSize=_vscwprintf(szFormat,arg_ptr)+1;
wchar_t *szRet= new wchar_t[nSize];
vswprintf_s(szRet,nSize,szFormat,arg_ptr);
strRet.assign(szRet);
delete []szRet;
return strRet;
}
std::wstring FormatString(const wchar_t *szFormat,... )
{
if(szFormat==NULL) throw (new CInvalidArgException());
std::wstring strRet;
va_list arg_ptr;
va_start(arg_ptr,szFormat);
strRet.swap(FormatString(szFormat,arg_ptr ));
va_end(arg_ptr);
return strRet;
}
template <typename tplstring=std:string,typename T=char >
class stringex : public tplstring
{
public:
void Format(const T *szFormat, ...)
{
if(szFormat==NULL) AfxThrowUserException();
va_list arg_ptr;
va_start(arg_ptr,szFormat);
swap(::FormatString(szFormat,arg_ptr ));
va_end(arg_ptr);
}
};
Utilisation:
stringex<std::string,char> strex;
strex.Format("essai %d,%10.2f",10,3.14);
// unicode
std::wstring wstr=FormatString(L"essai %d,%10.2f",10,3.14);
stringex<std::wstring,wchar_t> wstrex;
wstrex.Format(L"essai %d,%10.2f",10,3.14);
2 Commentaires + Ajouter un commentaire
Articles récents
Commentaires récents
Archives
- septembre 2010
- mai 2010
- avril 2010
- février 2010
- août 2009
- juin 2009
- mai 2009
- février 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- juillet 2008
- juin 2008
- mai 2008
- avril 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007
- avril 2007
- mars 2007
- février 2007
- janvier 2007
- décembre 2006
- novembre 2006
- octobre 2006
- septembre 2006
- août 2006
- juillet 2006
- juin 2006
- mai 2006
- mars 2006
- février 2006
Juste une petite remarque, ceci plante :
[code]std::wstring hello(L »Hello »); std::wstring wstr=FormatString(L »essai %s »,hello);[/code]
Mais utiliser ce code:
[code]std::wstring hello(L »Hello »); std::wstring wstr=FormatString(L »essai %s »,hello.c_str());[/code]
Avec les variadic templates de C++0x (cf http://blog.developpez.com/alp?title=en_route_pour_cpp0x_variadic_templates) ça sera beaucoup plus simple d’écrire ce genre de choses. A rajouter une couche de concepts avec un concept ConvertibleToString, et l’on aura quelque chose de très très solide _à la compilation_ et qui nous laisse une liberté d’utilisation toutefois très grande.