www.mikrocontroller.net

Forum: PC-Programmierung Scope- oder Zeigerproblem


Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe folgende Klasse BigInt in C++ implementiert.
Für den Anfang will ich nur mal einen String einlesen und ihn dann mit 
'.Ausgabe' auf der Konsole ausgeben

Mein Problem ist das ich am Ende des Konstruktors den Inhalt des Strings 
verliere.

#include <iostream.h>
#include <string.h>

class BigInt
{
public:

  BigInt ();
  BigInt (const char *const);
  ~BigInt ();

  BigInt operator+ (const BigInt &);
  BigInt operator- (const BigInt &);
  void operator= (const BigInt &);

  void Ausgabe(void);

private:
  char *pcString;
  int length;
  void StringUp(char);
};

BigInt::BigInt(const char *const pcZahl)
{
  length = strlen(pcZahl);

  pcString  = new char[length+1];    //neuer Stringpointer

  pcString[length+1] = '\0';      // Nullterminierung

  for (int i=0;i<= length;i++)
  {
    pcString[length-i]= pcZahl[i];
  }
}

/********* MAIN ************/
#include "BigInt.h"

int main(void)
{
  BigInt big2("98765432109876543210987654321098765432109876543210");

      big2.Ausgabe();
  return 0;
}



Kann mir jemand helfen und mir sagen an was das liegt?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mein Problem ist das ich am Ende des Konstruktors den Inhalt
> des Strings verliere.

Das hast Du wie festgestellt?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arrays starten in C und C++ beim Index 0.

Um 2 Elemente aufzunehmen läuft der Index von [0] zu [1]. Das 
abschliessende Nullbyte kommt nach [2]...

  pcString[length+1] = '\0';      // Nullterminierung

  for (int i=0;i<= length;i++)
  {
    pcString[length-i]= pcZahl[i];
  }

Dieser Code berücksichtigt das nicht. Der Fehler wird durch das reverse 
Kopieren begünstigt. Das abschliessende Nullbyte aus pcZahl wird auf das 
erste Element (Zeichen) von pcString kopiert und schwupp hast du einen 
Leerstring.

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@rufus: Im Debugger liest er die Zahl korrekt ins Array ein.

@stefb: Also muß es heißen:  pcString[length+2] = '\0';

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach jetzt hab ich es kapiert. Der Befehl

pcString[length-i]= pcZahl[i];

Speichert die '\0' in das erste Element von meinem String und schwubs 
und er ist weg.

Danke für die Hilfe

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geh das hier:
BigInt::BigInt(const char *const pcZahl)
{
  length = strlen(pcZahl);

  pcString  = new char[length+1];    //neuer Stringpointer

  pcString[length+1] = '\0';      // Nullterminierung

  for (int i=0;i<= length;i++)
  {
    pcString[length-i]= pcZahl[i];
  }
}

bitte mal mit Papier und Bleistift durch.
Nimm an, der Konstuktor wird mit dem Text "123"
aufgerufen.

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+

  length = strlen(pcZahl);

da gibt es also eine Variable length. Die malst
du gleich mal auf dein Papier:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+

   length
   +-------+
   |       |
   +-------+

und wenn wir mal davon ausgehen, dass strlen das richtige
Ergebnis bringt, dann bekommt length den Wert 3. Also
schreibst du eine 3 in deine Variable hinein:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+

   length
   +-------+
   |   3   |
   +-------+


 pcString  = new char[length+1];

hier wird ein Array der Länge length+1 angelegt. length
hat den Wert 3, also wird ein Array der Länge 4 angelegt
und ein Zeiger darauf in der Variable pcString abgelegt:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |   |   |   |
   +-------+       +---+---+---+---+

  pcString[length+1] = '\0';      // Nullterminierung

Aha. Im Array auf das pcString zeigt, wird ein Byte auf
'\0' gesetzt. Welches? das mit dem Index 4. Also zähl
mal im Array ab, welches das ist. Aber achte darauf:
In C++ wird bei 0 zu zählen angefangen:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |   |   |   |
   +-------+       +---+---+---+---+
                     0   1   2   3   4

Hoppla: Das Element 4 ist gar nicht mehr im Array. D.h.
du schreibst die '\0' in rigendwelchen Speicher. Kein
Mensch weis, was du dabei überschreibst, aber was solls.

  for (int i=0;i<= length;i++)

Eine for Schleife. i wird alle Werte von 0 bis
length annehmen (schau auf dein Papier: length hatte
den Wert 3). Also wird i nacheinander die Werte 0, 1, 2, 3
annehmen.

Soweit so gut. Was passiert innerhalb der Schleife:

    pcString[length-i]= pcZahl[i];

OK. pcZahl[i]. i hat den Wert 0, also wird worauf zugegriffen:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+
    0   1   2    3
   ***  <- hier

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |   |   |   |
   +-------+       +---+---+---+---+


Es wird also die '1' aus dem Array geholt und irgendwo ab-
gespeichert. Wo? In pcString[length-i]
Auch das suchen wir mal auf dem Papier. length war 3, i ist
0, also ist 3 - 0 gleich 3 und du suchst im pcString Array
das Element mit dem Index 3

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+
    0   1   2    3
   ***

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |   |   |   |
   +-------+       +---+---+---+---+
                     0   1   2   3
                                ***   <- hier

Dort wird also die '1' abgelegt. Machen wir das mal:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+
    0   1   2    3

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |   |   |'1'|
   +-------+       +---+---+---+---+

nächster Schleifendurchlauf: i hat jetzt den Wert 1
und wieder gilt es auszuführen

    pcString[length-i]= pcZahl[i];

length ist immer noch 3, i ist jetzt 1, also steht
da

   pcString[3-1] = pcZahl[1];

3-1 ist 2, also findet die Operation so statt:

  pcZahl
  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+
    0   1   2    3
       ***

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |   |'2'|'1'|
   +-------+       +---+---+---+---+
                     0   1   2   3
                            ***

Nächster Schleifendurchlauf: i hat jetzt den Wert 2
(Ich spar mir jetzt das genaue Aufschlüsseln)

  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+
    0   1   2    3
           ***

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +---+---+---+---+
   |   o---------->|   |'3'|'2'|'1'|
   +-------+       +---+---+---+---+
                     0   1   2   3
                        ***

und zuguterletzt wird die Schliefe noch mal mit einem
Wert von 3 für i ausgeführt:

  +---+---+---+----+
  |'1'|'2'|'3'|'\0'|
  +---+---+---+----+
    0   1   2    3
                ***

   length
   +-------+
   |   3   |
   +-------+

   pcString
   +-------+       +----+---+---+---+
   |   o---------->|'\0'|'3'|'2'|'1'|
   +-------+       +----+---+---+---+
                     0   1   2   3
                    ***

und jetzt schau dir mal das Ergebnis im pcString Array
genau an. Benenke auch: Ein String ist genau dann zuende
wenn ein Byte mit dem Wert '\0' angetroffen wird.

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die kleine Lehrstunde, ich hab noch einiges zu lernen.
Mach mich gleich dran....

Danke

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.