Forum: PC-Programmierung Stapelspeicher in C


von Kimi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich brauche bitte dringend Hilfe bei dem Thema Stapelspeicher in C, um 
die anstehende Klausur zu schaffen (bin leider im letzten Versuch und 
nein ich studiere kein Info). Ich hoffe jemand ist so nett und hilft mir 
Schritt für Schritt?

1.) Geben Sie die Strukturen für den gegeben Stapel mit den Datentypen 
stack_t und frame_t an
[c]
typedef struct stack{
   frame_t *top;
   int size;
}stack_t;

typedef struct frame{
  frame_t *previous;
  double value;
}frame_t;

2.)
Implementieren Sie eine Funktion push, die ein Nutzdatenobjekt oben auf 
den Stapel "auflegt".
Nutzdaten werden als Zeiger an die Funktion ¨ubergeben und m¨ussen nicht 
erst allokiert
werden. Ist das Argument ein Nullzeiger, so nimmt die Funktion keine 
Ver¨anderungen am.
Hier ist eigentlich mein größtes Problem, ich weiß nicht wie der 
Prototyp der Funktion auszusehen hat. Ich denke mal ich muss hier was 
mit der Nutzdatenstruktur anfangen(void(frame_t *frame)?)

3.)Implementieren Sie eine Funktion double top(void), die den obersten 
Wert des Stapels liefert, ohne ihn zu entfernen. Ist der Stapel leer so 
wird 0 zurückgeliefert.

von Oliver S. (oliverso)


Lesenswert?

Oh je...
Sowas wie void(frame_t *frame) als Antwort auf die Frage lässt 
befürchten, daß das tatsächlich deine letzte Klausur wird.
1
void push(double* Nutzdaten);
2
double Top(void);

Und bei allem nötigem Respekt, ich wette, daß die Lösungen dazu
A) in der Schulstunde
B) in den Hausaufgaben
C) im Netz

vorkommen.
Viel Glück.

Oliver

von Kimi (Gast)


Lesenswert?

Ich wollte die Aufgabe nur verstehen, bis zur Klausur habe ich ja noch 
reichlich zeit (einen Monat). Und ich dachte jetzt schon anfangen kann 
gar nicht verkehrt sein. Okey danke, dass heißt wohl Nachhilfe suchen.

von Kimi (Gast)


Lesenswert?

Und das sollte nicht die ganze Antwort sein bei 2., ich wollte nur 
wissen wie die Funktion als Prototyp aussieht.

von Linksammler (Gast)


Lesenswert?

Dann schau dir die Aufgabenstellung nochmal genau an.

push soll auf einen bestehenen Stack (1. Parameter) ein neues Element 
(2. Parameter) legen. Kein Rückgabgewert erwähnt. Ich würde den Stack 
wieder zurückgebgen, ist aber egal, "void" tuts auch.

also:
1
void push(stack_t * wohin, frame_t * was) {
2
  if (!was) return;
3
  if (!wohin) return;
4
  was.previous=wohin.top;
5
  wohin.top=was;
6
  wohin.size++;
7
}

Wichtig zum Verständnis: Selber nachvollziehen, ganz altmodisch mit 
Bleistift und Papier, was jede dieser Anweisungen macht.
Dann findest du auch den Fehler. :)

von Oliver S. (oliverso)


Lesenswert?

Linksammler schrieb:
> void push(stack_t * wohin, frame_t * was)

Ähem...

Besser nicht...

frame und frame_t sind die internen Datemstrukturen des Stacks, die 
haben draußen keinen zu interessieren. Die Daten sind vom Typ double.

Gepusht werden Daten, sonst nix. Die Funktion Push muß die dann in die 
internen Strukturen verpacken und einhängen.

Oliver

von Kimi (Gast)


Lesenswert?

Vielen Dank.Muss ich davor nicht etwas allokiert haben, die 
Aufgabenstellung verwirrt mich.
Jetzt wüsste ich nicht was ich mit "was, wohin"ersetzen soll. Soll ich 
dann einfach etwas annehmen?

von Hans Ulli K. (Gast)


Lesenswert?

Schau mal hier :

http://lernfunk.de/media/20202

direkt am Anfang

Und ja allozieren musst du.

von Kimi (Gast)


Lesenswert?

Im Video ist es echt gut erklärt danke!

von Karl H. (kbuchegg)


Lesenswert?

Kimi schrieb:
> Ich wollte die Aufgabe nur verstehen, bis zur Klausur habe ich ja noch
> reichlich zeit (einen Monat).

Das reicht nicht.
Was du da implementieren sollst, ist Stoff im 4. Semester 
Informatik-Studium (Vorlesung Datenstrukturen). Dir fehlen aber die 
Kentnisse, die du dir in den Semestern 1, 2, und 3 hättest aneignen 
sollen.

von Rolf M. (rmagnus)


Lesenswert?

Oliver S. schrieb:
> Linksammler schrieb:
>> void push(stack_t * wohin, frame_t * was)
>
> Ähem...
>
> Besser nicht...

Hans Ulli Kroll schrieb:
> Und ja allozieren musst du.

Aufgabenstellung lesen!

Kimi schrieb:
> Nutzdaten werden als Zeiger an die Funktion ¨ubergeben und m¨ussen nicht
> erst allokiert werden.

von Hans Ulli K. (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Oliver S. schrieb:
>> Linksammler schrieb:
>>> void push(stack_t * wohin, frame_t * was)
>>
>> Ähem...
>>
>> Besser nicht...
>
> Hans Ulli Kroll schrieb:
>> Und ja allozieren musst du.
>
> Aufgabenstellung lesen!
>

Ich habe nicht geschrieben was.

Das jetzt die Nutzdaten schon alloziert sind sagt nicht aus das noch was 
anderes alloziert werden muss.
Oder denkst du der Stack liegt einfach so rum ??

von Rolf M. (rmagnus)


Lesenswert?

Hans Ulli Kroll schrieb:
> Das jetzt die Nutzdaten schon alloziert sind sagt nicht aus das noch was
> anderes alloziert werden muss.

Du meinst, es wurde explizit darauf hingewiesen, daß man den einen 
double nicht dynamisch allokieren, aber trotzdem per Zeiger an die 
Funktion übergeben soll? Was sollte das denn bringen?

> Oder denkst du der Stack liegt einfach so rum ??

Ich vermute, daß das dynamische Speicherhandling hier ganz bewußt 
weggelassen werden soll. In einem real-world-Programm wäre das natürlich 
unsinnig, aber hier handelt es sich um eine Übungsaufgabe.

: Bearbeitet durch User
von Hans Ulli K. (Gast)


Lesenswert?

Den double brauch ich ja nicht zu allozieren.

Ich muss aber meine Listobject, also frame_t allozieren, oder meinen die 
mit Nutzdatenobject das Listobjekt ??.

In real world würde das denn so aussehen

struct object {
        struct object *prev;
        void *item;
};

struct stack {
        struct object *top;
        int size;
};

void *push(struct stack *st, void *data);
void *top(struct stack *st);
void *pop(struct stack *st);
int stack_size(struct stack *st);

Beachte auch das hier

Kimi schrieb:
> 2.)
> Implementieren Sie eine Funktion push, die ein Nutzdatenobjekt oben auf
> den Stapel "auflegt".
> Nutzdaten werden als Zeiger an die Funktion ¨ubergeben und m¨ussen nicht
> erst allokiert
> werden. Ist das Argument ein Nullzeiger, so nimmt die Funktion keine
> Ver¨anderungen am.

Die Nutzdaten werden als Zeiger übergeben !

von Rolf M. (rmagnus)


Lesenswert?

Hans Ulli Kroll schrieb:
> Den double brauch ich ja nicht zu allozieren.

Ja, eben. Warum sollte man das aber explizit erwähnen? Und warum sollte 
der double per Zeiger übergeben werden? Gibt keinen so richtigen Sinn, 
deshalb gehe ich davon aus, daß sich die Aussage

> Nutzdaten werden als Zeiger an die Funktion ¨ubergeben und m¨ussen nicht
> erst allokiert werden.

nicht darauf bezieht.

> Ich muss aber meine Listobject, also frame_t allozieren, oder meinen die
> mit Nutzdatenobject das Listobjekt ??.

Das dachte ich zumindest.

von Karl H. (kbuchegg)


Lesenswert?

Hans Ulli Kroll schrieb:

> Die Nutzdaten werden als Zeiger übergeben !

Das ergibt im Zusammenhang mit dem vorgegebenen Datentyp 'double' keinen 
wirklichen Sinn. Ich denke hier ist 'Nutzdaten' synonym zu 
'Nutzdatenobjekt' zu sehen.

von Hans Ulli K. (Gast)


Lesenswert?

So nochmal gelesen, die NUtzdaten der "double" wird per Zeiger 
übergeben.

Sample mit obigen Prototypen
1
int main (int argc, char **argv)
2
{
3
        double *nutzdaten;
4
        struct stack st;
5
6
        nutzdaten = malloc(sizeof(*nutzdaten));
7
8
        if (push(&st, nutzdaten) == NULL)
9
                pintf("stack push failed\n");
10
11
        /* Jetzt übergabe von NULL Pointer, der Stack soll sich nicht ändern */
12
        /*  Ist das Argument ein Nullzeiger, so nimmt die Funktion keine */
13
        /* Veräanderungen am.*/
14
15
        if (push(&st, NULL) == NULL)
16
              printf("stack push failed\n");
17
18
19
        return 0;
20
}

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Hans Ulli Kroll schrieb:
>
>> Die Nutzdaten werden als Zeiger übergeben !
>
> Das ergibt im Zusammenhang mit dem vorgegebenen Datentyp 'double' keinen
> wirklichen Sinn. Ich denke hier ist 'Nutzdaten' synonym zu
> 'Nutzdatenobjekt' zu sehen.

Obwohl auch das nicht wirklich Sinn ergibt. Auf den einen malloc() im 
push() und den free() im pop() wärs auch nicht angekommen. Ganz im 
Gegenteil: das hätte es sogar vereinfacht ein vernünftiges Testprogramm 
zu schreiben.
Mit der Vorgabe des 'Ausserhalb-Allokierens' verkompliziert sich beim 
Aufrufer wieder alles.

: Bearbeitet durch User
von Hans Ulli K. (Gast)


Lesenswert?

Weiter im Text ...

push und pop lasse ich mal aus, ds soll der Schüler machen.
1
void *top(struct stack *st)
2
{
3
        return st->top->item;
4
}
5
6
int stack_size(struct stack *st)
7
{
8
        return st->size;
9
}

Das einzige, was ich gerade vergessen habe:
Den Stack muss ich ausserhalb von main deklarieren !
1
struct stack st;
2
3
int main(int argc, char **argv)
4
{
5
         /* Der ganze Rest */
6
}

von Max H. (hartl192)


Lesenswert?

Hans Ulli Kroll schrieb:
> Den Stack muss ich ausserhalb von main deklarieren !
Darf man fragen wieso?

von Hans Ulli K. (Gast)


Lesenswert?

Wenn eine Variable in einer Funktion deklariert wird, dann wird diese 
auf dem Stack (CPU) abgelegt.

Der Wert, der Variablen ist nicht definiert.

Ausserhalb von main() sind diese NULL bzw. 0

Ich könnte es auch so machen
1
int main(int argc, char **)
2
{
3
        struct stack st;
4
5
        st.size = 0;
6
}

von Max H. (hartl192)


Lesenswert?

Hans Ulli Kroll schrieb:
> Wenn eine Variable in einer Funktion deklariert wird, dann wird diese
> auf dem Stack (CPU) abgelegt.
und dort bleiben sie auch bis die Funktion beendet wird und wenn man 
einen Pointer darauf an eine Funktion übergibt kann man auch darauf 
zugreifen.

> Der Wert, der Variablen ist nicht definiert.
bis man etwas zuweist und wieso sollte man eine Variable verwenden wenn 
man nichts hineinspeichern will?

> Ausserhalb von main() sind diese NULL bzw. 0
Außerhalb der main ist das Programm zu ende, da interessiert es mich 
nicht mehr was in den Variablen stand und wenn doch würde ich sie 
irgendwie ausgeben.

: Bearbeitet durch User
von Martin (Gast)


Lesenswert?

Das ist doch so einfach:

1
#include <stdio.h>
2
#include <unistd.h>
3
#include <fcntl.h>
4
5
int push(char *text) {
6
        char foo[1024];
7
        sprintf(foo, "echo '%s' >> /tmp/test.log", text);
8
        system(foo);
9
        return 0;
10
}
11
12
int pop(char *text) {
13
        int n;
14
        FILE *foo;
15
        foo = popen("head -n 1 /tmp/test.log", "r");
16
        system("sed '1d' /tmp/test.log > /tmp/tmp.log");
17
        system("cp /tmp/tmp.log /tmp/test.log");
18
        n=fread(text, 1, 1024, foo);
19
        text[n]=0;
20
        fclose(foo);
21
        return 0;
22
}
23
int main() {
24
        char buffer[1025];
25
        push("hello world");
26
        push("hello world 1");
27
        push("hello world 2");
28
        push("hello world 3");
29
        pop(buffer);
30
        printf("%s", buffer);
31
        pop(buffer);
32
        printf("%s", buffer);
33
        pop(buffer);
34
        printf("%s", buffer);
35
        pop(buffer);
36
        printf("%s", buffer);
37
        return 0;
38
}

aber da gibt's noch viel elegantere Lösungen.
Ausserdem darf sich der Prof nicht beschweren, alles ist in C 
geschrieben.

: Bearbeitet durch User
von Rene H. (Gast)


Lesenswert?

Meine Güte! Ihr seid ja eine Truppe.

Var a. : er ist ein Donnerstag Troll (meine Vermutung)
Var b. : google nach linked list und gut ist.

Es Grüsst,
René

von Hans Ulli K. (Gast)


Lesenswert?

ROTFL

von Daniel A. (daniel-a)


Angehängte Dateien:

Lesenswert?

Eine Beispielimplementierung eines Stacks. Könnte hilfreich sein, 
beschränkt sich aber nicht auf double Werte.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.