Frage

Gibt es einen sicheren Weg, um eine Ziffer am Ende einer ganzen Zahl von Zugabe ohne es in einen String konvertiert und ohne stringstreams mit?

Ich habe versucht, die Antwort auf diese und die meisten Lösungen Google vorgeschlagen es Konvertierung in einen String und stringstreams verwenden, aber ich möchte es als eine ganze Zahl halten, um die Datenintegrität zu gewährleisten und die Umwandlung Typen zu vermeiden.
Ich habe auch gelesen, eine Lösung, die den int von 10 zu multiplizieren vorgeschlagen und dann die Ziffer, aber dies könnte einen Integer-Überlauf verursachen.
Ist das sicher zu tun oder ist es eine bessere Methode, dies zu tun? Und wenn ich tun, um diese mit 10 multiplizieren und fügen Sie die Ziffern-Lösung, welche Vorsichtsmaßnahmen sollte ich?

War es hilfreich?

Lösung

Ihre beste Wette ist die Multiplikation mit 10 und die Addition des Wertes. Sie tun können, eine naive Kontrolle etwa so:

assert(digit >= 0 && digit < 10);
newValue = (oldValue * 10) + digit;
if (newValue < oldValue)
{
    // overflow
}

Andere Tipps

Überlauf zu vermeiden:

if ((0 <= value) && (value <= ((MAX_INT - 9) / 10))) {
    return (value * 10) + digit;
}

Anstelle von MAX_INT Sie std::numeric_limits<typeof(value)>::max() oder ähnliches verwenden könnten, um Typen zu unterstützen andere als int.

  assert(digit >= 0 && digit < 10);
  newvalue = 10 * oldvalue;
  if (oldvalue < 0 ) {
    newvalue -= digit;
  } else {
    newvalue += digit;
  }

  // check for overflow SGN(oldvalue) == 0 || SGN(newvalue) == SGN(oldvalue)

Hier ist eine bessere und kugelsicher Implementierung als die, die als Antwort akzeptiert wurden, die auch schnell:

#include <climits>
#include <cassert>

unsigned int add_digit(unsigned int val, unsigned int digit)
{
   // These should be computed at compile time and never even be given a memory location
   static const unsigned int max_no_overflow = (UINT_MAX - 9) / 10U;
   static const unsigned int max_maybe_overflow = UINT_MAX / 10U;
   static const unsigned int last_digit = UINT_MAX % 10;

   assert(digit >= 0 && digit < 10);
   if ((val > max_no_overflow) && ((val > max_maybe_overflow) || (digit > last_digit))) {
      // handle overflow
   } else {
      return val * 10 + digit;
   }
   assert(false);
}

Sie sollten auch in der Lage sein, dies in eine Inline-Funktion zu machen. Die Überlaufprüfung wird fast immer Kurzschluss nach dem ersten Vergleich. Die Klausel nach dem && ist einfach so können Sie (im Fall eines 32-Bit, Zweier-Komplement Ganzzahl) in 5 bis zum Ende der 429.496.729, aber nicht 6.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top