Stapelspeicher in C

Gast #4020157
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.
Angehängte Dateien:
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
Gast
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.
Gast
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. :)
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
Gast
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?
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.
Gast
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 ??
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.
Gast
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 !
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.
Gast
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
}
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.
Gast
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
}
Gast
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
}
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.
Gast
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.
Gast
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é

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 11 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.