Hi,
ich versuche mir gerade selber C++ bezubringen, muss aber feststellen, dass mir das nicht ganz gelingt. Als Vorinformation: Ich beherrsche JAVA und C ganz gut.
Ich habe mir eine Klasse (bigInt) geschrieben, die später eine Arithmetik für beliebig (heisst hier sehr gross) lange Zahlen erlauben soll. Leider weisst diese ein paar komische Verhalten auf. Bevor ich die Klasse selber angebe, gebe ich erst einmal das komische Verhalten an:
int main()
{
bigInt r( 339192040 );
printf( „r = %s\n“, r.to_string() );
bigInt b( „339192040“ );
printf( „r = %s\n“, r.to_string() );
printf( „b = %s\n“, b.to_string() );
return 0;
}
Der to_string Ausdruck von r verändert r jedesmal. Schon beim ersten Aufruf ist r nicht mehr das, was es mal war. Was läuft da schief? Ich bin mir sicher, dass meine Implementation daran schuld hat, finde aber den Fehler (mangels Erfahrung nicht). Seid bitte sehr kritisch mit dem Code, ich bin nämlich gerade in der Lernphase.
Vielen Dank,
Franz Prilmeier
Und jetzt die Klasse:
// Klasse bigInt, repraesentiert sehr lange Zahlen, d.h.
// bis zu MAX\_ULONG oder Groesse des Speichers, je nachdem,
// was kleiner ist.
class bigInt
{
public:
// Konstruktoren
bigInt();
bigInt( signed long );
bigInt( const char \* );
bigInt( const bigInt& );
// Destruktor
~bigInt();
// Operatorueberladung
void operator+( const bigInt & );
// Ausgabe
char \* to\_string();
// Ausnahmen
class bigIntException{ };
class bigIntOutOfMemoryException: public bigIntException{ };
class bigIntDivZeroException: public bigIntException{ };
private:
// Konstanten, zeigen an, welches Vorzeichen die Zahl haben kann
// Man koennte auch ein enum verwenden
static const int BIG\_SIGN\_0 = 0;
static const int BIG\_SIGN\_PLUS = 1;
static const int BIG\_SIGN\_MINUS = -1;
// Vorzeichen der Zahl
int sign;
// Anzahl der zur Verfuegung stehenden Dezimalstellen
unsigned long dgs\_alloc;
// Anzahl der benutzten Dezimalstellen
unsigned long dgs\_used;
// Die Zahl an sich, in jeder Zahl wird nur eine Dezimalstelle gespeichert
// an der Stelle dp[0] steht die kleinste signifikante Stelle
unsigned short \*dp;
unsigned long strlen( const char \*str );
};
// Initialisiere eine Null
inline bigInt::bigInt()
{
bigInt::dp = new unsigned short[sizeof( unsigned long )];
if ( bigInt::dp == 0 )
{
throw new bigIntOutOfMemoryException();
}
\*bigInt::dp = 0;
bigInt::dgs\_used = 1;
bigInt::dgs\_alloc = sizeof( unsigned long );
bigInt::sign = BIG\_SIGN\_0;
}
// Erzeuge ein bigInt aus einer Maschinenzahl
bigInt::bigInt( signed long value )
{
// Stelle Vorzeichen fest
if ( value == 0 )
{
bigInt::bigInt();
return;
}
else if ( value 0; copy /= 10 ) { bigInt::dgs\_alloc++; }
bigInt::dp = new unsigned short[bigInt::dgs\_alloc];
bigInt::dgs\_used = 0;
// Weise die einzelnen Dezimalstellen zu
while ( value \> 0 ) {
bigInt::dp[bigInt::dgs\_used++] = value % 10;
value /= 10;
}
}
// Erzeuge ein bigInt aus einer Zeichenkette
bigInt::bigInt( const char \*src )
{
unsigned long alloclen = bigInt::strlen( src );
if ( alloclen == 0 )
{
bigInt::bigInt();
return;
}
// Ueberlese Leerzeichen
while ( \*src == ' ' ) { src++; }
// Moegliches Vorzeichen beachten
if ( ( \*src == '-' ) || ( \*src == '+' ) )
{
bigInt::sign = (\*src == '-') ?
bigInt::BIG\_SIGN\_MINUS : bigInt::BIG\_SIGN\_PLUS;
src++;
}
else { bigInt::sign = bigInt::BIG\_SIGN\_PLUS; }
// Kann ja sein, dass da nur ein Vorzeichen war...
if ( \*src == '\0' )
{
bigInt::bigInt();
return;
}
bigInt::dp = new unsigned short[alloclen];
if ( bigInt::dp == 0 )
{
throw new bigIntOutOfMemoryException();
}
bigInt::dgs\_used = 0;
while ( \*src != '\0' )
{
// Es sollte schon eine Zahl sein
if ( \*src '9' )
{
break;
}
// Es handelt sich ja um ein Charakter, deshalb
// muss man den kleinsten Charakter, der eine
// Zahl repraesentiert davon abziehen (streng nach ASCII)
bigInt::dp[bigInt::dgs\_used++] = \*src - '0';
src++;
}
unsigned short \*new\_dp;
// Da wollte uns doch jemand hereinlegen ...
if ( bigInt::dgs\_used == 0 )
{
delete [] bigInt::dp;
bigInt::bigInt();
}
else
{
// Reihenfolge umdrehen, die niedrigstwertige Stelle soll
// ja nach vorne
new\_dp = new unsigned short[alloclen];
unsigned long i;
if ( new\_dp == 0 )
{
throw new bigIntOutOfMemoryException();
}
for ( i = 0; i b.dgs\_used )
{
// this bestimmt die Groesse der neuen Zahl
new\_dp = new unsigned short[bigInt::dgs\_used + 1];
if ( new\_dp == 0 ) { throw new bigIntOutOfMemoryException(); }
bigInt::dgs\_alloc = bigInt::dgs\_used + 1;
}
else
{
// b bestimmt die Groesse der neuen Zahl
new\_dp = new unsigned short[b.dgs\_used + 1];
if ( new\_dp == 0 ) { throw new bigIntOutOfMemoryException(); }
bigInt::dgs\_alloc = b.dgs\_used + 1;
}
unsigned long c\_ld = 0, b\_ld = 0, index = 0;
unsigned short result, carry = 0;
// Addiere mit Uebertrag
while ( b\_ld 10 ) {
carry = 1;
result %= 10;
}
else { carry = 0; }
new\_dp[index++] = result;
}
unsigned long r\_ld = 0, used = 0;
unsigned short \*r\_dp = NULL;
// Ist noch etwas uebrig?
if ( b\_ld 10 )
{
carry = 1;
}
else
{
carry = 0;
}
new\_dp[index++] = result;
}
}
else if ( used != 0 ) {
while ( r\_ld geklaut
// str muss terminiert sein!
unsigned long bigInt::strlen( const char \*str )
{
unsigned long result = 0;
while ( \*str != '\0' )
{
result++;
str++;
}
return result;
}