Stapel => push



  • Also ich komme teils mit. O.O
    Ich habe mal getestet und erfahren, dass das Programm in C++ geschrieben werden muss, da, wenn ich es als c-Programm kompilieren will, bekomme ich nur Fehler.

    Ist doch eine Ecke rasanter, als ich dachte. O.o Jetzt entstehen wieder einige Fragen mehr...
    Am Besten, wir Fragen mal unseren Übungsleiter, wie man das dort macht.

    Trotzdem THX Nexus! 🙂 Falls weitere Fragen zu diesem Stack sind, schreibe ich wieder in dieses Thema, da ich im Moment erstmal müde bin und zweitens ich morgen oder so eh noch nicht durchblicken werde.^^'

    MFG Majin_Clodan



  • Kannst du deinen Übungsleiter auch gerade fragen, wieso ihr nicht C++ programmiert, wenn das schon so dargestellt wird? 🤡
    Finde ich nämlich wie gesagt etwas fragwürdig.

    Nein, wenn du willst, kannst du dich ja mal erkundigen, warum man nicht cout statt printf() , cin statt scanf() verwendet. Oder wieso man immer noch die alten C-Header mit der Endung .h hat (in C++ wären C-Header wenigstens mit einem c vornedran und ohne Endung, also <cstdio> und <cstdlib> ). Aber nicht, dass du deswegen Probleme bekommst... 😉

    P.S. Den C++-Header <stack> brauchst du nur, wenn du auf die fertige Klasse stack zugreifen willst, also in deinem Falle nicht.



  • So:
    Wir sollen das Programm in C programmieren.
    Die vollständigen Vorgaben sehen nun so aus. Hat sich nicht viel geändert, außer das die C++-bibliothek nicht mehr da ist:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct TStackA {
      void** info;
      int maxGroesse;
      int pos;
    };
    
    TStackA stapel;
    int anzahl = 0;
    
    TStackA create()
    {
    
    }
    
    TStackA push(void* info, TStackA oldStack)
    {
    
    }
    
    TStackA pop(TStackA oldStack)
    {
    
    }
    
    void* top(TStackA stack)
    {
    
    }
    
    /*******************************************************************************
    * Das Ein-/Ausgabeverhalten der main-Funktion darf nicht verändert werden.
    * e <Enter>         beendet das Programm.
    * p <Zahl>  <Enter> speichert <Zahl> auf dem Stapel.
    * o <Enter>         entfernt das oberste Element vom Stapel.
    * t <Enter>         Gibt den Integerwert an der Stapelspitze aus.
    *******************************************************************************/
    int main(int argc, char* argv[])
    {
      int* val;
      char command[8];
      TStackA stack;
    
      printf("%d",stapel.info);
    
      stack = create();
      while(*command != 'e')
      {
        printf("cmd? ");
        scanf("%s",command);
        switch(*command)
        {
          case 'p' : val = (int*)malloc(sizeof(int));
                     printf("val? ");
                     scanf("%d",val);
                     stack = push(val,stack);
                     break;
          case 'o' : val = (int*)top(stack);
                     if(val)
                       free(val);
                     stack = pop(stack);
                     break;
          case 't' : if((val = (int*)top(stack)))
                       printf("%d ",*val);
                     break;
        }
      }
    }
    

    Nun haben wir uns heute hingesetzt und versucht, das Programm nun zum Laufen zu bringen, doch wir haben hierbei ein Problem:
    Wir wollen in der funktion "TStackA create()" einen neuen Stapel erstellen. Unsere codes sahen zum Schluss so aus:

    if(anzahl == 0)
            stapel.maxGroesse = 10;
    
        stapel.info=2;
    
        stapel.pos = 0;
        return stapel;
    

    Das Problem hierbei ist, dass in der Struktur die Variable "info" vom Typ "void" ist. Das heißt, dass man hierbei immer einen Fehler bekommt, wenn der Wert nicht(!) 0 ist:

    stapel.info=2;
    

    Wie kann man diese Problematik umgehen?? Mein Tutor sagte mal was zu etwas, was "malloc" heißt, aber kp was das ist und wie man das implementieren soll. O.o

    Hoffe, es ist nicht zu viel Text zum Lesen, da mein Beitrag doch arg lang ist. Ist aber nur die Vorgabe so lang.^^'

    MFG Majin_Clodan



  • Majin_Clodan schrieb:

    Nun haben wir uns heute hingesetzt und versucht, das Programm nun zum Laufen zu bringen, doch wir haben hierbei ein Problem:
    Wir wollen in der funktion "TStackA create()" einen neuen Stapel erstellen.

    Wollt ihr nicht eine Funktion TStackA* create(void) schreiben, die dynamisch Speicher anfordert und einen Zeiger darauf zurückgibt? Ist meiner Ansicht nach einheitlicher, da wahrscheinlich auch spätere Operationen per Zeiger passieren und passt auch zu malloc() .

    Wegen malloc() : Damit kannst du Speicher anfordern, schau mal hier. Denk dran, dass du den Speicher wieder mit free() freigeben musst.

    Majin_Clodan schrieb:

    Das Problem hierbei ist, dass in der Struktur die Variable "info" vom Typ "void" ist. Das heißt, dass man hierbei immer einen Fehler bekommt, wenn der Wert nicht(!) 0 ist:

    stapel.info=2;
    

    Wie kann man diese Problematik umgehen?? Mein Tutor sagte mal was zu etwas, was "malloc" heißt, aber kp was das ist und wie man das implementieren soll.

    Der Typ ist void* , nicht void . Man kann keine Variablen vom Typ void haben. void* ist ein typenloser Zeiger - also ein Zeiger, bei dem man nicht weiss, auf was für einen Typen er zeigt ( int , double , ...).

    Ich denke, die Aufgabenstellung ist so gemeint, dass man mittels malloc() Speicher für einen int reserviert und diesen dann der Variablen info zuweist. Auf der von mir verlinkten Seite sollte sich die Verwendung der manuellen Speicherverwaltung einigermassen erklären.

    Aber void* macht nur Sinn (aus C-Sicht), wenn sich dahinter mehrere Typen verbergen können. Und dann musst du noch irgendwo speichern, was für ein Typ nun tatsächlich genutzt wird, sonst weisst du ja nicht, wie du auf den Wert hinter dem Zeiger zugreifen kannst. Wenn du in deinem Stack nur int s haben sollst, nimmst du besser einen int* .



  • Moin!
    Also ich habe mir mal einige tutorials, auch wegen dem, was intern geschieht, durchgelesen und es wird langsam logisch, was hier alles geschieht. xD Naja, wenn man sowas bisher noch nicht kannte und man auf einmal damit konfrontiert wird. xD

    Trotzdem schaffe ich es aber irgendwie nicht, Speicher zu reservieren.

    Also mein "create" sieht nun so aus:

    TStackA create()
    {
      stapel.info = (void **)malloc(sizeof(int));  // Reservierung Speicherbereich in Groesse "int"
      stapel.info = 4;          //Stapelinformation, welche auf Stapel gelegt wird
    
      stapel.maxGroesse;    //Stapelgroesse
    
      stapel.pos = 0;       //Feldposition
    
      return stapel;    //RG von Veranderung des Stapels
    
    }
    

    Also bei er Zeile, wo ich Speicherbereich reserviere, kommt kein Fehler. Nun dacht ich mir, testest du es mal und legst einen int-Wert von 4 dort rein. Klappt aber nicht d.h. in der Zeile:

    stapel.info = 4;          //Stapelinformation, welche auf Stapel gelegt wird
    

    bekomme ich den folgenden Fehler:
    error: invalid conversion from 'int' to 'void*'*

    Ich verstehe das nicht. Ich habe doch einen gültigen Speicherbereich reserviert oder nicht?? Wieso kann ich diesen Wert nicht dort rein speichern?? ?.?

    MFG Majin_Clodan



  • Die Fehlermeldung sagt ja alles. Du probierst ein int einem void** zuzuweisen, was ohne casten nicht geht. (Und auch nicht viel Sinn macht..)



  • Nun info ist ein Zeiger auf einen Zeiger im Speicherbereich deines Stapels und du reservierst Speicher für genau ein Element der Größe int und versuchst dann dem Zeiger einen int Wert zuzuweisen, das kann nicht gehen. Wahrscheinlich geht es aber um folgendes Prinzip:

    int iStapelGröße = 100 // Das ist die Anzahl der Elemente die maximal auf den Stack gepusht werden können
    int* pStapel = (int*) malloc( sizeof ( int ) * iStapelGröße ); //hier wird Speicher reserviert
    int **info = &pStapel; //info zeigt nun auf das erste element im stapel
    
    //Push
    //Zuweisung:
    **info = 4;
    //nächstes freies Element wählen:
    info = &(*info++);
    // nächste Zuweisung:
    **info=3;
    ...
    


  • So,
    habe es nun endlich hinbekommen. 😃

    Jetzt gibt es nur noch ein kleines Problem, welches in einer weiteren Aufgabe ist. Es ist eigentlich fast alles gleich. Der einzigste Unterschied ist der, dass die Struktur nun so aussieht:

    struct TStackP
    {
      void* info;
      TStackP* p;
    };
    

    Mein Programm sieht bis jetzt so aus. Nicht wundern, falls es wieder viel aussieht. Ich gehe nur auf ein paar Zeilen ein. 🙂

    #include <stdio.h>
    #include <stdlib.h>
    
    struct TStackP
    {
      void* info;
      TStackP* p;
    };
    
    int zaehler = 0;
    
    TStackP stapel;
    void** zAufInfo = &stapel.info;     //Zeiger auf void* info im Stapel -> I
    
    TStackP create()
    {
        stapel.info = (void *)malloc(10 + sizeof(int));  // Reservierung Felder des Array vom Typ int! <--------------
    
        void** zAufInfo = &stapel.info;
    
        return stapel;
    }
    
    TStackP push(void* info, TStackP oldStack)
    {
        oldStack.info = (void *)malloc(10 + sizeof(int));  // Reservierung 1 Felder des Array vom Typ int! <--------------
    
        zAufInfo[zaehler] = info;   // I
        ++zaehler;
    
        return oldStack;
    }
    
    TStackP pop(TStackP oldStack)
    {
    
        zAufInfo[zaehler] = NULL;   //Oberstes Stapelelement gelöscht
        --zaehler;                  //Dekrementierung
    
        oldStack.p[zaehler-1];
    
        return oldStack;
    }
    
    void* top(TStackP stack)
    {
    
        if(zaehler <= 0)
        {
            printf("Der stapel ist leer");
            exit(EXIT_FAILURE);
        }
    
        return zAufInfo[zaehler];
    }
    
    /*******************************************************************************
    * Das Ein-/Ausgabeverhalten der main-Funktion darf nicht verändert werden.
    * e <Enter>         beendet das Programm.
    * p <Zahl>  <Enter> speichert <Zahl> auf dem Stapel.
    * o <Enter>         entfernt das oberste Element vom Stapel.
    * t <Enter>         Gibt den Integerwert an der Stapelspitze aus.
    *******************************************************************************/
    int main(int argc, char* argv[])
    {
      int* val;
      char command[8];
      TStackP stack;
    
      stack = create();
      while(*command != 'e')
      {
        printf("cmd? ");
        scanf("%s",&command);
        switch(*command)
        {
          case 'p' : val = (int*)malloc(sizeof(int));
                     printf("val? ");
                     scanf("%d",val);
                     stack = push(val,stack);
                     break;
          case 'o' : val = (int*)top(stack);
                     if(val)
                       free(val);
                     stack = pop(stack);
                     break;
          case 't' : if((val = (int*)top(stack)))
                       printf("%d ",*val);
                     break;
        }
      }
    }
    

    Man muss sich die vorgaben so vorstellen, dass in allen Funktionen außer der main nichts stand.
    Bei diesem Programm schaff ich es nicht, etwas auf meinen Stapel zu tun. Ich bekomme zwar keine Fehlermeldung, wenn ich etwas raufsetze, aber wenn ich es sehen will, was dort ist, sehe ich nichts, als wäre dieser nicht da. O.O
    Ich kann die Elemente auch löschen und ab einem bestimmten Punkt, wenn die Menge der elemente 0 ist und ich wieder was löschen will, wird das Programm beendet, doch das bringt mir ja nicht viel.^^'

    Also das Problem war ja meines erachtens, dass "info" in der Struktur kein Zeiger auf Zeiger mehr war. Dementsprchend bastelte ich mir einen und dieser zeigt dann auf dieses info in meiner Struktur:

    void** zAufInfo = &stapel.info;
    

    Wieso? Naja, weil ich später, wenn ich Elemente auf meinen Stapel tun wollte, immer Fehler bekam.
    Meine push-Anweisung sieht dann so aus:

    zAufInfo[zaehler] = info
    

    Hier wird die Information "info" an die Stelle "zaehler" im feld eingefügt.

    So weit so gut. Wenn ich nun aber sehen will, was ich auf dem Stapel habe, sehe ich ja nichts. In meinem "top" habe ich dann dafür das:

    return zAufInfo[zaehler];
    

    danach dann soll es ja per printf ausgegeben werden, doch das macht es nicht. 😞

    Was habe ich falsch gemacht? Etwas falsches mit meinem "Zeiger auf Zeiger" oder so??

    ______
    Legende in der Struktur:
    info => speichert einen Zeiger auf die Information zu dem heweiligen Eintrag
    p => dient der Verkettung der Stapelelemente

    => wusste selber kaum, was p mir sagen soll und deswegen umgehe ich es einfach oder in wie fern könnte man es gebrauchen??

    MFG Majin_Clodan

    PS: so viel Text in einem Beitrag. xD



  • Hallo Komilitone(hab die gleiche aufgabe 😉 )...also ich hab das Problem, dass der Compiler schon beim Aufruf der Funktion "create" einen Fehler meldet "syntax error before "create" ".
    Ich seh überhaupt nich durch 😕 ...muss ich vorher noch etwas definieren bzw. festlegen??



  • fischkopp schrieb:

    Hallo Komilitone(hab die gleiche aufgabe 😉 )...also ich hab das Problem, dass der Compiler schon beim Aufruf der Funktion "create" einen Fehler meldet "syntax error before "create" ".
    Ich seh überhaupt nich durch 😕 ...muss ich vorher noch etwas definieren bzw. festlegen??

    Dann zeig den Code mal her. Du hast doch nicht etwa ein ; bei der Klassendefinition vergessen, oder?



  • Hallo Programmierpraktikum-Geschädigte und nette Menschen, die uns helfen,

    Auch mir geht es so... Egal wie ich den Quelltext gestalte, immer kommt bei mir "Syntax-Error before create". Kann das am Compiler liegen (benutze DEV-C++)?? Ich mein, ich bekomm gar nicht die Fehlermeldungen, die schon erwähnt wurden, weil halt schon immer vorher ein Fehler auftritt. Hier beispielsweise mein create Funktion zu TStackA

    #include <stdio.h>
    #include <stdlib.h>
    
    struct TStackA 
    {
      void** info; 
      int maxGroesse;
      int pos;
    };
    
      TStackA stapel; // egal was ich mache kommt hier ein Fehler bzw.
      int anzahl = 0; // unten bei TStackA creat()
    
    TStackA create()
    {
    
      stapel.info = (void **)malloc(sizeof(int));  // Reservierung Speicherbereich in Groesse "int"
      stapel.info = 4;          //Stapelinformation, welche auf Stapel gelegt wird
    
      stapel.maxGroesse;    //Stapelgroesse
    
      stapel.pos = 0;       //Feldposition
    
      return stapel;    //RG von Veranderung des Stapels
    }
    

    Vielen Dank für eure Hilfe im Voraus!



  • @BartMan
    Das Programm, dass du bekommen hast ist als c Dokument gespeichert. Editiere mal die Endung auf *.cpp, dann kommt keine Meldung beim create mehr.



  • In C müssen Funktionen, die keine Parameter haben, das explizit durch void angeben.

    TStackA create(void)
    


  • hab das gleiche problem

    die vorgabe ist c und nicht c++ und lehvis wird sicher auch nur ein c programm annehmen. also bringt es nichts das ding auf .cpp zu ändern

    sonst könntest du ja gleich die c++ klassen dafür nehemen 😃
    in c++ könntest du sogar das struct weg lassen.

    wäre eine möglichkeit:

    typedef struct TStackA 
    {
      void** info; 
      int maxGroesse;
      int pos;
    }TStackA;
    

    in C brauchst du immer ein typedef (,oder?)

    diese aufgabe spiegelt leider auch die vorlesung des prof´s B. wieder. er mischt ständig c mit c++ und das was in C ist entspricht nicht mal dem C99 👎



  • dap schrieb:

    hab das gleiche problem

    Schau mal meinen Post an.

    dap schrieb:

    wäre eine möglichkeit:

    typedef struct TStackA 
    {
      void** info; 
      int maxGroesse;
      int pos;
    }TStackA;
    

    in C brauchst du immer ein typedef (,oder?)

    Wenn du das Schlüsselwort struct in Deklarationen weglassen willst, ja. (Okay, es ginge auch über ein Makro, aber lassen wir das...)

    Dein Konstrukt sollte aber eher so aussehen:

    typedef struct // hier kein Bezeichner
    {
        void** info; 
        int maxGroesse;
        int pos;
    } TStackA;
    


  • ohne dem typedef oder makro kann man sonst die funktion (vorgeabe)
    TStackA create(){} nicht aufrufen, weil beim compilieren ja schon der fehler kommt das er mit dem TStackA nix an zu fangen weiß

    allg. tuh ich mich mit dem anblick des "void**" schwer. zumal der den wert in der main-funktion als integer ausgeben soll und in der eingabe mit scanf kann man auch nur eine zahl eingeben. daher verstehe ich denn sinn überhaupt nicht. und ich denke das da schnell laufzeitfehler entstehen können 😕



  • Hi

    habe die selbe aufgabe gestellt bekommen,
    ich glaube das dass *void dazu dient um in C verschiedene komplexe Datenstrukturen zu speicher, also structs.

    da wir ja **void verwenden erzeugen wir eine Liste, ein array von vielen *voids
    somit kann man leicht hinzufügen wie bei normalen array.

    TStackA push(void* info, TStackA oldStack)
    {
      next = info;
      if (oldStack.pos < oldStack.maxGroesse){
        oldStack.info[oldStack.pos++] = next; // next info wird im info Feld gespeichert, danach pos erhöht um 1
      }
      else {  // wenn kein Platz mehr, erhöhe um 50%
        oldStack.info = (void**)realloc(oldStack.info, (oldStack.maxGroesse + oldStack.maxGroesse / 2));
        oldStack.info[oldStack.pos++] = next; // next info wird im info Feld gespeichert, danach pos erhöht um 1
     }
      return oldStack;
    }
    

    gruß



  • next ist ein void* next;

    eigentlich ist der überflüssig er zeigt nur noch mal deutlich, das es sich um ein nächstes element handelt.

    meine ausgabe ist äußert komisch, ich weis nicht wie ich den inhalt dieses pointer auf pointer ausgeben kann.

    er gibt mir immer nur die adresse aus, wenn ich info[stack.pos] anspreche sollte er eigentlich den inhalt davon ausspucken, nicht wieder den pointer auf die pos.

    gruß



  • Du brauchst *info[stack.pos].



  • HHHIIIIIILLLLLLFFFFFFFEEEEEEE!!!!!!!!

    Ich hab genau die gleichen Probleme wie alle andern auch.
    Mein Programm sieht noch genauso aus wie am Anfang, d.h. meine Vorgage ist immernoch unverändert. 😮
    Und bei den Lösungsansätzen hier verstehe ich rein garnichts.
    Ich bekomme nicht mal das create() hin und hab auch nicht die leiseste Ahnung, wie ich das anstellen soll.

    Ich hoffe, mir kann jemand helfen.


Anmelden zum Antworten