Newsgroup: it.comp.lang.c++
Titolo: conversione T->string e viceversa

Ho letto che alcune persone richiedono come convertire un intero in una stringa e viceversa.
Ecco una soluzione molto generale (anche se non è il massimo della efficienza,
ma a volte va bene comunque).
Il codice non è commentato ma ho riportato un esempio.
#include <ios>
#include <sstream>
#include <string>
#include <locale>
#include <stdexcept>
#include <utility>
//
// Conversione T -> string
//
template<class T> std::string
ToString(const T& val, std::locale loc = std::locale())
{
  std::ostringstream buf;
  buf.imbue(loc);
  buf << val;
  if(!buf) throw std::runtime_error("conversione errata");
  return buf.str();
}
template<class T> std::string
ToString(const T& val, const std::ios_base& format, std::locale loc = std::locale())
{
  std::ostringstream buf;
  buf.imbue(loc);
  buf.flags(format.flags());
  buf.precision(format.precision());
  buf << val;
  if(!buf) throw std::runtime_error("conversione errata");
  return buf.str();
}
//
// Conversione string -> T
//
template<class T> std::pair<T, typename std::string::size_type>
FromString(const std::string& str, std::locale loc = std::locale())
{
  std::istringstream buf(str);
  buf.imbue(loc);
  T val;
  buf >> val;
  if(!buf) throw std::runtime_error("conversione errata");
  return std::make_pair(val, buf.tellg());
}
Esempio:
int main()
{
  double d = 124.4;
  std::ios_base format = std::cout;
  format.setf(std::ios_base::scientific, std::ios_base::floatfield);
  std::string str = ToString(d, format);
  std::cout << "d = " << d << '\n';
  std::cout << "str = " << str << '\n';
  std::string str2("129.78resto");
  std::pair<double, std::string::size_type> result = FromString<double>(str2);
  std::cout << "str2 = " << str2 << '\n';
  std::cout << "d2 = " << result.first << '\n';
  std::cout << "end = " << result.second << '\n';
  std::cout << "str2.length() = " << str2.length() << '\n';
}
Saluti  Manlio Perillo

I miei vivissimi complimenti per aver postato codice standard e non
soluzioni basate sull'API Win32 o sulle VCL Borland, tanto di moda di
questo periodo.
Ciao,
Nicola

   format.setf(std::ios_base::scientific, std::ios_base::floatfield);
si modificano anche i flags di std::cout e la cosa non mi piace.
Per questo avevo pensato di creare una copia ed il BCC 5.5 mi ha illuso che fosse
possibile.
Saluti  Manlio Perillo

 si modificano anche i flags di std::cout e la cosa non mi piace.
Scusa, non ho un manuale sottomano, ma mi par di ricordare che
ios_base::setf ritorni i vecchi flags.  Se fosse cosi', potresti
ripristinare lo stato dello stream alla fine.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 ripristinare lo stato dello stream alla fine.
Confermo.
EMG

 Il costruttore di copie di ios_base è protetto.
Mi correggo, è privato (e lasciato non definito).
Manlio Perillo


Si certo, ma è scomodo.
Ho trovato una soluzione migliore:
class IOFormat: public std::ios_base
{
  public:
    IOFormat()
    : std::ios_base()
    {
      flags(skipws | dec);
      precision(6);
    }
    IOFormat(const std::ostream& o)
    {
      flags(o.flags());
      precision(o.precision());
    }
};
Quindi basta fare, ad esempio
    IOFormat format(std::cout);
e passarlo alle funzioni.
Saluti  Manlio Perillo