C++ Problem mit feldern und Konstanten

Fonce

Vice Admiral Special
Mitglied seit
03.08.2005
Beiträge
620
Renomée
1
  • SIMAP Race
Hi
wir sollen in der Schule ein Programm schreiben für nen Stack
nun habe ich das Problem das ich bei der Feld deklaration ne Constante brauche aber ich nicht weiss wie ich diese aus der main funktion richtig übergebe bzw. wie ich nen int wert in einer const speichern kann
den bei der Felddeklaration in der Methode eingabe der Klasse Stack brauche ich ja eine Konstante

PS: isn bisl komisch erklär aber ich weiss nicht wie ich sonst erklären soll
beim blick auf den quelltext sollte das problem aber klar werden

Code:
#include <iostream>
#include <cstring>

using namespace std;

class Stack
{
  private:
    int *data;
    int anz;
	int size;
    int long maxanz;

  public:
     Stack(long);
    ~Stack();
    bool Push(int);
    int Pop(void);
    bool isEmpty(void);
	bool eingabe(void);
};

Stack::Stack(long s)
{
  size=s;
  data=new(int[s]);
  if(data)
    {
      anz=0;
      maxanz=s;
    }
  else
    {
      anz=maxanz=0;
    }
}

Stack::~Stack()
{
  if(data) delete[](data);
}

bool Stack::Push(int w)
{
  if(anz<maxanz)
    {
      data[anz++]=w;
      return(true);
    }
  else
    {
      return(false);
    }
}

int Stack::Pop(void)
{
  if(anz>0)
    return(data[--anz]);
  else
    return(0);
}

bool Stack::isEmpty(void)
{
  return(anz==0);
}

bool Stack::eingabe(void)
{
	char str[size];
	cin.getline(str,size);

	if(strlen(str)>0)
	{
		return true;
	}
	else
	{
		return false;
	}
	
}

int main()
{
	const SIZE=10;
	Stack stack(SIZE);
	/*char str[SIZE];
	int x;
	cin.getline(str,SIZE);

	for(x=0;x<strlen(str);x++)
	{
		stack.Push(str[x]);
		//cout << endl;
	}
	while(!stack.isEmpty())
	cout << static_cast<char>char(stack.Pop());
	cout << endl;*/
	return 0;
}
 
Die Konstante an den Anfang des Moduls schreiben (nach den #includes, außerhalb der Klasse)
const int size = 123;
 
ich will die Variable aber nicht global deklariert haben den das programm wird später noch ein bisl abgeändert um als Header genutzt werden zu können
die Konstante im main wird dann später halt ne variable sein
das problemist halt das ich die Größe das Feld in der Methode eingabe variable haben will(soll von main kommen) aber die größe des Feldes kann nur mit einer konstanten Variablen festgelegt werden
und ich weiss halt nicht wie ich dies umgehen kann

hoffe es ist nun verständlicher geschrieben8)
 
Das habe ich befürchtet ;)

Man kann die Variablendefinition natürlich auch ins Headerfile schreiben. Ein ungewollter, aber kaum störender Nebeneffekt ist, dass es die Variable in jedem Modul gibt, das den Header inkludiert.

Bei C würde das so nicht funktionieren, da würde sich der Linker über Mehrfachdefinitionen beschweren.

Oder man macht es mit dem guten, alten #define. Ist zwar nicht state of the art, aber hier die effizienteste Lösung.

Absolute OO-Verfechter sagen an der Stelle, dass man bei OO in Klassen überhaupt keine Felder mehr braucht (statt dessen stdlib), was so auch kaum stimmt.;)
 
Wie wär's mit const int SIZE? Du musst dem Compiler schon sagen welchen Typ die Konstante hat.

Btw. long und int sind das selbe.

So funktioniert die main:

Code:
int main()
{
	const int SIZE=10;
	Stack stack(SIZE);
	char str[SIZE];
	int x;
	cin.getline(str,SIZE);

	for(x=0;x<strlen(str);x++)
	{
		stack.Push(str[x]);
		//cout << endl;
	}
	while(!stack.isEmpty())
	cout << static_cast<char> (stack.Pop());
	cout << endl;
	return 0;
}
(bei dem cout ist bei dir noch ein Fehler)
 
Zuletzt bearbeitet:
Na du hast nicht gesagt, dass man die Konstante auch direkt in der Funktion deklarieren kann, das geht nämlich auch. Und da C++ eigentlich auch beliebige Objekte als Konstante unterstützt (also auch irgendwelche neu definierten Klassen... glaub ich zumindest) musst du den Typ der Konstante immer angeben.
 
Na du hast nicht gesagt, dass man die Konstante auch direkt in der Funktion deklarieren kann, das geht nämlich auch. Und da C++ eigentlich auch beliebige Objekte als Konstante unterstützt (also auch irgendwelche neu definierten Klassen... glaub ich zumindest) musst du den Typ der Konstante immer angeben.
Die Frage war aber, wie die Konstante in der Funktion "eingabe" verfügbar gemacht wird. Wie geht das jetzt über die main-Funktion? Das habe ich noch nicht verstanden. ;D

Zum Typ: Das hängt einzig von der Mäkeligkeit des Compilers ab. Der MS C++ 6.0 - Compiler spuckt da noch nicht mal 'ne Warnung aus.

Edit:
Ich ging davon aus, dass die Konstante an mehreren Stellen gebraucht wird. Wenn dem nicht so ist, dann reicht natürlich eine lokale Definition oder einfach nur der numerische Wert ohne den Umweg über die Variable.
 
Zuletzt bearbeitet:
Hmm... ok, manchmal sollte man doch etwas genauer lesen :].

Ein template wär sicher auch eine Möglichkeit, in jedem Fall wär's schnell und würde, wenn die Konstante immer nur einen Wert hat, auch nur einmal Code produzieren. Ansonsten vielleicht ein const int als Parameter, das gibt aber mit dem array reibereien (müsste man dann dynamisch erzeugen).

Hmm... ja. Ist aber ein bisschen mit Kanonen auf Spatzen geschossen, einfacher wär's das char[] in eingabe einfach dynamisch zu allokieren. Hängt ganz davon ab, was mit der Konstante gemacht werden soll.
 
ähm also in der main Funktion hatte ich nen ganzen teil auskommentiert
dort spielen nur die ersten zwei Zeilen eine rolle
nämlich zum einen die Variablen deklaration(das ich hier auch nen int wert und keine Konstante brauch weiss ich) und zum anderen der aufruf der Kontruktors

wie schon oben gesagt soll die Klasse später in eine Header Datei ausgelagert werden
ich müsste nur wissen wie ich einer Konstanten einen wert zuweise welcher aber variabel ist
den dann kann ich mit dem was ich habe ohne probleme weiter arbeiten.

hoffe es wird deutchlier was ich von euch wissen will^^
aber macht nichts mein Lehrer hat auch zwei Stunden gebraucht um zu verstehen wie ich in den Programm vorgehen will*lol*
nur konnte er mir auch nich weiter helfen weil die Stunde zuende war:]
 
Na du wirst nicht drum herum kommen die Konstante global zu deklarieren, wenn du in der main und der Klasse darauf Zugriff haben willst.
 
Aber bitte das zugehörige delete nicht vergessen ;). Btw. Konstanten zeichnen sich nunmal dadurch aus, dass sie konstant sind... daher auch der Name... glaub ich *suspect*.
 
ok werds später dann mal probieren

das Konstanten den namen haben weil sie konstant sind is mir klar
nur da man Konstanten bei der Deklaration eines Feldes verwenden kann hatte ich mir gedacht das es doch nen weg geben muss um Sie zuzuweisen
 
@Fonce

So wie die Dinge in der Schule typischerweise laufen wird das Thema vermutlich nicht mehr aktuell sein, aber ich hoffe mal Du gehörst zu denen, die sich auch danach noch dafür interessieren.

PHP:
bool Stack::eingabe(void)
{
	char str[size];
	cin.getline(str,size);

	if(strlen(str)>0)
	{
		return true;
	}
	else
	{
		return false;
	}
	
}

So wie das da steht überprüft Stack::eingabe() lediglich OB etwas eingegeben wurde - WAS wird direkt wieder dem digitalen Alzheimer anheim gegeben. Soll das so sein ? Oder hast Du vor die Eingabe auf dem Stack abzulegen ? Dann müßtest Du z.B. intern Pushen


Offen gestanden - die eigendliche Frage mit der Konstante hab ich immer noch nicht 100% verstanden - also nochmal für Blöde: Was genau soll denn die Konstante speichern ? Die Stackgröße ? Ist besser dynamisch so wie Du das bisher machst. Was anderes seh ich derzeit nicht - aber das soll ja nix heißen. Wenn die Stackgröße gemeint ist wird die einzig und allein mit dem Konstruktor mitgeteilt - sonst garnicht. Falls Du das wegen der Methode eingabe brauchst:

statt
PHP:
char str[size];

erzeugst das dynamisch
PHP:
char* str = new char[size];

Allerdings liegt dann str nicht auf dem Stack (nicht Deine Klasse, sondern der "normale") sondern auf dem Heap - mußt also nach Gebrauch auch selber wieder abräumen. Sonst hast auf Dauer Speicherleaks (merkt man bei kleinen Programmen natürlich nicht - solltest Dir aber natürlich dennoch angewöhnen).

PHP:
delete str;




PHP:
int Stack::Pop(void)
{
  if(anz>0)
    return(data[--anz]);
  else
    return(0);
}

Fleißig Nullen zurückgeben, wenn der Stack empty ist ist unschön. Aber das geht wohl deutlich über das hinaus, was Du erledigen solltest.
Btw - das klammern der return-Werte kostet nur Toner beim Ausdruck ;-)



Mit dem ÄNDERN von Konstanten solltest Du bitte gleich aus dem Gedächtnis streichen. Klar gibt es die bekannten Tricksereien mit Pointern auf sowas zuzugreifen - und irgendwann wundert man sich, daß mit neuem OS oder Servicepack Schutzverletzungen kommen, weil die Konstanten in nem schreibgeschützten Bereich abgelegt wurden.

Fazit: BITTE AUS DEM GEDÄCHTNIS STREICHEN




Man kann die Variablendefinition natürlich auch ins Headerfile schreiben. Ein ungewollter, aber kaum störender Nebeneffekt ist, dass es die Variable in jedem Modul gibt, das den Header inkludiert.

Namespaces helfen für ein solches Problem ungemein - leider viel zu wenig genutzt.



Kleinigkeit am Rande:
PHP:
	for(x=0;x<strlen(str);x++)
	{
		stack.Push(str[x]);
	}

Sieht nett aus - geht wunderbar - und sehr schnell.

Etwas schneller ist:
PHP:
int length = strlen(str);
for(x=0;x<length;x++)
	{
		stack.Push(str[x]);
	}

Der Optimierer darf strlen() nicht aus der Schleife nehmen und muß die Abbruchbedingung vor jedem Durchlauf prüfen lassen. Macht in diesem Beispiel so ziemlich überhaupt keinen Unterschied - zum die Eingabe ja von Tastatur kommt. Aber der Mensch ist halt ein Gewohnheitstier und später ärgert man sich manchmal wenn man Takte liegen läßt.

So - genug gespammt.

Ich hoffe, daß Dir das ein wenig weiter hilft auf Deinem Weg,
Gruß,
Tom
 
nur zur info
ich hab bis auf die methode Eingabe nichts selber geschrieben von dem Programm
das war unser Lehrer :]
ich selber finde das Programm total sinnlos was ich meinem Lehrer auch gesagt hab aber er willst nunmal haben *noahnung*

wo mach ich den am besten das delete von str hin? dekonstructor?
 
Zuletzt bearbeitet:
wo mach ich den am besten das delete von str hin? dekonstructor?
Wenn str nicht anderswo gebraucht wird, dann ans Ende der Methode. Also nicht in den Destruktor. Alternativ muss bei eingabe() immer abgetestet werden, ob str schon belegt ist. Wenn ja, dann erst löschen.

Wichtig sind die "[]":
delete[] str;
 
Zum Typ: Das hängt einzig von der Mäkeligkeit des Compilers ab. Der MS C++ 6.0 - Compiler spuckt da noch nicht mal 'ne Warnung aus.

Nicht von der Mäkeligkeit, sondern von der Implementierung. Der Standard verlangt nur int <= long. Im LP-Modell ist auf 64bit Architekturen z.B. long 64bit breit, während int 32bit ist. Bei MS mag das noch nicht stören, weil sie das LLP-Modell gewählt haben, aber verlassen sollte man sich darauf auf keinen Fall.
 
Nicht von der Mäkeligkeit, sondern von der Implementierung. Der Standard verlangt nur int <= long. Im LP-Modell ist auf 64bit Architekturen z.B. long 64bit breit, während int 32bit ist. Bei MS mag das noch nicht stören, weil sie das LLP-Modell gewählt haben, aber verlassen sollte man sich darauf auf keinen Fall.
Meine Bemerkung bezog sich auf die Anweisung:
const SIZE=10;

Was hat das jetzt mit long oder int zu tun?*noahnung*
 
Zurück
Oben Unten