[C/C++] Problem mit dynamischer Speicheralloziierung

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Smokers, 10. Februar 2010 .

Schlagworte:
Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. 10. Februar 2010
    Problem mit dynamischer Speicheralloziierung

    Also die Aufgabe ist ein Programm zu entwickeln das aus einem vorgegebenen Alphabet eine lexikografische Ordnung an test zeichenketten vornimmt.

    Mein Problem liegt aber schon in der Alloziierung

    folgender Codeschnippsel :
    Code:
    char **test_zks;
     test_zks= (char**) calloc(anz_zk,sizeof(char*));
     for(i=0;i<anz_zk;i++){
     int zufall = zk_laenge - (rand()%zk_laenge);
     test_zks[i] = (char*) calloc(zufall,sizeof(char));
     }
     for(i=0;i<anz_zk;i++){
     int laenge = sizeof(test_zks[i])/sizeof(char);
     for(k=0;k<laenge;k++){
     test_zks[i][k] = a[(rand()%anz_chars)];
     }
     }
     for(i=0;i<anz_zk;i++){
     int laenge = sizeof(test_zks[i])/sizeof(char);
     printf("Zeichenkette %d: ",i+1);
     for(k=0;k<laenge;k++){
     printf("%c",test_zks[i][k]);
     }
     printf("\n");
     }
    
    
    Soll ein 2 Dimensionales Array erzeugen welches genau anz_zk Spalten enthalten soll.
    Wobei jede Zeile aus unterschiedlich aber maximal zk_laenge elementen (buchstaben) bestehen soll.

    Allerdings bekomme ich es nicht hin das unterschiedlich viele spalten erzeugt werden.
    ODer das befüllen haut nicht ganz hin , ich kann es nicht genau sagen.

    Ich bekomme egal was ich für zk_laenge (welches die max laenge darstellen soll) oder anz_zk eingebe immer nur 4 Spalten(also Buchstaben)
    Ich denke das es an den int laenge = sizeof(test_zks)/sizeof(char); Befehlen liegt, aber ich bin mir nicht sicher.

    Ich hoffe ihr habt das Problem verstanden und könnt mir helfen.
    Im Spoiler nochmal eine Testausgabe...

    Spoiler
    alphabet = {a,s,d,f,g,h}
    anz_zk = 7;
    zk_laenge = 3;


    --->
    Lexikographische Ordnung Ueber ein Vorgegebenes Alphabet
    --------------------------------------------------------


    Zeichenkette 1: fffd
    Zeichenkette 2: dadh
    Zeichenkette 3: ggha
    Zeichenkette 4: dfsf
    Zeichenkette 5: dfag
    Zeichenkette 6: hgag
    Zeichenkette 7: fafd
    Das Programm lief 56 Sekunden
     
  2. 10. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Das Problem liegt wirklich bei dieser Zeile:
    int laenge = sizeof(test_zks)/sizeof(char);

    Weil die "Funktion" sizeof dir nicht die Länge des allokierten Speichers zurückgibt,
    sondern die länge/größe des Types und in diesem Fall eines Pointers (4 Byte); dividert man diese
    durch die Länge des Types char (1 byte) so erhält man immer 4!

    Leider ist mit dem allokieren des Speichers nicht die Größe (nur Betriebsystemintern) bestimmt.

    Du müsstest entweder die Länge in einem extra Array speichern oder besser eine doppelte Schleife verwenden.

    Mfg Rushh0ur
     
  3. 10. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Mhh okay, wenn ich die länge so nicht auslesen kann is das erstmal okay.

    Ist es denn üerhaupt möglich diesen Speicherbereich so dynamisch mit random zahlen zu allokieren?!

    also so :

    for(i=0;i<anz_zk;i++){
    int zufall = zk_laenge - (rand()%zk_laenge);
    test_zks = (char*) calloc(zufall,sizeof(char));
    }
     
  4. 10. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    hmm... was ist denn der Unterschied zwischen malloc und calloc?
     
  5. 10. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung



    Ja klar geht das, dabei wird eine Länge um zk_leange-1 allokiert dh. wenn zk_leange den Wert 5 hat werden 4 Bytes reserviert. Für Zeichenketten solltest du ein Byte mehr allokieren für ein Terminerungszeichen, immer (meistens) hat es den Wert 0. Damit kann man auslessen wie lang eine Zeichenkette ist, quwasi gibt der 0-Byte-Wert das Ende an.

    Da calloc den Speicher mit Nullen füllt, ist das erste Zecihen direkt dein Terminerungszeichen und du hast eine Zeichenkette mit 0 Zeichen.
    Wenn du nun eine Zeichenkette mit 5 Zeichen haben willst, dann musst du deine Variable zk_leange den Wert 7 haben, da der MODULO operator den Rest zurück gibt ist dein allokierter Speicher (max) 6 Bytes lang. Nun kannst du die ersten 5 Bytes des Arrays beschreiben, der letzte Wert im Array ist dann das Terminerungszeichen.

    Durch diese Methode kannst du zB. mit der Funktion strlen, die Länge deiner Zeichenkette ermitteln und/oder mit printf und dem Paremeter %s die komplette Zeichenkette ausgeben.


    Etwas viel geschrieben ....

    Zum eigentlich Problem, setz doch deine zweite Schleife in die erste rein:
    Spoiler
    Code:
     test_zks= (char**) calloc(anz_zk,sizeof(char*));
     for(i=0;i<anz_zk;i++){
     int zufall = zk_laenge - (rand()%zk_laenge);
     test_zks[i] = (char*) calloc(zufall,sizeof(char));
    
     for(k=0;k<[B]zufall-1[/B];k++){ [COLOR="SeaGreen"]//Letztes Byte nicht Beschreiben da es als Terminerung fungiert[/COLOR]
     test_zks[i][k] = a[(rand()%anz_chars)];
     }
     }
    

    Und zum Ausgeben:
    Spoiler
    Code:
     for(i=0;i<anz_zk;i++){
     printf("Zeichenkette %s: ", test_zks[i]);
     printf("\n");
     }
    

    //Edit:

    Ist eigentlich das gleiche nur das bei malloc die absolute Größe direkt angegeben wird und der Speicher nicht initialisiert wird und bei calloc werden zwei größen Angegeben welche mit einander Multipliziert werden um die benötigte Speichergröße zu ermitteln, anschliesend wird der Speicher allokiert und mit Nullen initializiert.

    Mfg Rushh0ur
     
  6. 10. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    okay soweit wie du mir beschrieben hast funktioniert es nun,...

    ich habe jedoch ein neues problem ^^° ich weiß ich nerve,.. allersing muss ich es machen und weis sonst kaum jem der mehr weiß,.....

    bin nun beim umwandeln der buchstaben in zahlen, jedoch bekomm ich da glaube ich zugriffsfehler oder dergleichen :
    Code:
     protect me
    
    


    testausgabe:

    Spoiler
    Code:
    alphabet = {a,s,d,f,g,h,j,k,l,m}
    anz_zk = 10;
    zk_laenge =10;
    
    
    Zeichenkette 1: m=>2621380,f=>2,k=>2621380,l=>[B]2621380[/B],f=>2,a=>0,k=>2621380,d=>1,
    g=>3,a=>0,m=>[B]2621380[/B],
    Zeichenkette 12: m=>2621380,m=>2621380,m=>2621380,a=>0,
    Zeichenkette 5: g=>3,h=>4,d=>1,l=>2621380,
    Zeichenkette 5: l=>2621380,f=>2,f=>2,h=>4,a=>0,
    Zeichenkette 6: m=>2621380,l=>2621380,h=>4,a=>0,
    Zeichenkette 5: f=>2,g=>3,l=>2621380,
    Zeichenkette 4: g=>3,j=>2621380,d=>1,d=>1,j=>2621380,l=>2621380,
    Zeichenkette 7: k=>2621380,k=>2621380,j=>2621380,h=>4,g=>3,h=>4,j=>2621380,j=>26
    21380,h=>4,h=>4,h=>4,
    Zeichenkette 12: k=>2621380,g=>3,f=>2,j=>2621380,k=>2621380,k=>2621380,d=>1,
    Zeichenkette 8: j=>2621380,a=>0,a=>0,j=>2621380,l=>2621380,k=>2621380,k=>2621380
    ,h=>4,
    Das Programm lief 42 Sekunden
    
    wie man sieht sind manche zahlen viel zu hoch um zum index des alphabets zu stimmen, kann es sein das dort wieder dieses \0 byte oder so eine rolle spielt, oder mein zählverhalten in der funktion falsch ist?
     
  7. 10. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    ":", das komt bei der Ausgabe, sry war wohl mein Fehler:



    Dieser Zustand ist nicht definiert, dh. der Zustand kann 0 sein muss es aber nicht und wenn du Pech hast stürtz das Programm sogar ab.


    -------------------------------------------------------------------------------------------------

    Kein Problem, immer mit der Ruhe

    Deine Funktions numberOfChar ist leider etwas Falsch, der Ansatz ist aber da.
    Nochmals sizeof() gibt dir nicht die Länge deiner Zeichenkette zurück.

    Erstell am besten eine Funktion der du die Länge deines Alphabets übergibst:
    Code:
    int numberOfChar(char buchstabe, char* alphabet, int laenge){
     int i=0;
     for(i=0;i<=laenge;i++){
     if(buchstabe == alphabet[i]){
     return i;
     }
     }
    }

    Oder du benutzt strlen:
    Code:
    int numberOfChar(char buchstabe, char* alphabet){
     int i=0;
     int laenge = strlen(alphabet);
     for(i=0;i<=laenge;i++){
     if(buchstabe == alphabet[i]){
     return i;
     }
     }
    }
    
    [B]Aber nur wenn dein Alphabet Zeichenkette in etwa so aufgebaut ist (natürlich kann der inhalt varieren):[/B]
    char *alphabet = {"a", "s", "d", "f", "g", "h"};
    [B]oder so:[/B]
    char *alphabet = "asdefg";
    
    Mfg Rushh0ur
     
  8. 11. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Danke das hat mir schon seeeehr weitergeholfen.

    Ich bin nun soweit angekommen , das ich meinen Buchstaben explizit die Zahlen zuordnen will.
    Aber wahrscheinlich hab ich einfach immernoch nicht das Prinzip des Zählens von array werten gerafft.
    Okay bei char arrays kann ich es ja als string behandeln und es über strlen machen, bei int arrays geht das ja nicht.

    Kann ich dort nun sizeof(anz_zks_int)/sizeof(int) machen?
    Aus sämtlichen Seiten wird das angepriesen um die Anzahl an Array Elementen herauszufinden.


    Code:
     wegen code klau erstmal weg =)
    man is nirgendwo vor kommolitonen sicher
    };
     }
    Die letzte VOrschleife soll mir natürlich zeigen ob das denn mit der Zuweisung von Zahlenwerten geklappt hat.


    mein bubble_sort für die ZKs sieht auch noch nicht so rosig aus, aber das is nen anderes Problem


    (
    Spoiler
    void bubble_sort(int *array){
    int i, j, temp;
    for (i = ( ??????????? - 1); i >= 0; i--){
    for (j = 1; j <= i; j++){
    if (array[j-1] > array[j]){
    temp = array[j-1];
    array[j-1] = array[j];
    array[j] = temp;
    }
    }
    }
    }
    )


    Ich weiß ich bin nich so der C gimp,.. Java liegt mir ein wenig mehr
    Ist nicht ganz soo streng bisher fand ich ^^°
     
  9. 11. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    void bubble_sort(int **numbers, int count) {
     int i, o, tmp;
     
     for(i = count - 1; i > 0; --i) {
     for(o = 0; o < i; ++o) {
     if(*numbers[o] > *numbers[o + 1]) {
     tmp = *numbers[o];
     *numbers[o] = *numbers[o + 1];
     *numbers[o + 1] = tmp;
     }
     }
     }
    }
    
    int main(void) {
     int anz = 10;
     int **numbers = (int **) malloc(sizeof(int *) * anz);
     
     srand(time(NULL));
     
     int i;
     for(i = 0; i < anz; ++i) {
     numbers[i] = (int *) malloc(sizeof(int));
     *numbers[i] = rand() % 100 + 1;
     }
     
     for(i = 0; i < anz; ++i) 
     printf("%5d", *numbers[i]);
     
     printf("\n");
     
     bubble_sort(numbers, anz);
     
     for(i = 0; i < anz; ++i) 
     printf("%5d", *numbers[i]);
     
     free(numbers);
     
     return 0;
    }
    zur veranschaulichung
     
  10. 11. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Das funktioniert nur bei statischen Arrays (die auf dem Stack gespeichert werden), also z.B.
    Code:
    int array[5];
    Bei dynamischen Array (werden auf dem Heap gespeichert), musst du selbst die Anzahl der Elemente speichern, z.B. in einer zusätzlichen Variable.
     
  11. 12. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Ich danke euch vielmals,...
    ich hab alles nun zum laufen bekommen. Sicherlich nicht die angenehmste Variante, aber für diesen Beleg reichts =)

    danke =) bws sind raus.
     
  12. 14. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Okay,.. nachdem mein erstes Prgramm nun funktioniert, und es daran gilt das Programm zu modofizieren, sodass nichtmehr die Zeichenketten an sich intern geordnet werden, sondern die zeichenketten unverändert nur noch in eine Reihenfolge gebracht werden müssen, die auf das vorgegebene alphabet passt, komme ich an einen Punkt der mir Kopfschmerzen bereitet:

    Mein Code ist zur Zeit so :

    Code:
    protected :D
    


    Um das zu verdeztlichen hier ein Beispiel:

    ich habe das array welches 3 Elemente besitzt, diese elemente sind zeiger auf weitere int arrays .


    a[0] hat also eine länge von sagen wir mal 8 int werten, und a[1] eine länge von 5, wenn mein sortieralgorithmus also zum schluss kommt das diese beiden getauscht werden müssen, geht das ja denke ich mal nicht so einfach, weil ja bei a[0] zwar platz für 8x4byte ist aber bei a[1] nur 5x4byte und wir brauchen 8x4byte.

    also habe ich wie oben den speicher einfach neu allkoiert für die beiden elemente, trotzdessen kommt müll bei der sortierung raus.

    ein beispiel :

    Code:
    Lexikographische Ordnung ueber ein vorgegebenes Alphabet
    
    ----------------------------------------
    
    Ihr Alphabet lautet A={a,b,c,d,e} .
    
    
    Zeichenkette 1: acaa
    Zeichenkette 2: de
    Zeichenkette 3: a
    Zeichenkette 4: ee
    Zeichenkette 5: ba
    
    
    
    Zeichenkette 1 (int): 0200
    Zeichenkette 2 (int): 34
    Zeichenkette 3 (int): 0
    Zeichenkette 4 (int): 44
    Zeichenkette 5 (int): 10
    
    
    Zeichenkette 1 (sint): 0200
    Zeichenkette 2 (sint): 03866820
    Zeichenkette 3 (sint): 3
    Zeichenkette 4 (sint): 10
    Zeichenkette 5 (sint): 44
    wie ihr seht wird dort immer irgendwo müll erzeugt, was meiner meinung nach durch die begrenzung der speicherbereiche geschieht.

    und die sortierung ist auch noch ncith komplett richtig, wenn wenigstens die ersten zahlen stimmen würde -.-

    ich hoffe ihr könnt mir nochmal erneut helfen....
     
  13. 14. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Du denkst zu komplitziert; du arbeitest mit dynamischen Speicher, deine Variablen sind also Zeiger bzw. Pointer dh. einfache Addressen die auf einen Speicher zeigen.

    Du musst zum Tauschen einfach die Addressen vertauschen.

    Beispiel:
    Code:
    int cmp(char* zk1,char* zk2){ 
     int i=0;
     do
     { 
     if(zk1[i] > zk2[i]) return 1;
     if(zk1[i] < zk2[i]) return -1;
     if ((zk1[i] == zk2[i]) && (zk1[i] == 0)) return 0;
     }
     while (++i);
     return 0;
    }
    
    ...
    
     char *zk1 = "Test";
     char *zk2 = "ABC";
     
     if (cmp(zk1, zk2) == 1)
     {
    [B] char *swap = zk1;
     zk1 = zk2;
     zk2 = swap; [/B] 
     }
     
     printf("%s\n", zk1);
     printf("%s\n", zk2);
    
    In dem Beispiel hab ich jetzt keinen Speicher extra reserviert, da ich die Daten direkt definiert habe, aber im Prinzip ist es das selbe und man muss da keinen zusätzlichen Speicher reservieren.

    Die Daten bleiben im Speicher an der selben Position nur die Variablen die auf die Addresse zeigen haben die Addressen getauscht.
    Du kannst es dir wie zwei Hauser mit ihren Besitzer nebeneinander Vorstellen, wenn der eine Besitzer zum Nachbern umzieht und der andere genau umgekehrt zum anderen umzieht, dann bleiben die Häuser trotzdem da wo sie davor gestanden haben nur die Besitzer haben die "Addresse gewechselt".

    Mfg Rushh0ur
     
  14. 14. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    und genau das geht leider nicht,....

    ich habe mal mein vollen programm code hier im spoiler und die stelle die du damit dann meinst markiert...

    Spoiler
    Code:
    mhh mal vor komolitonen sichern [/SPOILER]
    
    Wenn ich das mache kann man wunderbar sehen, wie ... ach ich printe einfach das ergebnis ...
    
    [CODE]Ihr Alphabet lautet A={a,s,d,f,g,h,} .
    
    
    Zeichenkette 1: sshff
    Zeichenkette 2: ahhfh
    Zeichenkette 3: ahgh
    Zeichenkette 4: fhhg
    Zeichenkette 5: as
    Zeichenkette 6: aafs
    Zeichenkette 7: f
    
    
    //zum verständnis, ich wandle die Zks in Zahlen um um sie sortieren zu können, die zahlen beruhen auf den
     //Indexwerten aus dem Alphabet A
    Zeichenkette 1 (int): 11533
    Zeichenkette 2 (int): 05535
    Zeichenkette 3 (int): 0545
    Zeichenkette 4 (int): 3554
    Zeichenkette 5 (int): 01
    Zeichenkette 6 (int): 0031
    Zeichenkette 7 (int): 3
    
    
    
    Zeichenkette 1 (sint): 00310
    Zeichenkette 2 (sint): 01000
    Zeichenkette 3 (sint): 0545
    Zeichenkette 4 (sint): 0553
    Zeichenkette 5 (sint): [U][B]11 ---> das hier ist eigentlich 11533 wobei die 533 abgeschnitten wurde weil die array breite nicht getauscht wurde , genau wie bei den anderen zahlen, es kommt murks raus ^^°[/B][/U]
    Zeichenkette 6 (sint): 3000
    Zeichenkette 7 (sint): 3
     
  15. 15. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    Wow, viel Code...

    Du hast vergessen die länge der Zeichenketten zu vertauschen, die hast du ja auch seperat gespeichert und der gibt dir halt die ZK immer noch mit der alten länge aus. (Also nix abgeschnitten)

    Spoiler
    Code:
    void sort(int **array,int k,int* count_elements){ 
     int i=0,j=0;
     for(j=0;j<k;j++)
     {
     for(i=0;i<k-1;i++)
     { 
     // Länger ermitteln
     int count=0;
     if (count_elements[i] < count_elements[i+1])
     count = count_elements[i];
     else 
     count = count_elements[i+1];
     
     // Zeichenketten vergleichen
     int tmp;
     tmp = vgl(array[i],array[i+1],count);
     
     if(tmp == 1)
     {
     // Zeichenkette tauschen
     int* tmp = array[i+1];
     array[i+1]= array[i]; 
     array[i] = tmp; 
     
     // Zeichenkette länge tauschen
    [B] int itmp = count_elements[i+1];
     count_elements[i+1] = count_elements[i];
     count_elements[i] = itmp;[/B]
     }
     }
     }
    }
    

    //Edit: Ach und wenn du Speicher allocierst dann gib ihn mit free wieder frei wenn du ihn nicht brauchst. Und evtl. die Variable a vor der Benutzung initialisieren (char *a = "\0")

    Mfg Rushh0ur
     
  16. 15. Februar 2010
    AW: Problem mit dynamischer Speicheralloziierung

    wow,.. you made my day...
    ich danke dir vielmals das du dich in meinen code reingelsen hast und den fehler gefunden hast.

    Ich bin mir sicher ich wäre nicht mehr darauf gekommen, es funktioniert tatsächlich, und ich hatte wirklich die befürchtung das die allozierung auf den platz im array fest ist und ich es daher nicht umändern kann.

    ich hab schon mit realloc und alles sonem schmarn versucht, und nun gehts ^^ wahnsinn
     
  17. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.