Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Boas Pessoal!
Tinha esse trecho de código em um projeto.
E outro dia, para um projeto menor, me fez falta formatar strings, em C++, como faz-se em C.
Fui buscar esse código e decidi postar por aqui, pode ser que faça falta para alguém tbm.
Header:
#ifndef ASTRUTILS_H
#define ASTRUTILS_H
#include <cstdarg>
#include <sstream>
#include <string>
using std::string;
#include <AErr.h> //A definição da classe Err está aqui!
/* InvalidStrFmtErr is thrown by StrPrintF, if the function find a formatting error.
*/
class InvalidStrFmtErr : public Err
{
public:
InvalidStrFmtErr(const string &msg) : Err(msg) {}
};
/** @brief returns true if the conversion was sucessfull.
*/
template<typename T>
bool fromStr(T &t, const string &res, std::ios_base& (*radix)(std::ios_base&) = std::dec)
{
std::stringstream strm(res);
return !((strm >> radix >> t).fail());
}
/** @brief returns true if the conversion was sucessfull.
*/
template<typename T>
bool toStr(const T &t, string &res, std::ios_base& (*radix)(std::ios_base&) = std::dec)
{
std::stringstream strm;
strm << radix << t;
res = strm.str();
return !strm.fail();
}
/** @brief The same operations without error checking.
*/
namespace Unsafe
{
template<typename T>
string toStr(const T &t, std::ios_base& (*radix)(std::ios_base&) = std::dec)
{
std::stringstream strm;
strm << radix << t;
return strm.str();
}
template<typename T>
T fromStr(const string &str, std::ios_base& (*radix)(std::ios_base&) = std::dec)
{
std::stringstream strm(str);
T t;
strm >> radix >> t;
return t;
}/** @brief Very similar to sprintf, but work with std strings.
*/
string StrPrintF(string format, ...);
#endif
A classe Err é muito semelhante à classe exception, é a classe base para todas as exceções usadas no meu projeto.
class Err
{
public:
Err();
Err(const string &msg) : message(msg) {}
string What() const;
private:
string message;
};
Code:
string StrPrintF(string format, ...)
{
va_list argL;
int i = -1;
va_start(argL, format);
while ((i = format.find('%', i+1)) != string::npos)
{
string ax;
int subs = 2;
switch(format[i+1])
{
case 'd':
case 'i': toStr<int>(va_arg(argL, int), ax); break;
case 'x': toStr<int>(va_arg(argL, int), ax, std::hex); break;
case 'o': toStr<int>(va_arg(argL, int), ax, std::oct); break;
case 's': ax.assign(va_arg(argL, const char*)); break;
case 'c': ax = " "; ax[0] = va_arg(argL, int); break;
case 'f': toStr<double>(va_arg(argL, double), ax); break;
case 'l':
subs = 3;
switch(format[i+2])
{
case 'd':
case 'i': toStr<long int>(va_arg(argL, long int), ax); break;
case 'x': toStr<long int>(va_arg(argL, long int), ax, std::hex); break;
case 'o': toStr<long int>(va_arg(argL, long int), ax, std::oct); break;
case 'f': toStr<long double>(va_arg(argL, long double), ax); break;
default:
va_end(argL);
throw InvalidStrFmtErr(StrPrintF("%c is not a valid format flag after 'l'", format[i+2]));
}
break;
case '#':
{
int num = va_arg(argL, int);
subs = 3;
switch(format[i+2])
{
case 'x': toStr<int>(num, ax, std::hex); ax.insert(0, "0x"); break;
case 'o': toStr<int>(num, ax, std::oct); ax.insert(0, "00"); break;
default:
va_end(argL);
throw InvalidStrFmtErr(StrPrintF("%c is not a valid format flag after '#'", format[i+2]));
}
break;
}
default:
va_end(argL);
throw InvalidStrFmtErr(StrPrintF("%c is not a valid format flag", format[i+1]));
}
format.replace(i, subs, ax);
}
va_end(argL);
return format;
}
Exemplo:
std::cout << StrPrintF("%d = %#x\n", 34, 34);
std::cout << StrPrintF("String testing: '%s'", "abcde"); //Atenção, a flag %s recebe um char*
>
34 = 0x22
String testing 'abcde'