Array mit struct Pointer und memmove



  • Hallo,
    ich habe ein kleines Programm geschrieben, dass ein Array erstellt mit struct pointern.
    Dazu habe ich zwei structs erstellt: "priorityqueue_t" für die Abspeicherung von dem pointer Array, die Länge
    und "pquentry_t" für die dazugehörigen Werte.

    typedef struct {
    	char *value;
    	float priority;
    } pquentry_t;
    
    typedef struct {
    	int length;
    	int maxLength;
    	pquentry_t **elements;
    } priorityqueue_t;
    

    Der "Priority" Wert soll immer beim hinzufügen eines neuen Eintrages sortiert werden.
    Da man den Eintrag nicht einfach zwischen zwei anderen Einträgen quetschen kann, habe ich die Funktion memmove() gefunden.
    Hier erstmal der Code für die Funktionen:

    priorityqueue_t * pqueue_create() {
    	priorityqueue_t* prioq = malloc(sizeof(priorityqueue_t));
    	prioq->length = 0;
    	prioq->maxLength = 0;
    
    	return prioq;
    }
    
    void pqueue_insert(priorityqueue_t* pq, char * value, float p) {
    	if (isFull(pq)) {
    		increase(pq);
    	}
    
    	pq->elements[pq->length] = (pquentry_t*)malloc(sizeof(pquentry_t));
    
    	if (pq->length < 1) {
    		pq->elements[0]->value = value;
    		pq->elements[0]->priority = p;
    	} else {
    		int index = -1;
    
    		for (int i = 0; i < pq->length; i++) {
    			if (pq->elements[i]->priority >= p) {
    				index = i;
    				break;
    			}
    		}
    
    		if (index < 0) {
    			pq->elements[pq->length]->value = value;
    			pq->elements[pq->length]->priority = p;
    			printf("memEnd %s\n", value);
    		} else if (index < 1) {
    			memmove(pq->elements + 1, pq->elements, pq->length * sizeof(pquentry_t*));
    			pq->elements[0]->value = value;
    			pq->elements[0]->priority = p;
    			printf("mem0 %s\n", value);
    		} else {
    			memmove(pq->elements + index + 1, pq->elements + index, (pq->length - index) * sizeof(pquentry_t*));
    			pq->elements[index]->value = value;
    			pq->elements[index]->priority = p;
    			printf("mem~ %s\n", value);
    		}
    	}
    	pq->length++;
    }
    
    char isFull(priorityqueue_t* pq) {
    	return pq->length >= pq->maxLength;
    }
    
    void increase(priorityqueue_t * pq) {
    	if (pq->maxLength == 0) {
    		pq->elements = (pquentry_t**)malloc(10 * sizeof(pquentry_t*));
    		pq->maxLength = 10;
    	} else {
    		pq->elements = (pquentry_t**)realloc(pq->elements, (pq->length * 2) * sizeof(pquentry_t*));
    		pq->maxLength = (pq->length * 2);
    	}
    }
    
    void printQueue(priorityqueue_t* pq) {
    	int i;
    	printf("(%i/%i) -> {\n", pq->length, pq->maxLength);
    	for (i = 0; i < pq->length; i++) {
    		printf("    [%i] -> (Wert: %s - Prio: %f)\n",i, pq->elements[i]->value, pq->elements[i]->priority);
    	}
    	printf("}\n");
    }
    

    Und hier mein Testprogramm:

    int main() {
    	priorityqueue_t* pq;
    
    	pq = pqueue_create();
    
    	pqueue_insert(pq, "Portland", 5);
    	printQueue(pq);
    	pqueue_insert(pq, "Tallahassee", 4);
    	printQueue(pq);
    	pqueue_insert(pq, "Los Angeles", 8);
    	printQueue(pq);
    	pqueue_insert(pq, "Sydney", 7);
    	printQueue(pq);
    	printf("ENDE \n");
    }
    

    Das Programm läuft zwar durch, aber durch memmove wurden aus irgendeinem Grund Werte überschrieben die nicht überschrieben werden sollten.
    Ausgabe:

    (1/10) -> {
        [0] -> (Wert: Portland - Prio: 5.000000)
    }
    mem0 Tallahassee
    (2/10) -> {
        [0] -> (Wert: Tallahassee - Prio: 4.000000)
        [1] -> (Wert: Tallahassee - Prio: 4.000000)
    }
    memEnd Los Angeles
    (3/10) -> {
        [0] -> (Wert: Tallahassee - Prio: 4.000000)
        [1] -> (Wert: Tallahassee - Prio: 4.000000)
        [2] -> (Wert: Los Angeles - Prio: 8.000000)
    }
    mem~ Sydney
    (4/10) -> {
        [0] -> (Wert: Tallahassee - Prio: 4.000000)
        [1] -> (Wert: Tallahassee - Prio: 4.000000)
        [2] -> (Wert: Sydney - Prio: 7.000000)
        [3] -> (Wert: Sydney - Prio: 7.000000)
    }
    

    Wie man in der Ausgabe sieht ist Tallahassee zwei mal vorhanden, dasselbe mit Sydney...
    Woran kann dies liegen?

    Vielen dank im Voraus!

    mfg Marco



  • Erstens: du verwendest C, nicht C++ hier.
    Zweitens: wieso einen Zeiger auf einen Zeiger auf die Objekte? Nimm direkt einen Zeiger auf die Objekte. Weniger malloc -Aufrufe, weniger Komplexität, und die dynamische Liste verwaltest du immer noch.
    Drittens: du hast da jede Menge redundanten Code. Vielleicht solltest du diesen erstmal zusammenschrauben? Ein Beispiel dazu:

    size_t elements = pq->maxLength;
    if (elements == 0)
        elements = 10;
    else
        elements *= 2;
    
    /*TODO: Da fehlt noch eine Prüfung auf NULL.*/
    pq->elements = (pquentry_t**)malloc(elements * sizeof(pquentry_t*));
    pq->maxLength = elements;
    

    Und noch so andere Späße. Und wenn du das machst, dann siehst du den Fehler vielleicht auch schon von alleine.



  • Was genau ist deine Frage zu C++ zu deinem Programm?
    Dein Programm ist pures C.
    - mal mit unsinnigem malloc-Cast, mal ohne
    - zum Sortieren nimmt man qsort, egal ob man struct oder Zeiger auf struct verwendet
    - schon mal was von struct-Kopien gehört?
    - free fehlt
    - die Gleichheit bei Gleitkommazahlen zu bemühen ist anfängerhaft


  • Mod

    pq->elements[pq->length] = (pquentry_t*)malloc(sizeof(pquentry_t));
    

    Das passt nicht zum Code der darauf folgt. Du weisst an dieser Stelle ja noch gar nicht, wo eingefügt werden muss.

    Wutz schrieb:

    - zum Sortieren nimmt man qsort, egal ob man struct oder Zeiger auf struct verwendet

    Vorausgesetzt Daten liegen überhaupt einmal ungeordnet vor. Das ist jedenfalls beim gezeigten Programm nicht der Fall.

    Wutz schrieb:

    die Gleichheit bei Gleitkommazahlen zu bemühen ist anfängerhaft

    und unbedacht zweifelhafte Allgemeinplätze zu wiederholen, ist das ganz sicher...



  • camper schrieb:

    pq->elements[pq->length] = (pquentry_t*)malloc(sizeof(pquentry_t));
    

    Das passt nicht zum Code der darauf folgt. Du weisst an dieser Stelle ja noch gar nicht, wo eingefügt werden muss.

    Vielen Dank, habe jetzt die Speicher allokierung nach memmove gemacht und es funktioniert.

    Werde das Programm zur Übung auch noch mit einem einfachen Array umschreiben, ohne pointer auf pquentry...

    Vielen Dank an alle!

    mfg Marco



  • Hey nochmal,
    habe doch noch ein kleines Problem mit den Vergrößerung des Arrays.
    Hier nochmal die Funktion:

    void increase(priorityqueue_t * pq) {
    	if (pq->maxLength == 0) {
    		pq->elements = (pquentry_t**)malloc(1 *sizeof(pquentry_t*));
    		pq->maxLength = 1;
    	} else {
    		pq->elements = (pquentry_t**)realloc(pq->elements, (pq->length * 2) * sizeof(pquentry_t*));
    		pq->maxLength = (pq->length * 2);
    	}
    }
    

    Zum testen habe ich einfach mal 100 Werte reinschreiben lassen, doch aus irgendeinem Grund wird bei der maxLength von 16 ein Breakpoint von VS ausgelöst.
    Im Internet habe ich gelesen das es was mit der Speicherbegrenzung von einem MB zu tun hat. Deshalb habe ich den Speicher erhöht, doch leider wird der Breakpoint immer noch ausgelöst. Wenn ich den ganzen Speicher beim ersten mal mit malloc erstelle, klappt es. Muss ich noch was an VS einstellen oder ist das ein Fehler in meinem Code?

    Edit: hat sich erledigt, habe den Fehler schon selber gefunden 🙄



  • Das ist immer noch komplett C => falsches Forum



  • Marco_ru schrieb:

    habe doch noch ein kleines Problem mit den Vergrößerung des Arrays.

    Man kann die Größe eines C-Arrays nicht ändern - sie wird 1x und endgültig bei der Definition festgelegt.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum C (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


Log in to reply