INI Datei auslesen und als #define speichern



  • Hallo,

    Ich fange am 01.08 meine Ausbildung an und sitze momentan in gleicher Firma im Praktikum. Habe dort die Aufgabe bekommen, das Spiel des Lebens zu programmieren. Das hab ich soweit auch hinbekommen (Bissl Hilfe ausm Internet, aber egal).
    Nun hab ich die Aufgabe bekommen, die #define-Werte, die ich für die Größe des Spielfeldes angegeben hatte, in eine INI Datei auszulagern. Ich bekomm es jedoch nicht hin, diese auszulesen, dass diese auch überall funktionieren.
    Es muss ja irgendwie mit fstream funktionieren und mein Ausbilder sagte was von malloc und alloc, also dynamischer Speicherverwaltung.
    Vielleicht habt ihr ja 'ne Idee..
    Hier der Code..

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <fstream>
    
    #define X 10
    #define Y 10
    
    void random_array(int A[X][Y])					//Random Array mit X,Y erzeugen
    {
        for(int i = 0; i < Y; i++)
    	{
            for(int j = 0; j < X; j++)
    		{
                A[i][j] = rand() % 2;				//Füllen mit 0 / 1
    		}
    	}
    }
    
    void array_anzeigen(int arr[X][Y])				//Random Array mit X,Y anzeigen
    {
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                printf(" %d", arr[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    
    void neues_array(int A[X][Y])
    {
        int temp[X][Y];
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                temp[i][j] = A[i][j];
            }
        }
    
        int maske[Y][X];
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                maske[i][j] = 0;
            }
        }
    
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                if(temp[i-1][j-1] == 1 && i     > 0 && j     > 0) ++maske[i][j];
                if(temp[i  ][j-1] == 1              && j     > 0) ++maske[i][j];
                if(temp[i-1][j  ] == 1 && i     > 0             ) ++maske[i][j];
                if(temp[i-1][j+1] == 1 && i     > 0 && j + 1 < X) ++maske[i][j];
                if(temp[i  ][j+1] == 1              && j + 1 < X) ++maske[i][j];
                if(temp[i+1][j  ] == 1 && i + 1 < Y             ) ++maske[i][j];
                if(temp[i+1][j-1] == 1 && i + 1 < Y && j     > 0) ++maske[i][j];
                if(temp[i+1][j+1] == 1 && i + 1 < Y && j + 1 < X) ++maske[i][j];
    
                if(maske[i][j] > 3 || maske[i][j] < 2)
                    A[i][j] = 0;
                else if(maske[i][j] == 3)
                    A[i][j] = 1; 
            }
        }
    }
    
    int main(void)
    {
        srand((unsigned int) time(NULL));
        int A[X][Y];
        random_array(A);
    
        int runde = 1;
        while(getchar())
        {
    		neues_array(A);
            printf(" Runde %i\n", runde);
            array_anzeigen(A);
    
            ++runde;
        }
    
        return 0;
    }
    

    In der INI steht dann sowas wie
    [general]
    X = 10
    Y = 10

    Danke schonmal für Eure Hilfe..



  • Benutz Variablen dafür.

    Ein "define" wird zur Compilezeit ersetzt.



  • oenone schrieb:

    Benutz Variablen dafür.

    Ein "define" wird zur Compilezeit ersetzt.

    Dass das define ersetzt wird, dachte ich mir schon.
    Wie setz ich jedoch "X" und "Y" auf globale Variable, wenn ich die in einer Klasse initialisiere durchs auslesen der INI?

    Denk ich gerad einfach zu kompliziert?



  • Lösch das:

    #define X 10
    #define Y 10
    

    Und ersetz das:

    int A[X][Y];
    

    durch das:

    size_t X, Y;
    // zuerst X und Y auslesen
    int **A = (int**)malloc(sizeof(int*)*X);
    for (int i=0; i<X; ++i) A[i] = (int*)malloc(sizeof(int)*Y);
    

    und pass die Funktionen an (int** statt [X][Y], X und Y als zusätzliche Parameter).

    Ach ja, das ist eigentlich C. Durch die von dir benutzten Header (bis auf das nicht benutzte fstream) und den Hinweisen deines Ausbilders sollte das wohl besser ins C-Subforum.



  • Dieser Thread wurde von Moderator/in Arcoth aus dem Forum C++ (auch C++0x und C++11) in das Forum C (C89, C99 und C11) verschoben.

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

    Dieses Posting wurde automatisch erzeugt.



  • Ich gehe davon aus, dass du die main-Funktion meintest, wo ich das

    int A[X][Y];
    

    austauschen sollte.

    Meine Main-Funktion sieht dementsprechend so aus:

    int main(void)
    {
    	char ini[] = "I:\\usr\programs\game_of_life\GameOfLife #2\GameOfLife\test.ini";
    	int X = GetPrivateProfileInt("general","X", 10, ini);
    	int Y = GetPrivateProfileInt("general","Y", 10, ini);
    
        srand((unsigned int) time(NULL));
        int **A = (int**)malloc(sizeof(int*)*X);
    	for (int i=0; i<X; ++i) 
    		A[i] = (int*)malloc(sizeof(int)*Y)
        random_array(A);
    
        int runde = 1;
        while(getchar())
        {
    		neues_array(A);
            printf(" Runde %i\n", runde);
            array_anzeigen(A);
    
            ++runde;
        }
    
        return 0;
    }
    


  • oenone schrieb:

    int **A = (int**)malloc(sizeof(int*)*X);
    for (int i=0; i<X; ++i) A[i] = (int*)malloc(sizeof(int)*Y);
    

    Das ist Müll.



  • Carreck schrieb:

    int main(void)
    {
    	char ini[] = "I:\\usr\programs\game_of_life\GameOfLife #2\GameOfLife\test.ini";
    	int X = GetPrivateProfileInt("general","X", 10, ini);
    	int Y = GetPrivateProfileInt("general","Y", 10, ini);
    
        srand((unsigned int) time(NULL));
        int **A = (int**)malloc(sizeof(int*)*X);
    	for (int i=0; i<X; ++i) 
    		A[i] = (int*)malloc(sizeof(int)*Y)
        random_array(A);
     
        int runde = 1;
        while(getchar())
        {
    		neues_array(A);
            printf(" Runde %i\n", runde);
            array_anzeigen(A);
     
            ++runde;
        }
     
        return 0;
    }
    

    Das ist Müll. Woher kennen deine 'array' Funktionen die Größen des Arrays?
    Die Doppel-Backslashes gehören mehrfach ins Stringliteral.



  • Dass das Programm an sich "Müll" ist, weiß ich auch. Ich versuche jedoch zu verstehen, wie das ganze gemeint ist mit dem dynamischen Speicherplatz.



  • Mir gefällt sehr gut, wie Du die Funktionalität in kleine Funktionen aufteilst. Offensichtlich bist Du kein kompletter Programmieranfänger (oder hast es im Blut. 😉 )

    Neben Funktionen sind das wichtigste die Objekte auf denen Deine Funktionen arbeiten.

    Das allozieren von Speicher, das arbeiten damit und das anschließende freigeben des allozierten Speichers ohne ein geignetes Objekt geht - wird aber IMHO sehr häßlich.

    Leider ist so ein Forum kein adäquater Ersatz für ein Fachbuch - und die Aufgabe ist nicht trivial...
    Aber ein Spielbrett, dessen Größe erst zur Laufzeit bestimmt wird, könnte so aussehen

    #include <stdlib.h>
    #include <stdio.h>
    #include <assert.h>
    
    // ein grid besteht aus Breite und Hoehe
    // und einer entsprechenden Anzahl Zellen
    struct grid{
      int dim1, dim2;
      int cells[]; // das sind die Zellen - in diesem Fall als sog.
                   // flexible array member
    };
    
    struct grid* gol_alloc_grid(int dim1, int dim2){
      assert(0<dim1);
      assert(0<dim2);
      // groesse bestimmen...
      const size_t size = sizeof(struct grid)+sizeof(int[dim1*dim2]);
      // und allozieren.
      struct grid *ret = calloc(1, size); 
      if(!ret)
        return NULL;
      ret->dim1=dim1;
      ret->dim2=dim2;
      return ret;
    }
    
    void gol_free_grid(struct grid *g){
      free(g);
    }
    
    int gol_get_cell(const struct grid *g, int x, int y){
      assert(g!=NULL);
      assert(!(x<0) && x<g->dim1);
      assert(!(y<0) && x<g->dim2);
      // richtigen Index berechnen.
      // Stell Dir vor alle Zeilen eines int[][] liegen hinter-
      // einander im Speicher.
      // Mal Dir evtl. auf, wie man dann einen einzigen Index
      // aus x und y Position berechnet
      // (so:)
      return g->cells[y*g->dim1+x]; 
    }
    
    void gol_set_cell(struct grid *g, int x, int y, int v){
      assert(g!=NULL);
      assert(!(x<0) && x<g->dim1);
      assert(!(y<0) && y<g->dim2);
      g->cells[y*g->dim1+x] = v;
    }
    
    void gol_print_grid(const struct grid *g){
      for(int i=0; i<g->dim2; ++i){
        for(int j=0; j<g->dim1; ++j)
          printf("%3d ", gol_get_cell(g, j, i));
        puts("");
      }
    }
    
    int main(void){
      struct grid *g = gol_alloc_grid(4,5);
      if(!g){
        fprintf(stderr, "failed to alloc grid!\n");
        return -1;
      }
      puts("before:");
      gol_print_grid(g);
      gol_set_cell(g, 2, 2, 42);
      puts("after:");
      gol_print_grid(g);
      gol_free_grid(g);
    }
    


  • Huhu,

    Also ich bin jetzt ein Stück weitergekommen. Das Auslesen aus der Datei funktioniert soweit und auch die Übergabe der Parameter läuft. Mein folgender Quellcode ist nun der hier:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <Windows.h>
    #include <string>
    #include <vector>
    
    using namespace std;
    int a = GetPrivateProfileInt("general","X",10,"./test.ini");
    int b = GetPrivateProfileInt("general","Y",10,"./test.ini");
    
    void random_array(int **A, int X, int Y)                  //Random Array mit X,Y erzeugen
    {
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                A[i][j] = rand() % 2;               //Füllen mit 0 / 1
            }
        }
    }
    
    void array_anzeigen(int **arr, int X, int Y)              //Random Array mit X,Y anzeigen
    {
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                printf(" %d", arr[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    
    void neues_array(int **A, int X, int Y)
    {
    	int **array1=NULL;
    	array1 = (int **) malloc(a*sizeof(int *));
    	for (int i=0;i<a;i++)
    		array1[i] = (int *) malloc(b*sizeof(int));
    	const int S = sizeof(array1);
    	const int T = sizeof(array1);
    
        int temp[S][T];
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                temp[i][j] = A[i][j];
            }
        }
    
        int maske[S][T];
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                maske[i][j] = 0;
            }
        }
    
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                if(temp[i-1][j-1] == 1 && i     > 0 && j     > 0) ++maske[i][j];
                if(temp[i  ][j-1] == 1              && j     > 0) ++maske[i][j];
                if(temp[i-1][j  ] == 1 && i     > 0             ) ++maske[i][j];
                if(temp[i-1][j+1] == 1 && i     > 0 && j + 1 < X) ++maske[i][j];
                if(temp[i  ][j+1] == 1              && j + 1 < X) ++maske[i][j];
                if(temp[i+1][j  ] == 1 && i + 1 < Y             ) ++maske[i][j];
                if(temp[i+1][j-1] == 1 && i + 1 < Y && j     > 0) ++maske[i][j];
                if(temp[i+1][j+1] == 1 && i + 1 < Y && j + 1 < X) ++maske[i][j];
    
                if(maske[i][j] > 3 || maske[i][j] < 2)
                    A[i][j] = 0;
                else if(maske[i][j] == 3)
                    A[i][j] = 1;
            }
        }
    }
    
    int main()
    {
    	int **array1=NULL;
    	array1 = (int **) malloc(a*sizeof(int *));
    	for (int i=0;i<a;i++)
    		array1[i] = (int *) malloc(b*sizeof(int));
    
    	const int X = a;
    	const int Y = b;
    
        srand((unsigned int) time(NULL));
    	random_array(array1, X, Y);
    
        int runde = 1;
        while(getchar())
        {
            neues_array(array1, X, Y);
            printf(" Runde %i\n", runde);
            array_anzeigen(array1, X, Y);
    
            ++runde;
        }
    
        return 0;
    
    }
    

    Jetzt bekomm ich folgende Fehlermeldung:

    Ausnahme (erste Chance) bei 0x013C44A3 in GameOfLife.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000011
    
    Falls ein Handler für diese Ausnahme vorhanden ist, kann das Programm möglicherweise weiterhin sicher ausgeführt werden.
    

    Leider weiß ich nun nichts damit anzufangen. Wenn ich debugge, sagt er mir folgendes:
    http://s14.directupload.net/images/140730/joly3ffc.png

    Hoffe, ihr könnt damit was anfangen :x



  • Da derefenzierst Du einen Nullzeiger.
    Wo? Keine Ahnung. Es fehlt ja die Hälfte.

    Welche Sprache willst Du eigentlich benutzen?
    Wenn Du nicht sicher bist: frag Deinen Ausbilder/Betreuer.

    Das, was Du jetzt machst, ist ein ganz übles Gemisch aus C und C++.



  • Da fehlt nichts, das ist wirklich der komplette Code.

    Welche Sprache ich benutzen soll ist C++.
    Ich bin aber ganz ehrlich: Ich habe auf dem Gymnasium Einsteigerübungen in Java gemacht und auf dem Berufskolleg 2 Jahre lang C# gemacht.
    Mit C geschweige mit C++ hab ich in diesem Sinne noch nie gearbeitet.

    Mir gefällt sehr gut, wie Du die Funktionalität in kleine Funktionen aufteilst. Offensichtlich bist Du kein kompletter Programmieranfänger (oder hast es im Blut. ;) )
    

    Daher: Nein, komplette Programmieranfänger bin ich nicht, aber man hat mich mehr oder weniger einfach ins kalte Wasser geworfen. Ich will mich jetzt aber auch nicht rausreden, weil verstehen tu ich das wohl, aber es fehlen halt hin und wieder Kleinigkeiten, die man beim wirklichen lernen von C/C++ drin hätte.


  • Mod

    Carreck schrieb:

    Ich will mich jetzt aber auch nicht rausreden, weil verstehen tu ich das wohl, aber es fehlen halt hin und wieder Kleinigkeiten, die man beim wirklichen lernen von C/C++ drin hätte.

    Ein guter Anfang wäre die Einsicht, dass "richtiges" C++, bis auf die Syntax, praktisch nix mit C zu tun hat. Dass dein Versuch von C++ von meinem Moderatorkollegen Arcoth direkt als C eingeordnet wurde und dieser Thread daher ins C-Forum verschoben wurde, sollte dich zum Nachdenken bewegen, was (und wie) du bisher über C++ gelernt hast. Das war nämlich kein C++, sondern C, und wer dir was anderes erzählt hat keine Ahnung und sollte schon allein deswegen nicht weiter als Quelle benutzt werden.



  • Carreck schrieb:

    Da fehlt nichts, das ist wirklich der komplette Code.

    Ah. Mein Fehler. Dann ist GetPrivateProfileInt() wohl aus Windows.h .

    Carreck schrieb:

    Welche Sprache ich benutzen soll ist C++.

    Das ist verwunderlich, da Dein Ausbilder von malloc() sprach. Aber das ist C(*). Bist Du wirklich, wirklich sicher?

    Carreck schrieb:

    beim wirklichen lernen von C/C++ drin hätte.

    C/C++ ist eine Formulierung, die nur in bestimmten Kontexten Sinn ergibt.
    Ich finde die Formulierung meist unpassend, da suggeriert wird, das C und C++ eine Sprache sind, nämlich genau jenes C/C++.
    Tatsächlich sind es aber zwei Sprachen.

    Frage ist: was machen wir jetzt mit Deinem Code, bevor das völlig den Bach runtergeht!? 🙂

    (*)Jedem der jetzt aufheult: Get a Life!



  • Furble Wurble schrieb:

    Frage ist: was machen wir jetzt mit Deinem Code, bevor das völlig den Bach runtergeht!? 🙂

    Von mir aus können wir das dann auch gerne in C machen. Wenn es sowieso schon C ist, dann ist es halt so.

    @Moderatoren: Tut mir Leid, dass nicht jeder genau den Unterschied kennt. Man fragt ja nicht umsonst in einem Forum um Hilfe, wenn man es könnte.

    Ich weiß halt wirklich nicht, wo der Null-Pointer ist. Selbst durchs debuggen komme ich nicht drauf :<



  • Was soll das array1 in neues_array ?
    Was steht in S bzw T ? Und was sollte dort stehen? Welche Dimensionen haben demnach temp und maske ?
    Werden allgemein die Dimensionen X und Y richtig herum verwendet? (Erst x dann y, wie beim malloc ?)



  • Carreck schrieb:

    Furble Wurble schrieb:

    Frage ist: was machen wir jetzt mit Deinem Code, bevor das völlig den Bach runtergeht!? 🙂

    Von mir aus können wir das dann auch gerne in C machen. Wenn es sowieso schon C ist, dann ist es halt so.

    IMHO ist die Funktion neues_array(); "Fucked up beyond repair". 🙂
    Die Allozierung ist Müll, das Interface erschließt sich mir nicht, sizeof in Zeilen 42(!) und 43 ist falsch (Du bekommst Die Größe eines int** ) und a, b, X, Y, S, und T werden wild durcheinander benutzt.
    Wegschmeissen. Neu und besser machen.

    Egal, ob Du jetzt C oder C++ benutzt, Dein Spielfeld gehört irgendwie gekapselt.
    Siehe z.B. nochmal meinen Post mit dem vielen Quelltext oben für ein Beispiel. (Das nicht so kompliziert ist, wie es scheint - viele assert() s und Kommentare.)
    Und um Gottes Willen: Ab jetzt kein C++ mehr für diese Aufgabe. (Es sei denn Dein Ausbilder will C++, dann um Gottes Willen kein C mehr!) 😉



  • Dann splitte ich das mal eben auf.

    void neues_array(int **A, int X, int Y)
    {
        int temp[20][20];
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                temp[i][j] = A[i][j];
            }
        }
    
        int maske[20][20];
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                maske[i][j] = 0;
            }
        }
    
        for(int i = 0; i < Y; i++)
        {
            for(int j = 0; j < X; j++)
            {
                if(temp[i-1][j-1] == 1 && i     > 0 && j     > 0) ++maske[i][j];
                if(temp[i  ][j-1] == 1              && j     > 0) ++maske[i][j];
                if(temp[i-1][j  ] == 1 && i     > 0             ) ++maske[i][j];
                if(temp[i-1][j+1] == 1 && i     > 0 && j + 1 < X) ++maske[i][j];
                if(temp[i  ][j+1] == 1              && j + 1 < X) ++maske[i][j];
                if(temp[i+1][j  ] == 1 && i + 1 < Y             ) ++maske[i][j];
                if(temp[i+1][j-1] == 1 && i + 1 < Y && j     > 0) ++maske[i][j];
                if(temp[i+1][j+1] == 1 && i + 1 < Y && j + 1 < X) ++maske[i][j];
    
                if(maske[i][j] > 3 || maske[i][j] < 2)
                    A[i][j] = 0;
                else if(maske[i][j] == 3)
                    A[i][j] = 1;
            }
        }
    }
    

    Das ist meine "neues_array()" Funktion.
    So funktioniert die auch. Nun hab ich in einer "test.ini" Werte stehen (X,Y), die für "20" eingesetzt werden müssen. Das ist eigentlich dann die Kunst dahinter. :x



  • Carreck schrieb:

    Nun hab ich in einer "test.ini" Werte stehen (X,Y), die für "20" eingesetzt werden müssen. Das ist eigentlich dann die Kunst dahinter. :x

    Exakt.
    Deswegen musst Du irgendwo Dein Spielfeld dynamisch allozieren(*).

    Offenbar weigerst Du Dich beharrlich, Dich mit Objekten auseinanderzusetzen. Das ist schade.
    Die Zeit würde ich investieren, bevor ich weiter mit int** arbeitete - Jedenfalls mit meinem heutigen Wissen. 😉

    (*) Wer jetzt auf VLAs verweist: Get lost!


Anmelden zum Antworten