Variablen konvertieren

Thomasio

Erfahrenes Mitglied
Früher mal habe ich fertige Funktionen wie itoa() verwendet, was bei manchen Variabletypen lange Suche bedeutet hat, bis ich die passende Funktion gefunden hatte.
Dann habe ich entdeckt, dass diese Funktionen intern fast alle stringstream verwenden und bin dazu übergegangen mir meine Funktionen selber zu schreiben.

Code:
stringstream s;
s << Source;
s >> Dest;
return Dest;

Das funktioniert mit allen standard Variabletypen, selbst mit UNICODE (wstringstream), uintTOwstring() und umgekehrt, gibt es keine Probleme.

Ich frage mich nur, wo die Grenze ist?
WideCharToMultiByte() geht offensichtlich nicht so einfach.

Gibt es irgendwo eine Liste der Variabletypen, die (w)stringstream konvertieren kann?
 
Gibt es irgendwo eine Liste der Variabletypen, die (w)stringstream konvertieren kann?
Nein, denn diese Liste kann nie vollständig sein. Du kannst beliebige Typen mit stringstream verwenden, wenn du operator>> und/oder operator<< für diesen Typen überlädst. Beispiel:

C++:
#include <sstream>
#include <iostream>

struct MyStruct {
  int foo;
  float bar;
};

std::ostream& operator<<(std::ostream& stream, const MyStruct& ms) {
  return stream << ms.foo << ' ' << ms.bar;
}

std::istream& operator>>(std::istream& stream, MyStruct& ms) {
  return stream >> ms.foo >> ms.bar;
}

int main() {
  MyStruct ms1 = { 42, 47.11f };
  MyStruct ms2;

  std::stringstream ss;
  ss << ms1;
  ss >> ms2;

  std::cout << ms2;

  return 0;
}

Du solltest dir auch mal Boost.Lexical_Cast anschauen.

Grüße,
Matthias
 
Vielen Dank für die Antworten.

Scheinbar gehen die Möglichkeiten noch viel weiter als ich dachte, das macht es mir in Moment viel einfacher.

Klar verwende ich C++, weil ich meistens Win32 Anwendungen schreibe.
Entdeckt habe ich das in einer Antwort, wo jemand genau danach gefragt hat, wie diverse Konvertierfunktionen intern arbeiten.
Optimierung auf Geschwindigkeit ist für mich (noch) kein Thema, weil ich (immer noch) nur zu Lernzwecken code.
 
Klar verwende ich C++, weil ich meistens Win32 Anwendungen schreibe.

Die Windows API ist in C geschrieben, ergo kannst du auch "nur" C verwenden.
Sonst gäbe es ja Klassen anstatt der ganzen einzelnen Funktionen.

Der Geschwindigkeitunterschied ist hierbei übrigens auf normalen System so klein, dass es nicht beachtet werden muss.
Außer du hast große Datenmengen oder du programmierst für einen Mikrocontroller o.Ä.
 
Klar verwende ich C++, weil ich meistens Win32 Anwendungen schreibe.
Das geht mit C auch.
Optimierung auf Geschwindigkeit ist für mich (noch) kein Thema, weil ich (immer noch) nur zu Lernzwecken code.
Aber andere sind Geschwindigkeitssüchtig.
Entdeckt habe ich das in einer Antwort, wo jemand genau danach gefragt hat, wie diverse Konvertierfunktionen intern arbeiten.
...lieber auf den Code verlassen.

Hier ein Auszug, aus was itoa bestehen kann ;-]
C:
#if _ITOA_NEEDED
char *
_itoa (value, buflim, base, upper_case)
     unsigned long long int value;
     char *buflim;
     unsigned int base;
     int upper_case;
{
  const char *digits = (upper_case
			? _itoa_upper_digits
			: _itoa_lower_digits);
  const struct base_table_t *brec = &_itoa_base_table[base - 2];

  switch (base)
    {
# define RUN_2N(BITS) \
      do								      \
        {								      \
	  /* `unsigned long long int' always has 64 bits.  */		      \
	  mp_limb_t work_hi = value >> (64 - BITS_PER_MP_LIMB);		      \
									      \
	  if (BITS_PER_MP_LIMB == 32)					      \
	    {								      \
	      if (work_hi != 0)						      \
		{							      \
		  mp_limb_t work_lo;					      \
		  int cnt;						      \
									      \
		  work_lo = value & 0xfffffffful;			      \
		  for (cnt = BITS_PER_MP_LIMB / BITS; cnt > 0; --cnt)	      \
		    {							      \
		      *--buflim = digits[work_lo & ((1ul << BITS) - 1)];      \
		      work_lo >>= BITS;					      \
		    }							      \
		  if (BITS_PER_MP_LIMB % BITS != 0)			      \
		    {							      \
		      work_lo						      \
			|= ((work_hi					      \
			     & ((1 << (BITS - BITS_PER_MP_LIMB%BITS))	      \
				- 1))					      \
			    << BITS_PER_MP_LIMB % BITS);		      \
		      work_hi >>= BITS - BITS_PER_MP_LIMB % BITS;	      \
		      if (work_hi == 0)					      \
			work_hi = work_lo;				      \
		      else						      \
			*--buflim = digits[work_lo];			      \
		    }							      \
		}							      \
	      else							      \
		work_hi = value & 0xfffffffful;				      \
	    }								      \
	  do								      \
	    {								      \
	      *--buflim = digits[work_hi & ((1 << BITS) - 1)];		      \
	      work_hi >>= BITS;						      \
	    }								      \
	  while (work_hi != 0);						      \
	}								      \
      while (0)
    case 8:
      RUN_2N (3);
      break;

    case 16:
      RUN_2N (4);
      break;

    default:
      {
	char *bufend = buflim;
# if BITS_PER_MP_LIMB == 64
	mp_limb_t base_multiplier = brec->base_multiplier;
	if (brec->flag)
	  while (value != 0)
	    {
	      mp_limb_t quo, rem, x, dummy;

	      umul_ppmm (x, dummy, value, base_multiplier);
	      quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1);
	      rem = value - quo * base;
	      *--buflim = digits[rem];
	      value = quo;
	    }
	else
	  while (value != 0)
	    {
	      mp_limb_t quo, rem, x, dummy;

	      umul_ppmm (x, dummy, value, base_multiplier);
	      quo = x >> brec->post_shift;
	      rem = value - quo * base;
	      *--buflim = digits[rem];
	      value = quo;
	    }
# endif
# if BITS_PER_MP_LIMB == 32
	mp_limb_t t[3];
	int n;

	/* First convert x0 to 1-3 words in base s->big.base.
	   Optimize for frequent cases of 32 bit numbers.  */
	if ((mp_limb_t) (value >> 32) >= 1)
	  {
#  if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
	    int big_normalization_steps = brec->big.normalization_steps;
	    mp_limb_t big_base_norm
	      = brec->big.base << big_normalization_steps;
#  endif
	    if ((mp_limb_t) (value >> 32) >= brec->big.base)
	      {
		mp_limb_t x1hi, x1lo, r;
		/* If you want to optimize this, take advantage of
		   that the quotient in the first udiv_qrnnd will
		   always be very small.  It might be faster just to
		   subtract in a tight loop.  */

#  if UDIV_TIME > 2 * UMUL_TIME
		mp_limb_t x, xh, xl;

		if (big_normalization_steps == 0)
		  xh = 0;
		else
		  xh = (mp_limb_t) (value >> (64 - big_normalization_steps));
		xl = (mp_limb_t) (value >> (32 - big_normalization_steps));
		udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm,
				   brec->big.base_ninv);

		xl = ((mp_limb_t) value) << big_normalization_steps;
		udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm,
				   brec->big.base_ninv);
		t[2] = x >> big_normalization_steps;

		if (big_normalization_steps == 0)
		  xh = x1hi;
		else
		  xh = ((x1hi << big_normalization_steps)
			| (x1lo >> (32 - big_normalization_steps)));
		xl = x1lo << big_normalization_steps;
		udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm,
				   brec->big.base_ninv);
		t[1] = x >> big_normalization_steps;
#  elif UDIV_NEEDS_NORMALIZATION
		mp_limb_t x, xh, xl;

		if (big_normalization_steps == 0)
		  xh = 0;
		else
		  xh = (mp_limb_t) (value >> 64 - big_normalization_steps);
		xl = (mp_limb_t) (value >> 32 - big_normalization_steps);
		udiv_qrnnd (x1hi, r, xh, xl, big_base_norm);

		xl = ((mp_limb_t) value) << big_normalization_steps;
		udiv_qrnnd (x1lo, x, r, xl, big_base_norm);
		t[2] = x >> big_normalization_steps;

		if (big_normalization_steps == 0)
		  xh = x1hi;
		else
		  xh = ((x1hi << big_normalization_steps)
			| (x1lo >> 32 - big_normalization_steps));
		xl = x1lo << big_normalization_steps;
		udiv_qrnnd (t[0], x, xh, xl, big_base_norm);
		t[1] = x >> big_normalization_steps;
#  else
		udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32),
			    brec->big.base);
		udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base);
		udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base);
#  endif
		n = 3;
	      }
	    else
	      {
#  if UDIV_TIME > 2 * UMUL_TIME
		mp_limb_t x;

		value <<= brec->big.normalization_steps;
		udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32),
				   (mp_limb_t) value, big_base_norm,
				   brec->big.base_ninv);
		t[1] = x >> brec->big.normalization_steps;
#  elif UDIV_NEEDS_NORMALIZATION
		mp_limb_t x;

		value <<= big_normalization_steps;
		udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32),
			    (mp_limb_t) value, big_base_norm);
		t[1] = x >> big_normalization_steps;
#  else
		udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32),
			    (mp_limb_t) value, brec->big.base);
#  endif
		n = 2;
	      }
	  }
	else
	  {
	    t[0] = value;
	    n = 1;
	  }

	/* Convert the 1-3 words in t[], word by word, to ASCII.  */
	do
	  {
	    mp_limb_t ti = t[--n];
	    int ndig_for_this_limb = 0;

#  if UDIV_TIME > 2 * UMUL_TIME
	    mp_limb_t base_multiplier = brec->base_multiplier;
	    if (brec->flag)
	      while (ti != 0)
		{
		  mp_limb_t quo, rem, x, dummy;

		  umul_ppmm (x, dummy, ti, base_multiplier);
		  quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1);
		  rem = ti - quo * base;
		  *--buflim = digits[rem];
		  ti = quo;
		  ++ndig_for_this_limb;
		}
	    else
	      while (ti != 0)
		{
		  mp_limb_t quo, rem, x, dummy;

		  umul_ppmm (x, dummy, ti, base_multiplier);
		  quo = x >> brec->post_shift;
		  rem = ti - quo * base;
		  *--buflim = digits[rem];
		  ti = quo;
		  ++ndig_for_this_limb;
		}
#  else
	    while (ti != 0)
	      {
		mp_limb_t quo, rem;

		quo = ti / base;
		rem = ti % base;
		*--buflim = digits[rem];
		ti = quo;
		++ndig_for_this_limb;
	      }
#  endif
	    /* If this wasn't the most significant word, pad with zeros.  */
	    if (n != 0)
	      while (ndig_for_this_limb < brec->big.ndigits)
		{
		  *--buflim = '0';
		  ++ndig_for_this_limb;
		}
	  }
	while (n != 0);
# endif
	if (buflim == bufend)
	  *--buflim = '0';
      }
      break;
    }

  return buflim;
}
#endif
 
Dann habe ich entdeckt, dass diese Funktionen intern fast alle stringstream verwenden und bin dazu übergegangen mir meine Funktionen selber zu schreiben.

Was? Bevor das hier noch weitere Kreise zieht: Entweder du hast dich hier verschrieben, oder ein Vollhorst hat Quark erzählt. Natürlich verwenden diverse Umwandelfunktionen intern KEINEN stringstream. Genau umgekehrt.

Zusätzlichen du den X Objekten, die ein stringstream benötigt, ruft er dann intern auch nur die einzelnen Umwandelroutinen auf (bzw. setzt über Operatoren eigene ein).
 

Neue Beiträge

Zurück