Frage zur Logik bei Arrays

  • C++/CLI

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von exc-jdbi.

    Frage zur Logik bei Arrays

    Hallo zusammen,
    ich habe ein Verständnissproblem bzgl. der Arrays in C++ und verstehe die "Logik" dahinter nicht.
    Als "Beispielcode" Habe ich jetzt mal folgendes:

    C-Quellcode

    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4. int main()
    5. {
    6. string gaeste[4][2][2] =
    7. {
    8. {"Gast01", "Info01", "test1"},
    9. {"Gast02", "Info02", "test2"},
    10. {"Gast03", "Info03", "test3"},
    11. {"Gast04", "Info04", "test4"}
    12. };
    13. cout << "Erster Gast: " << gaeste[0][0][1] << "\n";
    14. cout << "Erster Gast: " << gaeste[1][1][0] << "\n";
    15. cout << "Erster Gast: " << gaeste[2][1][0] << "\n";
    16. cout << "Erster Gast: " << gaeste[3][1][0] << "\n";
    17. }


    Jetzt zu meiner Frage:
    in dem Abschnitt

    C-Quellcode

    1. string gaeste[4][2][2]

    gebe ich ja das "Array" vor und rufe es mit den darauffolgenden Zeilen auf.
    Aber
    ich versteh einfach noch nicht ganz wie die Zuordnung funktioniert,
    also was genau diese Zahlen in den Eckigen Klammern angeben.

    C-Quellcode

    1. cout << "Erster Gast: " << gaeste[0][0][1] << "\n";


    Heißt das
    Eckige Klammer1 -> Zeile 1,
    Eckige Klammer 2 -> Zeile 1 Attribut 2
    Eckige Klammer 3 -> Zeile 1 Attribut 3

    usw oder was genau rufen die auf? Weil wenn ich das so wie oben angegeben "Ausführe" dann würde bei der Zeile von oben
    Erster Gast: Info01
    rauskommen, was m. E. irgendwie keinen Sinn macht.

    Vielleicht stehe ich einfach nur auf dem Schlauch aber ich möchte das einfach verstehen...
    Evtl. kann mir das jemand verständlich erklären, ich wäre sehr dankbar dafür...
    Das was du da hast nennt sich Multidimensionales Array.
    Das heißt, du hast nicht nur eine, sagen wir einfach mal, Liste von Objekten, sonderm tief-verschachtelte Listen.

    Der [] Operator nennt sich Subscript Operator!

    Die eckigen Klammern bei Arrays haben zwei verschiedene Bedeutungen.
    1. Größendefinition: Dies wird angegeben bei der Deklaration des Arrays z.B [5] gibt an, dass das Array 5 Elemente enthält und [2][5] gibt an dass das Array zwei mal 5 Elemente enthält
    Die gesamte Größe ergibt sich durch Multiplikation aller Klammern je nachdem wie viele Dimensionen du angegeben hast.

    2. Index: Der Index ist eine Zahl von 0 bis Größe - 1. Du kannst auch höher gehen aber das ist UB!
    Der Index, anders als die Größe, zeigt an auf welches Objekt du zugreifen möchtest.
    Diese Art des Subscript Operators wird nur bei Zugriffen auf das Array verwendet.

    Somit wäre also [0][0][1] der Zugriff auf das zweite Element im gesamten Array.
    [0][1][0] wäre Zugriff auf das 3 Element in deinem Array wenn die Größe wie [4][2][2] definiert wurde.

    Lg Elanda :)
    ----------------------------------------------------------------------------------------------------------------------

    Premature optimization is the root of all evil.
    ~ Donald Knuth

    1. “There are only two kinds of languages: the ones people complain about and the ones nobody uses.
    2. “Proof by analogy is fraud.
    ~ Bjarne Stroustrup

    ----------------------------------------------------------------------------------------------------------------------
    Hallo und vielen Dank für deine Antwort. Leider muss ich sagen dass ich das irgendwie immer noch nicht so ganz begreif..
    Das "zweite Element" ist dann der inhalt in der geschweiften Klammer, also so { {0},{X},{0} } (Das X soll das zweite Element sein)?
    Gibts da evtl eine grafische Darstellung oder sowas?
    Also mit dem Index (quasi die erste eckige Klammer) zeigt an wieviele "Zeilen" es sind oder?
    Ich steh total auf dem Schlauch... ;(

    //edit: was ist UB?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „0ptix“ ()

    Ein (lebensrettender) Merksatz, den mein damals Informatik studierender damaliger Mitbewohner mitbrachte:
    "Zeile zuerst, Spalte später".

    Eine Array-Erklärung fängt besser erstmal mit einem eindimensionalem Array an.
    int numbs[10]; - das ist ein eindimensionales int-Array mit 10 Elementen: 10 Nummern (in einer Reihe)
    int numbs2d[6][10]; Das ist ein Array von int-Arrays mit 6 Elementen. Beachte: die 6 Elemente sind int-Arrays, jedes wieder mit 10 Elementen, also 6 mal die 10 Nummern in einer Reihe.
    Stell es dir als Tabelle vor, mit Zeilen und Spalten: 10 Nummern in einer Reihe sind eine (Tabellen-)Zeile, und 6 solcher Zeilen stehen untereinander.
    Dassis noch einfach, oder?

    Aber es geht weiter:
    int numbs3d[4][6][10]; Das ist ein Array von int[]Arrays mit 4 Elementen: Also quasi 4 solche Tabellen wie oben.
    Du kannst es dir auch räumlich vorstellen als Quader. Also wie du dir numbs1d in einer Reihe vorstellst, und numbs2d dann als Reihen untereinander - also als Tabelle, jetzt numbs3d als Tabellen, 3-dimensional angeordnet hintereinander.

    Mathematisch sind natürlich beliebig viele Dimensionen machbar, aber das kann man sich dann nicht mehr so schön vorstellen - normale menschliche Vorstellung spielt sich im 3-dimensionalen Raum ab, manche können sich als 4. Dimension noch eine Zeit-Achse vorstellen (ich zB eher nicht).
    Ich kanns auch deshalb nicht, weil ich nichtmal fürs einfachste denkbare 4-dimensionale Objekt den Begriff weiss (wenns den überhaupt gibt).
    Bis drei Dimensionen sind die Namen der einfachsten Objekte jedermann vertraut:
    Linie (eindimensional), Fläche (zweidimensional), Quader (dreidimensionsl)



    Zahlenangaben im Post bearbeitet

    Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @ErfinderDesRades
    "int numbs[9];" < 9 Elemente, nicht 10
    "int numbs2d[5][9];" < insgesamt 45 Elemente

    In C++ wird die Größe nicht mit Indizes angegeben sondern mit tatsächlicher Größe!

    @0ptix
    Und zu deiner Frage, "Was ist UB?"
    Das bedeutet Undefined Behaviour, was soviel heißt wie "unbekanntes Verhalten".
    Sprich, man weiß nicht was passieren wird!
    ----------------------------------------------------------------------------------------------------------------------

    Premature optimization is the root of all evil.
    ~ Donald Knuth

    1. “There are only two kinds of languages: the ones people complain about and the ones nobody uses.
    2. “Proof by analogy is fraud.
    ~ Bjarne Stroustrup

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

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Elanda“ ()

    ErfinderDesRades schrieb:

    0ptix schrieb:

    das ist ja quasi wie excel

    Ja, genau. Allerdings deine Deutung ist noch schief. Korrekt wäre:
    Bei gaeste[2][7][5] wäre es 3. Tabelle, 8.Zeile, 6. Wort


    Ach so also quasi von "groß" nach "klein".
    Wobei dann 3 eckige Klammern eigentlich nie gebraucht werden oder?
    Mit 2 eckigen kann ich ja alles darstellen denk ich mal.

    Aber noch mal vielen Dank, jetz hab ichs kapiert :)
    Gehen wir es mal so an!


    Du hast das Array:

    C-Quellcode

    1. int array[3][2][2] =
    2. { // erste klammer
    3. { // zweite klammer
    4. {0, 1}, {2, 3} // dritte klammern
    5. },
    6. {
    7. {4, 5}, {6, 7}
    8. },
    9. {
    10. {8, 9}, {10, 11}
    11. }
    12. } ;


    Das sieht dann ungefähr so aus, ich habe jetzt einfach mal die indizes als Elemente genommen

    Du könntest auch sagen, pro eckige Klammer geht das Array um ein Level Tiefer. Also [] -> {}

    Ok nun schauen wir mal, wie könntem wir die 9 Erhalten?

    Diese müssten wir wie folgt auflösen:[2][0][1]
    [2] < weil wir

    C-Quellcode

    1. {
    2. {8, 9}, {10, 11}
    3. }

    haben möchten

    [0] < weil {8, 9}
    und [1] < weil "9"

    Das erste Element fängt immer bei 0 an

    Interessanter fun fact:
    Ein Array wird imm RAM hintereinander abgespeichert, das heißt, egal wie wie viele Level du deklarierst, die Elemente sind immer noch hintereinander angeordnet!

    Das bedeutet
    Anstatt [1][0][0] könntest du auch [0][0][8] schreiben
    Aber tu das nicht, du weißt nie ganz sicher ob es im Geltungsbereich liegt.
    ----------------------------------------------------------------------------------------------------------------------

    Premature optimization is the root of all evil.
    ~ Donald Knuth

    1. “There are only two kinds of languages: the ones people complain about and the ones nobody uses.
    2. “Proof by analogy is fraud.
    ~ Bjarne Stroustrup

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

    0ptix schrieb:

    Ach so also quasi von "groß" nach "klein".
    Sehr bildlich gesprochen.
    Es geht um die Dimensionalität - jedes [] bedeutet eine Dimension.
    Jo - ist richtig - es geht von den höheren Dimensionen bis hinunter zu Dimension 1 (die "Spalten").
    Der Spruch "Zeile zuerst, Spalte später" betrachtet also nur 2 Dimensionen aber lässt immerhin das Prinzip anklingen.

    Willst du also von einem Array die Dimension erhöhen, so häng die [] nicht hinten an, weil dann verschiebt sich die Dimensionalität - also was vorher Spalte gewesen ist, ist dann auf einmal Zeile usw.
    Mal der Dimensions-Aufbau von deine gaeste[5][2][7]
    1 Dimension (Spalten): gaeste[7] - das 8. Wort
    2 Dimensionen (Zeilen+Spalten): gaeste[2][7] - die 3.Zeile, das 8. Wort
    3 Dimensionen (Tabellen+Zeilen+Spalten): gaeste[5][2][7] - 6.Tabelle, 3.Zeile, 8. Wort

    0ptix schrieb:

    Wobei dann 3 eckige Klammern eigentlich nie gebraucht werden oder?
    Mit 2 eckigen kann ich ja alles darstellen denk ich mal.
    Hmm, hmm ... wirst dich noch wundern! ;)

    Im Ernst: Jo, mit bis zu 2 Dimensionen kommt man schon ziemlich weit.
    Aber iwann muss denn doch eine dritte oder vierte her.
    Nur wenns soweit ist, dann kennst du dich hoffentlich inzwischen mit Listen aus. Die kann man in gleicher Weise mehrdimensional ausführen, und haben den Vorteil, dass sie im Gegensatz zum Array vergrössert/verkleinert werden können.
    Das spart im Zweifelsfall viel Speicherplatz, eröffnet aber auch nochmal ganz neue Möglichkeiten.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Nachtrag zu @ErfinderDesRades

    Ja, Arrays sind gut für fixed-size Mengen!
    Wenn du aber etwas dynamisches brauchst sind so wie ErfinderDesRades sagte, Listen notwendig!

    In C++ wäre der häufigste Container dafür std::vector
    Es ist wie ein Array aber dynamisch zuweisbar.
    Einziger Nachteil, wenn du mit Leistungskritischen Anwendungen wie z.B real-time threads arbeitest, sind dynamische Container nicht so geeignet, da sie dynamisch Speicher allozieren und diese Threads somit zu größeren Pausen zwingen können.

    Aber mach dir darum mal keine Sorgen, ich denke mal nicht das du das jetzt so dringend brauchst.
    Jetz weißt du ja mal bescheid

    Übrigens, in C++, vermeide C Arrays generell und verwende std::array stattdessen
    Also anstelle von "int [2]" verwende, "std::array<int, 2>"

    Das solltest du, soweit du nicht C verwendest, immer so tun da std array viel sicherer zu Handhaben ist! :)
    ----------------------------------------------------------------------------------------------------------------------

    Premature optimization is the root of all evil.
    ~ Donald Knuth

    1. “There are only two kinds of languages: the ones people complain about and the ones nobody uses.
    2. “Proof by analogy is fraud.
    ~ Bjarne Stroustrup

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

    ErfinderDesRades schrieb:

    normale menschliche Vorstellung spielt sich im 3-dimensionalen Raum ab, manche können sich als 4. Dimension noch eine Zeit-Achse vorstellen (ich zB eher nicht).
    Ich kanns auch deshalb nicht, weil ich nichtmal fürs einfachste denkbare 4-dimensionale Objekt den Begriff weiss (wenns den überhaupt gibt).
    Habe das Wort für das einfachste 4-dimensionale Objekt nu doch noch gefunden: Tesserakt.
    Gugge Tesserakt
    Ist hübsch, mit Animation.
    Und ich finde, zeigt auch recht eindrücklich, wie schwierig das sich noch vorzustellen ist ...
    Ich denke nach den tollen Erklärungen von @Elanda und @ErfinderDesRades ist das Thema durch. Wobei für's visuelle ...




    Array...[3, 3, 3]

    (Z)uerst (Z)eile, (SP)äter (SP)alte und (D)anach (D)imension - wobei Dimension in diesem Bild die Seiten darstellt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Maffi“ ()

    tja "danach die Dimension" ist grad falsch.
    Es muss heissen: "davor noch die dritte Dimension".
    Deswegen ist ein Quader mit drei unterschiedichen Kantenlängen auch besser zu erklären als ein Würfel, weil beim Quader haben die verschiedenen Dimensionen verschiedene Zahlen, sodass die Zuordnung sichtbar wird.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @0ptix

    Zur Logik einer Array.


    Ich sitze gerade an einem uralten Pc und kann daher nicht mit C++ schreiben,
    weshalb ich es kurz in C# erkläre.

    String ist immer so eine spezielle Sache, weil String eigentlich eine 1D-Char-Array ist.

    Es wurde oben schon erwähnt, dass String zu bevorzugen ist, auch wenn ich persönlich
    die Char-Array für vieles andere auch verwende. Das geht auch mit C++ Cli.

    C#-Quellcode

    1. string mystring = "MyString";
    2. char[] mychars = mystring.ToCharArray();



    Hier mal ein kleines Beispiel:
    Ich fange gleich mal mit einer ganz normalen String an.

    C#-Quellcode

    1. string firstname = "Johnny";
    2. string lastname = "Depp";


    Auf einen String betrachtet haben wir noch um keine Dimension erweitert

    C#-Quellcode

    1. var dim0a = firstname;
    2. var dim0b = lastname;


    Man kann natürlich Vornamen + Nachnamen in eine 1Dstring-Array setzen

    C#-Quellcode

    1. var dim1a = new[] { dim0a, dim0b };
    2. var dim1b = new[] { "Uschi", "Glas" };
    3. var dim1c = new[] { "Kiefer", "Sutherland" };
    4. var dim1d = new[] { "Nico", "Schulz" };
    5. var dim1e = new[] { "Lisa", "Schmitz" };


    Da mehrere Vor- und Nachnamen existieren kann man wiederum eine weitere Dimension daraus machen.

    C#-Quellcode

    1. var dim2a = new string[5][];
    2. dim2a[0] = dim1a;
    3. dim2a[1] = dim1b;
    4. dim2a[2] = dim1c;
    5. dim2a[3] = dim1d;
    6. dim2a[4] = dim1e;


    Das obere entspricht als Einzeiler dem hier.

    C#-Quellcode

    1. var dim2b = new string[][] { dim1a, dim1b, dim1c, dim1d, dim1e };


    Oder wenn Elementar aufgebaut werden soll

    C#-Quellcode

    1. var dim2c = new string[][]
    2. {
    3. new[] { "Johnny", "Depp" },
    4. new[] { "Uschi", "Glas" },
    5. new[] { "Kiefer", "Sutherland" },
    6. new[] { "Nico", "Schulz" },
    7. new[] { "Lisa", "Schmitz" }
    8. };


    Nun kann man eine weitere Dimension (3D) einführen in dem z.B. nach Geschlecht getrennt wird.
    Z.B. als Einzeiler

    C#-Quellcode

    1. var dim3a = new string[][][] { new[]{ dim1b , dim1e },new[] { dim1a, dim1c, dim1d } };


    Oder Elementar

    C#-Quellcode

    1. var dim3b = new string[][][]
    2. {
    3. new[]
    4. {
    5. new[]
    6. {
    7. "Uschi", "Glas"
    8. } ,
    9. new[]
    10. {
    11. "Lisa", "Schmitz"
    12. }
    13. },
    14. new[]
    15. {
    16. new[]
    17. {
    18. "Johnny", "Depp"
    19. } ,
    20. new[]
    21. {
    22. "Kiefer", "Sutherland"
    23. },
    24. new[]
    25. {
    26. "Nico", "Schmitz"
    27. }
    28. }
    29. };


    Nun stellt sich die Frage besteht eine Möglichkeit auf die 4 Dimension?
    Ja. Nämlich die 4D-Char-Array.
    Leider gibt es hier keine Extension "ToCharArray()". Daher eine kleine entsprechende Methode

    C#-Quellcode

    1. var dim4chars = ToChars(dim3b);
    2. private static char[][][][] ToChars(string[][][] str3d)
    3. {
    4. var l0 = str3d.GetLength(0);
    5. var result =new char[l0][][][];
    6. for (int i = 0; i < str3d.Length; i++)
    7. {
    8. result[i] = new char[str3d[i].Length][][];
    9. for (int j = 0; j < str3d[i].Length;j++)
    10. {
    11. result[i][j] = new char[str3d[i][j].Length][];
    12. for (int k = 0; k < str3d[i][j].Length; k++)
    13. {
    14. result[i][j][k] = str3d[i][j][k].ToCharArray();
    15. }
    16. }
    17. }
    18. return result;
    19. }



    Fazit:

    Array's können für Daten verwendet werden. Die Daten müssen jedoch zuerst strukturieren werden. Wieviel Dimensionen das eine Array schlussendlich hat, hängt mit der strukturtiefe der Daten zusammen.

    Werden die strukturierten Daten dynamisch verwaltet, ist es besser z.B. auf ListOfT zu wechseln. Es gibt aber auch noch andere Möglichkeiten wie z.B. ein Dataset.


    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()