Struct und Arrays



  • Ich wünsch euch einen schönen guten abend. Ich hab schon einiges über Structs und Arrays gelesen(u.a. in diesem Forum) und auch umgesetzt(unabhängig voneinander), allerdings habe ich schwierigkeiten wenn ich in meiner Struktur ein Array habe.

    ///////////////////////////////////////////////////////////////////////////
    // wenn ich das richtig verstanden habe ist 'kleinesfeld' keine Variable vom typ // matrix sondern ein anderer Bezeichner von matrix(liegt am typedef) jupp? :>
    // weiter gehts
    
    #include <iostream>
    using namespace std;
    
    typedef struct matrix
    {
        // nun lege ich ein Array mit 4 zeilen und 4 spalten an
        char carray[4][4];
    
    }kleinesfeld;
    
    int main()
    {
       // deklaration der variable muster vom type kleinesfeld
       kleinesfeld muster;
    
       // Problem ist das fuellen des 'kleinesfeld'
       // einen Zugriff bekomme ich doch ueber die namen getrennt von einem Punkte oder?
    
       muster.carry[4][4] = {
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                            };
    
        for(int i = 0; i < 5; i++){
          for(int j = 0; j < 5; j++){
                cout << muster.carry[i][j] << endl;
           }
         };
       return 0;
    }
    

    Mein Problem dabei ist, ich bekomme Fehlermeldung das in der Zeile wo ich auf das Array zugreife, Semikolons und geschweifte Klammer fehlen bzw. zu viele sind.

    Ist es möglich das das Array in der Strukur mit Zufallswerten gefüllt ist? 😡

    vielen dank erstmal fürs durchlesen :>



  • Also, eine Struktur wird mit "struct >Strukturname>" deklariert. Die struktureigenen Elemente werden dann über den Punktoperator angesprochen.

    Sprich: struct Struktur { int array[10][10]; }; überhalb der main-Funktion,
    Struktur.array[0][0] = 100; bspw. dann in der main-Funktion, um dem Feld an der Stelle (0,0) den Wert 100 zuzuweisen.

    PS: Wenn du das Array nicht explizit mit Werten initialisierst, wird da nix gefüllt. 😉



  • #include <iostream>
    
    struct matrix
    {
        char data[4][4];
        matrix(char default='x')
        {
            for (std::size_t x = 0; x < 4; ++x)
                for (std::size_t y = 0; y < 4; ++y)
                    data[x][y] = default;
        }
        friend std::ostream& operator << (std::ostream& out, matrix const& data)
        {
            for (std::size_t x = 0; x < 4; ++x)
            {
                for (std::size_t y = 0; y < 4; ++y)
                    out << data[x][y];
                out << "\n";
            }
        }
    };
    
    int main()
    {
        matrix muster;
        std::cout << muster << std::endl;
    }
    

    Ehm ein Array [4] bedeutet, du hast einen Index von 0 ... 3 ... also 4 Elemente bei 0 anfangend 😛



  • Keydo schrieb:

    ...

    ///////////////////////////////////////////////////////////////////////////
    // wenn ich das richtig verstanden habe ist 'kleinesfeld' keine Variable vom typ // matrix sondern ein anderer Bezeichner von matrix(liegt am typedef) jupp? :>
    // weiter gehts
    

    typedef <typ> <name>;

    ==> Definiert den Typ unter den angegebenen Namen. In deinen Fall ist das meines erachtens reine Verschwendung. Ich würde es wie folgt schreiben (da struct bereits einen Typ definiert):

    struct kleinesfeld // <-- Wie soll es wirklich heißen?
    {
        char carray[4][4];
    };
    

    Keydo schrieb:

    ...
    int main()
    {
       // deklaration der variable muster vom type kleinesfeld
       kleinesfeld muster;
    
       // Problem ist das fuellen des 'kleinesfeld'
       // einen Zugriff bekomme ich doch ueber die namen getrennt von einem Punkte oder?
    
       muster.carry[4][4] = {
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                            };
    

    Hier hast du gleich mehrere Fehler:
    1. In der Struktur nennst du das Array noch "carray", in deiner main-Funktion aber "carry".
    2. Eine Initialisierung eines Arrays geht nur bei der Deklaration. Nachträglich ist eine Initialisierung nur durch setzen aller einzelwerte separat möglich.

    Beispiel:

    int main()
    {
       char carray[4][4] = { // Deklaration UND Initialisierung
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                               {'x','x','x','x'},
                            };
    }
    

    3. Mittels "muster.carry[4][4] = ..." weist du der 5ten! Spalte/5ten Zeile etwas zu. Hierzu gleich mehr den einen weiteren Irrtum in dem Gebiet begehst du auch in der folgenden Schleife.

    Keydo schrieb:

    for(int i = 0; i < 5; i++){
          for(int j = 0; j < 5; j++){
                cout << muster.carry[i][j] << endl;
           }
         };
    

    Wenn du ein Array Deklarierst, stehen die Zahlen für die Anzahl der Elemente:

    char carray[4][4]; // ==> 4 Zeilen, 4 Spalten

    ABER: der Zugriff beginnt bei dem Index 0. Zulässige Werte sind daher jeweils 0..3 nicht aber 4. Deine Schleife würde mit hoher Wahrscheinlichkeit eine "Access Violation" auslösen, da der Zugriff außerhalb des Arrays erfolgt.

    Keydo schrieb:

    Mein Problem dabei ist, ich bekomme Fehlermeldung das in der Zeile wo ich auf das Array zugreife, Semikolons und geschweifte Klammer fehlen bzw. zu viele sind.

    Eine nachträgliche Initialisierung hättest du z.B. so machen müssen:

    for(int i = 0; i < 4; ++i)
       {
          for(int j = 0; j < 4; ++j)
          {
             muster.carray[i][j] = 'x';
          }
       }
    

    Wenn es einzeln für sich steht ist es besser immer ++i als i++ zu schreiben. Bei int noch relativ uninteressant, aber bei Klassen bedeutet dies das eine zusätzliche Kopie erfolgt.

    Ist es möglich das das Array in der Strukur mit Zufallswerten gefüllt ist?  :rage:
    

    Ja, da es nicht initialisiert wurde. Konstruktoren helfen 😉
    Aber nichts desto trotz: "Arrays stinken" 😉
    Letzteres meine ich hauptsächlich deshalb weil sich Arrays etwas anders verhalten als man vielleicht erwartet (siehe Initialisierung, siehe Unterschied Deklaration und Zugriff...).

    cu André



  • Super vielen dank, bei (D)Evil muss ich noch 2-3 Kapitel vor switchen um das alles nachzuvollziehen :> aber ich bin motiviert ^^

    Die Initialisierung eines Arrays in einem sruct ist aber ganz schön tricky...

    (kleinere Zusammenfassung): Wenn ich einen neuen Datentype mittels struct erstellen möchte welches als Element ein Array mit x*x Feldern hat, so bleibt mir entwerder die Option, die Initialisierung der Elemente im Array bereits bei der Deklaration vorzunehmen oder später im Program, da aber dann nur jedes Feld einzeln für sich. Was unter umständen bei mehreren Eintraege vlt. etwas unuebersichtlich wird.

    So nun habe ich ein Array mit 3 Zeilen und 3 Spalten. Wenn ich das Array in main() deklariere und Initialisiere kann ich Problemlos damit arbeiten.

    Möchte ich nun einen neuen Datentype matrix anlegen welches ein Array mit dem namen c_array beinhaltet.
    Mit Hilfe des neuen Datentypes und dem element Array, soll nun ein "+"-Pluszeichen dargestellt werden.

    Also Initialisiere ich c_array bereits bei der Deklaration mit den entsprechenden Zeilen und Spalten.

    Das merkwürdige dabei ist, deklariere und initialisiere ich mein Array in main() kann ich damit problemlos arbeiten(also ausgeben ^^), packe ich das gleiche array in struct... nölt der Compiler.

    #include <iostream>
    using namespace std;
    
    struct matrix{
    
    		char c_array[3][3] = {        
    								{' ', 'x', ' '},
    								{'x', 'x', 'x'},
    								{' ', 'x', ' '}
    						};
    
    };
    
    int main(){
    
    		for(int i = 0; i < 3; ++i)
    		{
    			for(int j = 0; j < 3; ++j)
    			{
    				cout << matrix.c_array[i][j];
    			}
    			cout << "\n";
    		}
    
    	return 0;
    }
    

    Fehler:

    ... -struct_array\main.cpp(7) : error C2059: Syntaxfehler: '{'
    ... -struct_array\main.cpp(7) : error C2334: Unerwartete(s) Token vor '{'; sichtbarer Funktionstext wird übersprungen
    ... -struct_array\main.cpp(24) : error C2143: Syntaxfehler: Es fehlt ';' vor '.'
    ... -struct_array\main.cpp(24) : error C2143: Syntaxfehler: Es fehlt ';' vor '.'
    

    fuuu !

    oh mann... 2 int variablen hbaen nicht so rumgezickt im struct wie ein array 8P



  • Wenn du die struct deklarierst, hast du ja auch noch keine Variable, die du befüllen könntest - die wird erst später angelegt. Und erst beim Anlegen der Variable kannst du deren Elemente füllen (entweder per Ctor oder mit einer Initialisierungsliste):

    //Möglichkeit a:
    struct matrix1
    {
      char c_array [3][3];
    
      matrix1()
      {
        for(int i=0;i<3;++i) for(int j=0;j<3;++j) c_array[i][j]=(i==1||j==1)?'x':' ';
      }
    };
    
    ...
    matrix1 m1;
    for(int i = 0; i < 3; ++i)
    {
      for(int j = 0; j < 3; ++j)
      {
        cout << m.c_array[i][j]; // Zeile 24
      }
      cout << "\n";
    }
    
    //Variante 2:
    strct matrix2
    {
      char c_array[3][3];
    };
    
    ...
    matrix2 m = {{' ','x',' '},{'x','x','x'},{' ','x','x}};
    for(...)//Ausgabeschleife wie oben
    


  • Keydo schrieb:

    Möchte ich nun einen neuen Datentype matrix anlegen welches ein Array mit dem namen c_array beinhaltet...
    Also Initialisiere ich c_array bereits bei der Deklaration mit den entsprechenden Zeilen und Spalten.

    Leider geht das auch nicht. Wie gesagt, "Arrays stinken" 🙂

    Du kannst in einer Struct/Class kein Element direkt initialisieren, die Initialisierung kann man im Konstruktor machen, letzteres geht für Arrays aber nicht wie du das willst. Wohl oder übel: Konstruktor mit Schleife für die Initialisierung.

    Arrays haben noch andere Einschränkungen, und man merkt sehr deutlich das Arrays für C konzepiert sind. In deinem Fall wären die Alternativen aber etwas übertrieben (std::vector ist z.B. eine solche Alternative).

    cu André



  • auch dir vielen dank CStoll !

    @asc oh je ^^, die alterntavie sprengt momentan sicherlich den Rahmen, können ma nächste Nacht machen *hust* ^^


Log in to reply