C++ Prüfen, ob der Stack voll ist

Life Sucks

Cadet 2nd Year
Registriert
Juli 2018
Beiträge
29
C++:
#pragma once
#include <string>

class FixedCapacityOfStack
{
private:
    std::string* k;
    int N;
public:
    FixedCapacityOfStack(int capacity)
    {
        k = new std::string[capacity];
        N = 0;
    }
    bool isEmpty() { return N == 0; }
    bool isFull()
    {
        //int m = sizeof(k);
        //if (m == N)
            //return true;
    }
    void push(std::string item) { k[N++] = item; }   
    std::string pop() { return k[--N]; }

};

Hallo,
also ich bin auf der Suche nach einer Methode zum überprüfen, ob der Stack voll ist. Ich hab einen Ansatz aber er funktioniert nicht. Er gibt nur aus, wie viele Elemente drinnen sind. Ich möchte irgendwie die Kapazität mit
C++:
N
vergleichen(siehe Zeile 16 - 21). Hat einer eine Idee?
 
Meine erste Fraghe die ich da hätte ist warum die Capacity in einem String k gespeichert wird...?

Und zweitens, sizeof liefert dir die Größe im Speicher (also wie viele Bytes ein Datentyp belegt)... für die Umwandlung eines Strings in einen int gibt es andere (Parser-)Methoden. Mit dem Stichwort solltest du sie finden können.
 
es es ist vieles falsch der Name is falsch es ist StackOfFixedCap...

k ist ein pointer mit dem type std::string deswegen kriegst du bei sizeof(k) == 4 oder 8 byte das geht nur mit array also
int arr[10];
sizeof(arr) == 40

speicher capacity als private member in die klasse.
wenn ihr schon templates gemacht hat hier würde ich sie benutzen!

also
class x
{
private:
const int m_MaxSize {0};
public:
x(cap) : m_MaxSize(cap){};
}

dann musst du nur noch N mit m_MaxSize vergleichen. du hast new[] ohne ein delete[] das ist immer ein fehler. benutze doch einfach STL container am besten std::vector mit template.
 
  • Statt eines Strings nimm eine Liste/Array/Vergleichbares, zB object[] oder sowas.
  • Dann hast Du notwendigerweise die Größe des Stacks immer dabei und kannst jederzeit mit der Arraylänge vergleichen.
  • Bei Bedarf kann man dem Konstruktor dann auch eine MaxSize-Property mitgeben und die dann in irgendeiner privaten Eigenschaft halten (oder gleich das Array damit initialisieren, wenn man eins verwendet).

- Strings gehen grad noch so als Backend für Stacks mit element:char, sollte man sich aber nicht angewöhnen. Zu spezifisch.
 
#pragma once
sagt mir das du alles in den header schreibst. das ist falsch weil du den header mehrfach inkludierst. du wirst linker error bekommen.
Ergänzung ()

RalphS schrieb:
  • Statt eines Strings nimm eine Liste/Array/Vergleichbares, zB object[] oder sowas.
  • Dann hast Du notwendigerweise die Größe des Stacks immer dabei und kannst jederzeit mit der Arraylänge vergleichen.
  • Bei Bedarf kann man dem Konstruktor dann auch eine MaxSize-Property mitgeben und die dann in irgendeiner privaten Eigenschaft halten (oder gleich das Array damit initialisieren, wenn man eins verwendet).
- Strings gehen grad noch so als Backend für Stacks mit element:char, sollte man sich aber nicht angewöhnen. Zu spezifisch.
Er hat einen stack von strings! nicht der string ist der stack. und c++ std::string kommt von einen template niemand würde ihn aufhalten std::basic_string<int> zu benutzen.
 
Multivac schrieb:
sagt mir das du alles in den header schreibst. das ist falsch weil du den header mehrfach inkludierst. du wirst linker error bekommen.
Kannst du das näher erläutern? Afaik ist es völlig I.O. alles in den Header zu schreiben, egal wie oft man ihn inkludiert (solange #pragma once o.ä. vorhanden ist).
 
  • Gefällt mir
Reaktionen: Kanibal und nullPtr
danke, ich hatte mittlerweile selber mal probiert und habe eine extra variable im private erstellt, und dann im Rumpf des Konstruktors die capacity einfach der extra variable übergeben. Was dem Namen angeht, ich habe beim erstellen der Header Datei den Namen falsch eingeben und dann war ich faul es umzuändern daher habe ich so einfach weitergemacht. Mir ist bewusst, das das nicht korrekt ist, aber ist halt nur zu Übungszwecken.
 
Multivac schrieb:
Er hat einen stack von strings!
Und das hab ich falsch gesehen... ups! Also vergiss meine Frage von wegen String, hab das irgendwie falsch verstanden was du da machst.

Einfachste Variante wäre dass du dir die übergebene Capacity in einem zusätzlichen int speicherst, dann hast du sie zum vergleichen parat (hast du wohl selber schon gemacht wenn ich das aus deinem letzten Post so rausles)
 
Multivac schrieb:
#pragma once
sagt mir das du alles in den header schreibst. das ist falsch weil du den header mehrfach inkludierst. du wirst linker error bekommen.

Ja hab alles in der header. Ich inkludiere alles ja nur einmal. Aber auch wenn würden da keine Errors auftauchen. Könnte z.B. das mit #ifndef, #def machen. Aber pragma once tut es auch. Also soweit ich weiß.
 
  • Gefällt mir
Reaktionen: new Account()
C++:
#pragma once
#include <list>
#include <string>

class FixedCapacityOfStack
{
private:
    std::list<string> k;
    unsigned int N;
public:
    FixedCapacityOfStack(int capacity)
    {
        N = capacity;
    }
    bool isEmpty() { return k.length() == 0; }
    bool isFull()
    {
        return k.length() == N;
    }
    void push(std::string item) { !isFull() ? k.push_back(item); }
    std::string pop() { return k.pop_back(); }

};

So etwa?

C++ std list kann doch schon Stack?

Update: Ich muss natürlich list benutzen...
 
Zuletzt bearbeitet von einem Moderator:
ne also ich hab eine variable die immer erhöht wird, wenn ich pushe une verringert wenn ich pope. Dann vergleiche ich die mit der Variable die ich extra eingeführt habe.
Hier mal mein code:
C++:
#pragma once
#include <string>
#include <iostream>

class FixedCapacityOfStack
{
private:
    std::string* k;
    int N, maxCapacity;    //siehe hier
public:

    FixedCapacityOfStack(int capacity)
    {
        k = new std::string[capacity];
        N = 0;
        maxCapacity = capacity;    //siehe hier
    }
    bool isEmpty() { return N == 0; }
    bool isFull() { return maxCapacity == N; } //siehe hier
    

    void push(std::string item) { k[N++] = item; }   
    std::string pop() { return k[--N]; }

};
 
Du programmierst einen std::vector nach.
Bloß dass in deiner Implementierung einige Unzulänglichkeiten sind.
 
new Account() schrieb:
Kannst du das näher erläutern? Afaik ist es völlig I.O. alles in den Header zu schreiben, egal wie oft man ihn inkludiert (solange #pragma once o.ä. vorhanden ist).

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
3.2 One definition rule [basic.def.odr] 1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

und jetzt guck dir einfach noch mal an was #pragma once macht.
Ergänzung ()

wayne_757 schrieb:
Du programmierst einen std::vector nach.
Bloß dass in deiner Implementierung einige Unzulänglichkeiten sind.
hier geht es ja ums lernen er könnte ja auch einfach std::stack nehmen :D
 
Und jetzt lies noch §3.2.6. Ein "pragma once" (oder Include-Guards) ist völlig ausreichend, weil dieselbe Definition in verschiedenen Translation-Units erlaubt ist. :)

OT: Wenn das keine Übung ist, schau dir mal den Adapter std::stack (https://en.cppreference.com/w/cpp/container/stack) an. Außerdem in modernem C++ nie selbst allozieren. Entweder std::vector oder std::unique_ptr verwenden. Deiner Klasse feht nämlich direkt der Destruktor.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: new Account()
Das es ausnahmen geben muss für templates ist mir nicht neu. Es ist ja klar das jede translation unit in der Lage sein muss um aus einen Muster eine richtige Funktion zu erzeugen. wichtig ist hier das auch inline funktions erlaubt sind. ohne weiteres geht es nicht bsp.

C++:
#pragma once
#include <iostream>
struct foo{
    void bar();
};
void foo::bar(){
    std::cout << "foobar\n";
}

Kopiere diesen code in zwei *.cpp files und kompiliere. der linker wird dir erklären das es zwei foo::bar(void) gibt und das ist ein Problem. jetzt einfach mal die frage warum geht dass was OP geschrieben hat? Hand hoch wer es weiß.

C++:
foo{ 
   void bar() {} 
}

hier wird bar() implizit inline. So jetzt sollten wir uns die frage stellen wollen wir das?

C++:
#pragma once
#include <iostream>
struct foo{
    void bar();
};
inline void foo::bar(){
    std::cout << "foobar\n";
}

kompilieren wir noch mal eine version mit inline und vergleichen, werden wir feststellen das die obj files bei der inline Variante deutlich größer werden. Der compiler hat für beide translation units code erzeugt. ihr wollt nicht das der compiler für jede translation-unit den code neu erzeugt. der wird zwar vom linker wieder entfernt. und nun das beste #pragma once hat absolut nichts damit Zutun.

Bei der nächsten Übung wird er über eine Funktion stolpern.

C++:
void foobar() {
  std::cout << "hello, world";}
}

und er wird nicht verstehen können was falsch ist wenn er linker Fehler bekommt.

§3.2.6. ist eine liste mit ausnahmen.
 
Richtig, das geht nur mit inline-Funktionen/Methoden. OP hat die aber. Für nicht-inline-Funktionen hat 3.2.6 auch keine Ausnahme.

Dein zweites Beispiel ist in der Tat gut und ich bin da voll bei dir: Inline-Funktionen mit externer Linkage sind mit Vorsicht zu genießen. Weil sie Code-Optimierungen auf der Caller-Seite verhindern können und den Compiler zwingen (meist ungewollten) Code zu erzeugen.
 
Zurück
Oben