C: Datentausch bei enum und struct

stift

Level-1
Beiträge
261
Reaktionspunkte
17
Zuviel Werbung?
-> Hier kostenlos registrieren
hey, ich hab ein kleines projekt in C zu schreiben, komme aber überhaupt nicht weiter. Vielleicht hat von euch einer ne idee.
Folgendes:
Ich habe eine Enum am anfang definiert, welche in eine Struct eingebunden ist. Nun möchte ich zwei Werte über pointer miteinander tauschen. Dabei ist ein Datentyp teil der Enum, der andere ist Int. Kann ich die beiden datentypen irgenwie casten?

Code:
typedef enum {...} AUFZ;

typedef struct Table
{[INDENT]char ....
int Ergebnis
AUFZ Aufzählung 
[/INDENT]}

main(void)
AUFZ *pTemp
AUFZ *pAlt
AUFZ *pNeu

pAlt = &Table[i].Aufzählung
pNeu = &Table[i].Ergebnis 
(Hier ist das Problem; wenn ich den Pointer pNeu anders, also nich über geschenke definiere, dann habe ich das problem später, bei:)

pTemp = *pAlt;
*pAlt = *pNeu;
*pNeu = pTemp;
...
Hat einer ne idee? ich bin seit zwei abenden am verzweifeln x)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Irgendwie ist dein Beispiel-Code etwas konfus...
Aber mal angenommen du hast irgendwo nochmal Table als Array definiert und das typedef hat dann einen anderen Namen, könnte folgender Cast funktionieren:
Code:
pNeu = (AUFZ*)&Table[i].Ergebnis;
Es hängt aber vom Compiler und C-Standard ab, ob das Ergebnis dann definiert ist.
 
ja, genau;
thomas hat mein problem schon verstanden.
einen array hab ich definiert - dummerweise aber vergessen ins forum reinzutippen - sorry

den fehler hab ich allerdings immer noch.
ich hab die beiden pointer folgendermaßen definiert:
Code:
pAlt = &Array[i].Gegenstand;
pNeu = (AUFZ*)&Array[i].iErgebnis;
Beim Tauschvorgang stürzt mein compiler allerdings jedes mal ab.
Code:
        *pTemp = *pAlt;
        *pAlt = *pNeu;
        *pNeu = *pTemp;
 
Die Größe eines int muss nicht gleich der Größe einer enum sein. Dies kann natürlich zu einem Problem führen. Außerdem sehe ich nirgends, wo der Speicher allokiert wird. Ist dies in ausreichender Größe getan worden?
Was bedeutet "Compiler stürzt ab"? Welche Fehlermeldung gibt er aus? Erzeugt er einen BSOD? Oder läuft die Anwendung nicht? Gibt es in der Entwicklungsumgebung einen Ausnahmefehler?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zeig doch bitte mal einen compilierbaren Programmcode, und nicht immer solche Programmschnippsel die kein Compiler frisst.

Aber ich denke mal du hast da noch ein Problem mit den Zeigern:
Code:
AUFZ *pTemp; /* Variable für einen Zeiger auf den Typ AUFZ */
AUFZ *pAlt;  /* Variable für einen Zeiger auf den Typ AUFZ */
AUFZ *pNeu;  /* Variable für einen Zeiger auf den Typ AUFZ */
Damit legst du Variablen für einen Zeiger auf den Datentyp AUFZ an.
Code:
pAlt = &Array[i].Gegenstand;
pNeu = (AUFZ*)&Array[i].iErgebnis;

pAlt zeigt jetzt auf Array.Gegenstand.
pNeu zeigt jetzt auf Array.iErgebnis.

Code:
*pTemp = *pAlt;
Und hier versuchst du, der Variablen auf die pTemp zeigt den Wert zuzuweisen auf den pAlt zeigt. Und worauf zeigt pTemp?
Ich sehe zumindest keine Zuweisung.

Wenn du den Zeiger pTemp vorher nicht auf eine gültige Speicherstelle zeigen lässt, zeigt pTemp auf einen zufälligen (und aller Wahrscheinlichkeit nach) nicht gültigen Wert. Beim Zugriff auf diese Speicherstelle bekommst du unter einem Betriebssystem einen Speicherzugriffsfehler, bei einem Mikrocontroller ohne Betriebssystem zerschießt du dir deinen Speicher.
 
danke schon mal euch beiden.
den speicher habe ich noch nirgends allokiert. ich habe von malloc zwar mal was gelesen, habe allerdings nicht verstandent, was ich damit anfangen kann.

ptemp soll eine zwischenvariable sein, da ich möchte, dass die inhalte von palt und pneu getauscht werden.

das ganze is ne heimarbeit, für die uni. aber ich will ehrlich gesagt nicht, dass ihr mir was ausbessert und die sache läuft.
wär cool, wenn ihr mir tipps geben könntet, damit ich nen ansatz habe und bisschen weiter komme aber dabei auch was lerne.
damit habt ihr mir ja vor drei jahren in der sps-technik wahnsinnig viel beigebracht.

Ziel der aufgabe ist, dass zwei studenten ihr geschenk tauschen.
ein wichtelprogramm :rolleyes:
folgenden code habe ich geschrieben:

Code:
/* Heimarbeit 5-3 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

 typedef enum {HOERBUCH,LEGOAUTO,DVD,BOOMERANG,JOJO,SPIELKARTEN} GESCHENKE;
    
typedef struct Table
{
    char szName[20];
    int iErgebnis;
    GESCHENKE Gegenstand;
};


main(void)
{
    struct Table Student[6];
    int i;
    char szGeschenk[12];
    GESCHENKE *pTemp=NULL;
    GESCHENKE *pAlt=NULL;
    GESCHENKE *pNeu=NULL;

    //Schleife der Namens- und Geschenkeingabe
    for(i=0; i<=1; i++)
    {
    printf("Bitte geben Sie den Namen des %i. Studenten ein:\n", i+1);
    scanf("%s", &Student[i].szName);

    printf("Bitte geben Sie das Geschenk des %i. Studenten ein:\n", i+1);
    scanf("%i", &Student[i].Gegenstand);
    }

    //Schleife zur Würfelergenisseingabe und Aufruf der Schleife zum Tauschvorgang
    for(i=0; i<=1; i++)
    {
        printf("%s wuerfelt: ", Student[i].szName);
        scanf("%i", &Student[i].iErgebnis);

        //Schleife zur Überprüfung korrekter Würfelergebnisse
        while (Student[i].iErgebnis<=0 || Student[i].iErgebnis>=7)
        {
            printf("Falscheingabe: Bitte noch einmal wuerfeln!\n");
            printf("%s wuerfelt: ", Student[i].szName);
            scanf("%i", &Student[i].iErgebnis);
        }

        //Tauschvorgang
        pAlt = &Student[i].Gegenstand;
        pNeu = (GESCHENKE*)&Student[i].iErgebnis-1;

        *pTemp = *pAlt;
        *pAlt = *pNeu;
        *pNeu = *pTemp;
        /////////////////////////////////////////////////////////////////////////////////
        
    }

    for(i=0; i<=1; i++)
    {
        switch (Student[i].Gegenstand){
            case 0: 
                strcpy(szGeschenk, "HOERBUCH");
                break;
            case 1:
                strcpy(szGeschenk, "LEGOAUTO");
                break;
            case 2:            
                strcpy(szGeschenk, "DVD");
                break;
            case 3:
                strcpy(szGeschenk, "BOOMERANG");
                break;
            case 4:
                strcpy(szGeschenk, "JOJO");
                break;
            case 5: 
                strcpy(szGeschenk, "SPIELKARTEN");
                break;
        }
        
        printf("%s: %s \n", Student[i].szName, szGeschenk);
    }

    return(0);
}
 
Seltsames Programm ;-)

Aber schau die meinen Hinweise mit dem nicht initialisiertem pTemp an.
Das ist ein Grund warum es kracht.

In dein neues Programm hast du noch einen weiteren Fehler eingebaut:
Code:
pNeu = (GESCHENKE*)&Student[i].iErgebnis-1;
Was soll die -1 bewirken?
So wie du es dort geschrieben hast, wird der Zeiger pNeu auf die Adresse der Variablen "Student.iErgebnis" minus 1 gesetzt.
Mal angenommen die Variable Student.iErgebnis liegt im Speicher an Byteadresse 1000. dann zeigt pNeu auf Speicherstelle 999. Und da willst du sicherlich nicht drauf zugreifen ;-)

Warum überhaupt der Umweg über Zeiger und keine direkte Zuweisung?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
im anhang ein bild, wie das programm schlussendlich funktionieren soll. ich hab das ganze auch bereits hinbekommen, allerdings nicht über call by reference. und das ist teil der aufgabenstellung.
 

Anhänge

  • 83b9b150f013fa7282b92fda43c9da91.jpg
    83b9b150f013fa7282b92fda43c9da91.jpg
    106,2 KB · Aufrufe: 10
im anhang ein bild, wie das programm schlussendlich funktionieren soll. ich hab das ganze auch bereits hinbekommen, allerdings nicht über call by reference. und das ist teil der aufgabenstellung.

Mit Pointern zu arbeiten würde da aber nur Sinn ergeben, wenn man den Geschenketausch in eine eigene Funktion verlegen würde.

Als Anregung vielleicht so:
Code:
void geschenketausch(GESCHENKE *gesch, int *erg)
{
...
}

oder noch allgemeiner:
Code:
void geschenketausch(Table *student1, Table *student2)
{
...
}

Dann benötigt man auch diese Hilfsvariable als Zwischenspeicher, die aber kein Zeiger ist. Denn der Zeiger selber kann keinen Wert speichern sondern nur eine Adresse (Zeiger).
 
soo, die anwendung läuft endlich.
Code:
/* Heimarbeit 5-3 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

 typedef enum {HOERBUCH,LEGOAUTO,DVD,BOOMERANG,JOJO,SPIELKARTEN} GESCHENKE;
    
typedef struct Table
{
    char szName[20];
    int iErgebnis;
    GESCHENKE Gegenstand;
};
void Geschenktausch(GESCHENKE *Student1, GESCHENKE *Student2)
{
    GESCHENKE iTemp;
    iTemp = *Student1;
    *Student1 = *Student2;
    *Student2 = iTemp;
};


main(void)
{
    struct Table Student[6];
    int i;
    char szGeschenk[12];
    GESCHENKE *pAlt=NULL;
    GESCHENKE *pNeu=NULL;

    //Schleife der Namens- und Geschenkeingabe
    for(i=0; i<=5; i++)
    {
    printf("Bitte geben Sie den Namen des %i. Studenten ein:\n", i+1);
    scanf("%s", &Student[i].szName);

    printf("Bitte geben Sie das Geschenk des %i. Studenten ein:\n", i+1);
    scanf("%i", &Student[i].Gegenstand);
    }

    //Schleife zur Würfelergenisseingabe und Aufruf der Schleife zum Tauschvorgang
    for(i=0; i<=5; i++)
    {
        printf("%s wuerfelt: ", Student[i].szName);
        scanf("%i", &Student[i].iErgebnis);
        Student[i].iErgebnis= Student[i].iErgebnis-1;

        //Schleife zur Überprüfung korrekter Würfelergebnisse
        while (Student[i].iErgebnis<0 || Student[i].iErgebnis>5)
        {
            printf("Falscheingabe: Bitte noch einmal wuerfeln!\n");
            printf("%s wuerfelt: ", Student[i].szName);
            scanf("%i", &Student[i].iErgebnis);
            Student[i].iErgebnis= Student[i].iErgebnis-1;
        }

        //Tauschvorgang
        if (Student[i].iErgebnis == i)
             goto keinTausch;
        else
        Geschenktausch(&Student[i].Gegenstand, &Student[Student[i].iErgebnis].Gegenstand);
        keinTausch:;
    }

    for(i=0; i<=5; i++)
    {
        switch (Student[i].Gegenstand){
            case 0: 
                strcpy(szGeschenk, "HOERBUCH");
                break;
            case 1:
                strcpy(szGeschenk, "LEGOAUTO");
                break;
            case 2:            
                strcpy(szGeschenk, "DVD");
                break;
            case 3:
                strcpy(szGeschenk, "BOOMERANG");
                break;
            case 4:
                strcpy(szGeschenk, "JOJO");
                break;
            case 5: 
                strcpy(szGeschenk, "SPIELKARTEN");
                break;
        }
        
        printf("%s: %s \n", Student[i].szName, szGeschenk);
    }

    return(0);
}

ich habe es mit hilfe einer funktion gelöst, so wie du es angeregt hast. vielen dank.
die zweite variante habe ich allerdings nicht hinbekommen, da ich schon wieder unverträgliche typen hatte, wegen der enum und der struct...
wie müsste ich da denn das ganze adressieren. hab es folgendermaßen versucht, wobei ich allerdings gleich in der zweiten zeile der funktion die genannten probleme hatte:
Code:
void Geschenktausch(struct Table*Student1, struct Table *Student2)
{
    int iTemp;
    iTemp = (*Table).Student1;
...
};

eine generelle frage habe ich allerdings noch.
ich war immer der meinung, dass alle physikalischen adressen aus einer integer-zahl bestehen. warum habe ich dann immer diese probleme beim einsatz höherer datentypen?
wenn ich einen pointer nutze, dann ist die adresse doch trotzdem eine ganzzahl, auch wenn ich dabei auf einen eigenen, höheren datentyp zugreife, oder?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
die zweite variante habe ich allerdings nicht hinbekommen, da ich schon wieder unverträgliche typen hatte, wegen der enum und der struct...
wie müsste ich da denn das ganze adressieren. hab es folgendermaßen versucht, wobei ich allerdings gleich in der zweiten zeile der funktion die genannten probleme hatte:
Code:
void Geschenktausch(struct Table*Student1, struct Table *Student2)
{
    int iTemp;
    iTemp = (*Table).Student1;
...
};

Du musst auf das Strukturelement von Table passend zugreifen. Da der Zugriff auf Strukturen über Zeiger in C sehr häufig benötigt wird, hat man dafür den eigenen Operator -> eingeführt. Dann fällt der Dereferenzierungsoperator * weg.

Als Ansatz:
Code:
void Geschenktausch(struct Table*Student1, struct Table *Student2)
{
    GESCHENKE iTemp;
    iTemp = Student1->Gegenstand;
...

eine generelle frage habe ich allerdings noch.
ich war immer der meinung, dass alle physikalischen adressen aus einer integer-zahl bestehen. warum habe ich dann immer diese probleme beim einsatz höherer datentypen?
wenn ich einen pointer nutze, dann ist die adresse doch trotzdem eine ganzzahl, auch wenn ich dabei auf einen eigenen, höheren datentyp zugreife, oder?

Der Compiler muss wissen auf welchen Datentyp der Zeiger zeigt. Ansonsten funktioniert die Pointerarithmetik nicht.
Z.B. wird ein int-Pointer
int *pInt;
mit pint++ um sizeof(int) hochgezählt, welches auf 32-Bit Rechnern meistens den Wert 4 hat.
Du könntest auch einen Zeiger auf deine Table anlegen.
Table *pTable;
Bei pTable++ wird dann der Zeiger um einen kompletten Struktursatz erhöht (20*sizeof(char) + sizeof(int) + sizeof(GESCHENKE)).
 
Als Verfeinerung für deine switch-case Anweisung um die Geschenknamen auszugeben, kannst du einfacher folgendes machen:
Code:
const char *geschenknamen[7] = {"KEINS", "HOERBUCH", "LEGOAUTO", "DVD", "BOOMERANG", "JOJO", "SPIELKARTEN"};
Dann kannst du die Geschenknamen ohne switch-case direkt aus dem enum-index auslesen:
Code:
printf("Geschenk: %s", geschenknamen[Student[0].Gegenstand]);
 
spitze, vielen dank für deine erklärungen. jetzt hab ich alles verstanden.
auch das mit dem switch ist klasse.

mir war die alte lösung auch zu umständlich, hab das letzte woche schon ma gegooglet und bin in irgend einem forum darauf gestoßen, dass es nicht möglich ist, das ganze ohne switch case zu machen :rolleyes:

nochmal danke
 
Zurück
Oben