Problem mit Strukturen

hakkejimmy25

Grünschnabel
Hallo alle zusammen habe folgende Aufgabenstellung:

Programmieren Sie in C eine Warteschlange für int-Werte mit folgenden Operationen:

void qinit(): Erzeugen einer leeren Warteschlange. Sie besteht nur aus dem Endelement.

void enqueue(int element): Anfügen eines Elementes an die Warteschlange

int dequeue(void): Entfernen des ersten Elementes aus der Warteschlange

int isempty(void): Rückgabe von -1, falls die Schlange leer ist, 0 sonst.

void printQueue (void): Ausgabe der in der Schlange gespeicherten Elemente.

Benutzen Sie diese Warteschlangenimplementierung, um in einem Programm den Benutzer menügeführt eine Warteschlange füllen, entleeren und ausgeben zu lassen.
Das Menü sollte dabei ungefähr so aussehen:

Menü zur Warteschlangenverwaltung:
1. Anfügen eines Elementes
2. Löschen und ausgeben des ersten Elementes
3. Ausgeben der Warteschlange
4. Beenden des Programms

Bitte geben Sie die Ziffer der gewünschten Funktion ein:




Folgenden Code habe ich schon geschrieben.....Jedoch klappt es nicht so ganz wie ich möchte ;)
Alsi ich möchte über die switch Anweisung Zahlen ( Integer Werte ) eingeben, die dann gespeichert werden sollen und später auch gelöscht werden können....
Mein Problem liegt erst mal bei der EIngabe....Bekomme es irgendwie nicht hin, das er die Integer Werte abspeichert

Code:
#include <stdio.h>
#include <stdlib.h>

struct Element 
       {
        int element;                                /* Zahlenwerte */
        struct Element *n;                          /* Verweis auf Nachfolger */
       };

struct Element *einfuegen (int element, struct Element *a);
struct Element *loeschen (int element, struct Element *a);
void anzeigen (struct Element *a);


int main(int argc, char *argv[])
    {
     struct Element * dieListe=NULL;                  /* Nullpointer bzw. Listenkopf */
     int element;                                     /* Zahlenwerte */
     int befehl;                                      /* wird für die Switch-Anweisung benötigt */
     
     printf("\n< Einfuegen[1], Loeschen[2],Anzeigen[3], Ende[4] >");  /* Ausgabe */
     
     while (EOF!=scanf("%d",&befehl))
           {
           getchar();
           switch(befehl)
                         {
                         case 1 : printf("Werte zum einfuegen");
                                  scanf("%d",&element);
                                  dieListe=einfuegen(element,dieListe);
                                  break;
                         case 2 : printf("Werte zum loeschen");
                                  scanf("%d",&element);
                                  dieListe=einfuegen(element,dieListe);
                                  break;
                         case 3 : anzeigen(dieListe);
                                  break;
                         case 4 : printf("ENDE");
                                  return;                                        /* Programm wird beendet */
                         }                                                       /* Ende vom switch */
      printf("\n< Einfuegen[1], Loeschen[2],Anzeigen[3], Ende[4] >");            /* Ausgabe */                       
           }                                                                     /* Ende von der While-Anweisung */
             
  system("PAUSE");	
  return 0;
}


struct Element *einfuegen (int element, struct Element *a)
       {
       struct Element *p=a;                    /* aktuelle Position */
       struct Element *vp;                     /* Vorgängerposition */
       struct Element *neu;                    /* Zeiger auf ein neues Element */
       
       /* Enirichten eines neuen Elements */
       neu=malloc(sizeof(struct Element));     /* Speicherplatz wird reserviert */
       neu->element;                   /* Mit Werten füllen */
       
       /* Neues Element an den Anfang ? */
       (if p==NULL || element<0)
           {
           a=neu;                              /* neues Element wird Listenkopf */
           (*neu).n=p;                         /* bisheriges erstes Objekt [Zugriff auf Komponente des Strukturobjekts] */
           return a;                           /* wird dessen Nachfolger */
           }
       /* Sortiergerechte EInfügeposition suchen */
       while(p!=NULL || element>=0)
                     {
                     vp=p;                      /* alte Position merken */              
                     p=(*p).n;                  /* zum nächsten Element */
                     }
       (*neu).n=p;                              /* Einhängen in Verkettung */
       (*vp).n=neu;                             
       return a;
       }
 
Hi.

Die Funktion scanf gibt die Anzahl der Elemente zurück, die erfolgreich eingelesen und konvertiert werden konnten. D.h. in deinem Fall gibt die Funktion entweder 0 oder 1 zurück. D.h. du solltest nicht auf EOF prüfen sondern ob es gleich 1 war. Bei den anderen scanf Aufrufen solltest du grundsätzlich überhaupt erstmal prüfen ob etwas eingelesen wurde.

\edit33:
C:
 neu->element;                   /* Mit Werten füllen */
Wo füllst du denn dort etwas? Sollte das evtl. eine Zuweisung sein?


Gruß
 
Zuletzt bearbeitet:
SO haben meinen Code jetzt bisschen verändert....Ich kann jetzt Integer-Werte eingeben die gespeichert werden, jedoch habe ich jetzt beim löschen Probleme....Er löscht mir immer nur das erste Objekt.

Code:
#include <stdio.h>
#include <stdlib.h>

struct Element {
       int element;
       struct Element *n;
       };


struct Element *einfuegen (int element, struct Element *a);
struct Element *loeschen (int element, struct Element *a);
void anzeigen(struct Element *a);



int main(int argc, char *argv[])
    {
     struct Element *anfang = NULL;                                           /* Nullpointer bzw. Listenkopf */
     int element,eingabe;
                                          
     
     printf("\n< Einfuegen[1], Loeschen[2], Anzeigen[3], Ende[4] >");           /* Ausgabe */
                                                          /* Auswahl wird eingelesen  */
     while(0<=scanf("%d",&eingabe))
     
          {
     switch(eingabe)
                    {
                            case 1 :     printf("Ein Element einfuegen> ");
                                         scanf("%d",&element);
                                         anfang=einfuegen(element,anfang);
                                         break;
                    
                            case 2 :     printf("Zu loeschendes Element eingeben> ");
                                         scanf("%d",&element);
                                         anfang=loeschen(element,anfang);
                                         break;
                                         
                            case 3 :     anzeigen(anfang);
                                         break;
                   
                            case 4 :     printf("Beenden");
                                         return;
                            
                            default :    printf("Sie haben einen falsche Eingabe gemacht!!\n");
                                         
                    }
          printf("\n< Einfuegen[1], Loeschen[2], Anzeigen[3], Ende[4] >");           
     }
                    
    printf("\n\n");               
    system("Pause"); 
     }
     
     

struct Element *einfuegen (int element, struct Element *a)
       {
       struct Element *anfang = NULL; /*Nullpointer bzw. Listenkopf*/
       struct Element *neu;           /*neues Element*/
       struct Element *p=a;           /*aktuelle Position*/
       
       
       neu=malloc(sizeof(struct Element)); /*Speicherplatz wird reserviert*/
       neu->element = element;             /* neu mit Nutzdaten füllen*/
       
       if ( anfang == NULL )
           a=neu;                          /*neues Element wird Listenkopf*/
           neu->n=p;                       /*bisheriges erstes Element [Zeiger auf eine Struktur]*/
           return a;                       /*wird sein Nachfolger*/
      
       }
       
 void anzeigen(struct Element *a)
      {
       while(a!=NULL)
                     {
                      printf("\n%d",a->element);
                      a=a->n;
                      }
      }     

struct Element *loeschen (int element, struct Element *a)
       {
       struct Element *p=a;   /*aktuelle Position*/
       struct Element *vp;    /*Vorgängerposition*/
       
       if ( p!=NULL )

       vp=p;
       a=a->n;
       free(p);
       p=p->n;
       
       return a;
       
      
       }
 
Hi.
Code:
struct Element *einfuegen (int element, struct Element *a)
       {
       struct Element *anfang = NULL; /*Nullpointer bzw. Listenkopf*/
       ...       
       if ( anfang == NULL )
Wozu diese Abfrage?
Code:
struct Element *loeschen (int element, struct Element *a)
       {
       ...
       free(p);
       p=p->n;
Du gibst den Speicher von p frei, und greifst dann nochmal drauf zu? Was soll das denn werden? Und wozu soll das gut sein die lokale Variable zu ändern kurz bevor die Funtion beendet ist?

Ich schätze du solltest in der Funktion loesche alle Elemente aus der Liste entfernen, die mit dem gesuchten Element übereinstimmen. Dazu müßtest du allerdings die ganze Liste traversieren. Das kannst du so machen wie bei der anzeigen Funktion.

Gruß
 
Zuletzt bearbeitet:
Danke, habe die Sachen verbessert ;)

Jedoch wie kann ich eine :
void qinit(): Erzeugen einer leeren Warteschlange. Sie besteht nur aus dem Endelement. erzeugen

und
int isempty(void): Rückgabe von -1, falls die Schlange leer ist, 0 sonst.

erstellen ;)
 
Hi.

Warum hast du es denn anders implementiert als in der Aufgabenstellung vorgesehen? Die Signaturen der Funktionen sollen doch ganz anders aussehen...

Es soll ein spezielles End-Element verwendet werden, du benötigst die Operationen enqueue und dequeue - einmal zum Anhängen am Ende und zum Entfernen des ersten Elements der Liste am Anfang.

Da bei den Funktionen die Liste selbst nicht übergeben wird, müßtest du die Liste als globale Variable definieren (was eigentlich nicht so toll ist, aber anscheinend so vorgegeben wurde).

C:
struct Element 
{
        int element;                                /* Zahlenwerte */
        struct Element *n;                          /* Verweis auf Nachfolger */
};

struct Element nil = { 0, NULL }; // Endelement
struct Element* list;

void qinit() {
  list = &nil;
}

int isempty() {
  return (list == &nil ? -1 : 0);
}
Evlt. solltest du für eine Warteschlange eine doppelt verkettete Liste verwenden? Da würde auch ein spezielles Endelement mehr Sinn machen und du müßtest vor allem nicht die ganze Liste durchgehen wenn du die dequeue Operation ausführen willst.

Gruß
 
@Deepthroat

Du meinst doch bestimmt enqueue (Einfügen eines Wertes am Ende der Warteschlange)

Am sinnvollsten wäre hier ein Sentinel der einen Zeiger auf den Anfang und das Ende beinhaltet. Somit wäre Einfügen und Entfernen am sinnvollsten ausführbar meiner Meinung nach.

Das global zu definieren ist eigentlich auch nicht der sauberste Weg, zur Not lieber doch als Parameter übergeben :)

Viel Glück noch :)
 
@Deepthroat

Du meinst doch bestimmt enqueue (Einfügen eines Wertes am Ende der Warteschlange)
Nee, meine ich eigentlich nicht. Worauf beziehst du dich da?

Am sinnvollsten wäre hier ein Sentinel der einen Zeiger auf den Anfang und das Ende beinhaltet. Somit wäre Einfügen und Entfernen am sinnvollsten ausführbar meiner Meinung nach.
Ja, wenn die Liste doppelt verkettet ist.

Gruß
 
Hi.
Evlt. solltest du für eine Warteschlange eine doppelt verkettete Liste verwenden? Da würde auch ein spezielles Endelement mehr Sinn machen und du müßtest vor allem nicht die ganze Liste durchgehen wenn du die dequeue Operation ausführen willst.

Glaube wir haben eine unterschiedliche Vorstellung von einem Queue ;)
Ich würde neue Elemente immer ganz hinten einreihen und dementsprechend beim entfernen die "alten" ganz vorne sprich das erste Element entfernen auf welches man ja sofort mit der Struktur Zugriff hat.

Man kann ja auch nur so ein Dummy Sentinel erzeugen der einmalig ist und den man immer ändern muss bei den Operationen einfügen und entfernen das wäre keine doppelt verkettete Liste.

mfg:-)
 
Zurück