Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Stack - Zuweisungsfunktion

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
22.05.2007, 17:37 Uhr
~Michael1984
Gast


Hallo,

ich bin am Verzweifeln.
Und zwar sollen wir einen Stack in C++ implementieren:

class StackDbl {
int size;
double *pa;


Und dazu nun eine Zuweisungsfunktion schreiben:
StackDbl &assignStackDbl(StackDbl &to, const StackDbl &from);


Nun probiere ich die ganze Zeit schon rum, aber ich habe immer Probleme, wenn ich neuen Speicher alloziere, dass Elemente aus dem zweiten Stack gelöscht werden.

Hier mal ein Ausschnitt aus dem Code, ist gerade mitten in der Bastelphase, daher kann es sein, dass einige Variablen überflüssig sind:

javascript:insert_tag('
C++:
','
',1)

C++:
StackDbl &assignStackDbl(StackDbl &to, const StackDbl &from)
{
   int i, j, error = 0;
   double *pa_tmp;
  
   delete [] to.pa;  
   for (to.size = 0; to.size < (from.size); to.size++) {
      if ((to.size % BLOCKSIZE) == 0) {
       //  if (to.size > 0) {
            printf("Element(11) %.2f von from\n", from.pa[10]);
            /*Diese Allokation zerschießt FROM ab BLOCKSIZE!!!*/
            pa_tmp = new(nothrow)double[(to.size) + BLOCKSIZE];
            printf("Element(11) %.2f von from\n", from.pa[10]);
            if (pa_tmp == 0)
               error = 1;
            else {
               for (i = 0; i < to.size; i++)
                  pa_tmp[i] = to.pa[i];
               delete [] to.pa;
                to.pa = pa_tmp;
                delete [] pa_tmp;
            }
     /*     }
         else {
            to.pa = new(nothrow)double[BLOCKSIZE];+
            printf("Element(11) %.2f von from\n", from.pa[10]);
             if (to.pa == 0)
               error = 1;
         }*/

       }
       if (error == 0) {
         to.pa[to.size] = from.pa[to.size];
         to.size++;
      }
   }

   return to;
}


Unser Prof möchte gerne, dass Speicher immer in BLOCKSIZE-Größe (hier 10) angefordert wird, sofern es möglich ist.

Kann mir vielleicht jemand helfen? :-(
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
22.05.2007, 18:21 Uhr
(un)wissender
Niveauwart


Die Allokation ist ok. Zeig mal mehr Code vom StackDbl.
Wobei die ganze Logik von assignStackDbl völlig unlogisch erscheint.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
22.05.2007, 18:24 Uhr
0xdeadbeef
Gott
(Operator)


Au weia, da hat der Prof aber von C++ nicht besonders viel Ahnung. Die Datenmember public? Ts, ts.

Wenn ich das mal in sinnvoll umstrukturiere,

C++:
#include <cstddef>
#include <exception>

class StackDbl {
public:
  typedef std::size_t size_type;

  struct empty : public std::exception {
    virtual char const *what() const throw() { return "stack is empty"; }
  };

  StackDbl();
  ~StackDbl();

  inline size_type size() const throw() { return size_; }
  void push(double d);
  double peek() const throw(empty);
  double pop ()       throw(empty);

  StackDbl &operator=(StackDbl const &s);

private:
  static size_type const BLOCKSIZE;

  void increase_reserve_if_necessary();

  size_type size_;
  size_type reserved_;
  double *data_;
};

#include <algorithm>
#include <iostream>

StackDbl::size_type const StackDbl::BLOCKSIZE = 10;

StackDbl::StackDbl()
  : size_(0U),
    data_(new double[BLOCKSIZE]),
    reserved_(BLOCKSIZE) { }

StackDbl::~StackDbl() { delete[] data_; }

void StackDbl::push(double d) {
  increase_reserve_if_necessary();
  data_[size_++] = d;
}

double StackDbl::peek() const throw(StackDbl::empty) {
  if(size_ == 0) throw empty();
  return data_[size_ - 1];
}

double StackDbl::pop() throw (StackDbl::empty) {
  if(size_ == 0) throw empty();
  return data_[--size_];
}

void StackDbl::increase_reserve_if_necessary() {
  if(size_ == reserved_) {
    double *tmp = new double[reserved_ + BLOCKSIZE];
    std::copy(data_, data_ + size_, tmp);
    delete[] data_;

    data_ = tmp;
    reserved_ += BLOCKSIZE;
  }
}


StackDbl &StackDbl::operator=(StackDbl const &s) {
  double *tmp = new double[s.reserved_];

  std::copy(s.data_, s.data_ + s.size_, tmp);

  delete[] data_;

  data_ = tmp;
  reserved_ = s.reserved_;
  size_ = s.size_;
}


int main() {
  StackDbl s1, s2;

  s1.push(2.0);
  s1.push(3.0);

  s2 = s1;

  std::cout << s2.pop() << std::endl;
  std::cout << s2.pop() << std::endl;
}


Der fett markierte Code ist die Zuweisung.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 22.05.2007 um 18:27 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
22.05.2007, 18:28 Uhr
~Michael1984
Gast


Oh, der Prof ist eigentlich ziemlicher Pro in seinem Fach

Ich würde gerne mehr Code zeigen, aber dann gibt es wieder Ärger, weil man damit es auch den anderen Studis zur Verfügung stellt.

Ich werde, wenn ich heute Abend wieder da bin, noch einmal etwas dazu schreiben.

Vielen Dank schonmal für die Antworten.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
22.05.2007, 18:30 Uhr
~Michael1984
Gast


Bin gerade noch einmal den anderen Code überflogen:


Operator= dürfen wir für diese Lösung nicht verwenden!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
22.05.2007, 18:34 Uhr
0xdeadbeef
Gott
(Operator)


Dann nenns halt irgendwie anders, läuft auf das selbe raus. Du wirst die Funktion, wenn sie kein member sein soll, evtl. als friend deklarieren müssen, um direkten Zugriff auf die privaten Member zu erhalten.

Allerdings - ein Prof, der

C++:
StackDbl &assignStackDbl(StackDbl &to, const StackDbl &from)


...und öffentliche Member size und pa vorschlägt (die übrigens so, wie sie in der genannten Deklaration stehen, private sind, d.h. du hast gar keinen Zugriff darauf), der hat von C++ nicht besonders viel Ahnung. Das ist ein alter C-Coder. Groooßer Unterschied.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
22.05.2007, 18:56 Uhr
(un)wissender
Niveauwart


ich hoffe den Code kannst so benutzen, sind keine abgehobenen Sachen drin.


C++:
#include <iostream>

class StackDbl
{
public:
    StackDbl(unsigned initial_size = 0);
    StackDbl(StackDbl const& from);    
    StackDbl& operator=(StackDbl const& from);
    ~StackDbl();
    
    bool isEmpty() const;
    double top() const;
    void push(double value);
    void pop();
    
    void print() const;
      
private:
    void assign(StackDbl const& from);
    
    int index; // zeiger aufs aktuelle element
    unsigned capacity; //größe des containers
    double * container; //der speicher
    
    static unsigned const BLOCKSIZE;
};

unsigned const StackDbl::BLOCKSIZE = 10;

StackDbl::StackDbl(unsigned initial_size)
{
    container = new double[initial_size];
    capacity = initial_size;
    index = -1;
}

StackDbl::StackDbl(StackDbl const& from)
{
    container = 0;
    capacity = 0;
    index = -1;
    assign(from);
}

StackDbl& StackDbl::operator=(StackDbl const& from)
{
    assign(from);
}  

StackDbl::~StackDbl()
{
    delete [] container;
}    

bool StackDbl::isEmpty() const
{
    return index < 0;
}
    
double StackDbl::top() const
{
    if(isEmpty()) throw "Stack empty!";
    return container[index];
}
    
void StackDbl::push(double value)
{
    //bisher zu klein
    if(capacity == unsigned(index + 1))
    {
        //blocksize dazu
        double * temp = new double[capacity + BLOCKSIZE];
        //alten werte kopieren
        for(unsigned i = 0; i < capacity; ++i)
        {
            temp[i] = container[i];
        }
        
        //neue größe merken
        capacity += BLOCKSIZE;  
        //alten speicher weg
        delete [] container;
        container = temp;                  
    }  
    
    container[++index] = value;  
}
    
void StackDbl::pop()
{
    if(isEmpty()) throw "Stack empty!";
    --index;
}

void StackDbl::assign(StackDbl const& from)
{
    //unser container ist zu klein
    if(capacity < from.capacity)
    {
        delete [] container;
        capacity = from.capacity;
        container = new double[capacity];      
    }  
  
    index = from.index;  
    
    //alten werte kopieren
    for(unsigned i = 0; i < index + 1; ++i)
    {
        container[i] = from.container[i];
    }  
}  

void StackDbl::print() const
{
    std::cout << "Capacity: " << capacity << std::endl;
    std::cout << "Index: " << index << std::endl;
    for(int i = 0; i < index + 1; ++i)
    {
        std::cout << container[i] << ' ';
    }
     std::cout << std::endl;  
}  

int main()
{
    StackDbl stack, stack2;
    stack.push(1.);
    stack.push(2.);
    stack.push(3.);
    stack.print();
    stack2.print();
    stack2  = stack;
    stack2.print();
}


--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
22.05.2007, 18:57 Uhr
(un)wissender
Niveauwart


Ups zu langsam...
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
22.05.2007, 18:58 Uhr
(un)wissender
Niveauwart


Ach ja, operator= MUSS implementiert werden, da diese Klasse dynamischen Speicher anfordert.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
22.05.2007, 19:00 Uhr
(un)wissender
Niveauwart


Ach ja, immer besser erst allokieren (weil wegen wenn Ausnahme), dann den alten Kram löschen, ist schon eine Zeit her bei mir mit C++.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: