C++ Vector und Array

  • C++/CLI

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Gonger96.

    C++ Vector und Array

    Ich möchte mehrere Matrizen (double) darstellen.
    Diese sollen static sein. Ich will also Matrix::MeineMatrix abrufen können.
    In einer Methode brauche ich eine Auflistung solcher Matrizen. Die Länge kann dabei aber immer unterschiedlich sein. (5x5, 3x3 ...)
    Problem ist, dass ich nicht genau weiß wie ich das ganze jetzt darstellen soll.
    Das hier kann ich als Methodenkopf ja nicht benutzen. ​void Process(vector<double[][]> xyz)
    Ich würde ja jetzt die Matrix als vector darstellen. Geht jedoch nicht, da das Ding statisch sein soll.
    Die Liste der Matrizen soll man dynamisch füllen können.

    Kurzform:Ich möchte eine dynamische Liste mit festen Matrizen füllen.

    Ich suche nun eine möglichste kurze und elegante Lösung. Hat da jmd. eine Idee?
    Mach dir dich ebend selbst ne Liste. Parameteranzahl kannst du per variadic Templates realisieren.

    /Edit
    Für Matrix würde ich direkt Templates nehmen. Also matrix<m1, m2, m3...>::process. Dabei könnt man auch wieder die Nontemplate Parameter unbegrenzt machen.

    LaMiy schrieb:

    (5x5, 3x3 ...)
    Oder mach Dir pro Dimensionspaar eine abgeleitete Klasse einer gemeinsamen Basisklasse, diese Basisklasse kanst Du dann als Parameter übergeben.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Gonger96 Die Idee ist gut. Das würde ja auch in die Richtung von @RodFromGermany gehen.
    Ich habe nur ein Problem bei der Implementierung. Ich sitze nun schon einige Minuten dran und bekomm's einfach nicht hin.
    Was ist denn hier falsch?!

    Header

    C-Quellcode

    1. #pragma once
    2. template<size_t x, size_t y>
    3. class cMatrix
    4. {
    5. public:
    6. cMatrix(double[x][y] pMatrix);
    7. ~cMatrix();
    8. private:
    9. double[x][y] matrix;
    10. };


    cpp-Datei

    C-Quellcode

    1. #include "stdafx.h"
    2. #include "cMatrix.h"
    3. template<size_t x, size_t y>
    4. cMatrix<x, y>::cMatrix(double[x][y] pMatrix)
    5. {
    6. }

    LaMiy schrieb:

    Was ist denn hier falsch?
    Ein Template kannst Du machen, wenn Du eine Instanz für double und eine für int machen willst.
    Du willst unterschiedliche Anzahlen von Membern / Operanden haben, das geht nicht über Template.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Ich wollte gerade schreiben, dass ich es so habe, dass es kompiliert.
    Nur kann ich jetzt leider nicht zuweisen. (Wahrscheinlich der Grund den du meintest)

    C-Quellcode

    1. #pragma once
    2. template<size_t x, size_t y> class cMatrix
    3. {
    4. public:
    5. cMatrix(double pMatrix[x][y]);
    6. ~cMatrix();
    7. private:
    8. double matrix[x][y];
    9. };


    Wie soll ich es denn sonst machen?
    So geht's nicht.

    C-Quellcode

    1. class cMatrix
    2. {
    3. public:
    4. cMatrix(int pX, int pY);
    5. ~cMatrix();
    6. void SetValues(double pValues[x][y]);
    7. private:
    8. int x;
    9. int y;
    10. };

    LaMiy schrieb:

    Wie soll ich es denn sonst machen?
    Probier mal meinen ersten Vorschlag:
    Spoiler anzeigen

    C-Quellcode

    1. class MatrixBase
    2. {
    3. public:
    4. MatrixBase(int pX, int pY);
    5. ~MatrixBase();
    6. void SetValues(double pValues[x][y]);
    7. protected:
    8. int x;
    9. int y;
    10. };
    11. class Matrix3_3
    12. {
    13. public Matrix3_3() : MatrixBase(3, 3)
    14. {
    15. }
    16. };
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    LaMiy schrieb:

    void SetValues(double pValues[x][y]);
    Die Deklaration?
    Die muss ohne x und y gehen: void SetValues(double pValues[][]);
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Sowas ist unnötig. Ne matrix<width, height> ist am Schönsten. Ich werde heut Abend mal ne Lösung posten. Templates sind keinesfalls nur für variable Typen da, grade diese Verwendung ist am seltensten. Du kannst dich auch mal etwas in Templates, Nontype Parameter, variadic Templates und Rekursion durch Templates einlesen.
    @Gonger96
    Hab mich eigentlich schon eingelesen. Ist in C++ nur alles etwas schwieriger.
    z.B
    Spoiler anzeigen

    C-Quellcode

    1. template<unsigned int base, unsigned int n>
    2. struct Hoch
    3. {
    4. static const int wert{base * Hoch<base, n - 1>::wert };
    5. };
    6. template<> struct Hoch<2, 0>
    7. {
    8. static const int wert{ 1 };
    9. };

    Im Moment scheitert es ja lediglich an der Darstellung des mehrdimensional Double-Arrays.
    Ich werde es mir aber nochmal genauer ansehen.
    Wie wär sowas ?
    Spoiler anzeigen

    C-Quellcode

    1. template <size_t height, size_t width, typename precision = float, typename pr = void> class matrix;
    2. template <size_t height, size_t width, typename precision>
    3. class matrix<width, height, precision, typename enable_if<((is_floating_point<precision>::value || is_integral<precision>::value) && !is_same<precision, bool>::value)>::type>
    4. {
    5. static const size_t elem_width = width;
    6. static const size_t elem_height = height;
    7. using elem_precision = precision;
    8. public:
    9. matrix()
    10. {
    11. for(size_t w = 0; w < width; w++)
    12. {
    13. for(size_t h = 0; h < height; h++)
    14. {
    15. data[w][h] = 0;
    16. }
    17. }
    18. };
    19. matrix(precision _p[][height])
    20. {
    21. if((!_p) || !(*_p))
    22. throw invalid_argument("Invalid pointer");
    23. for(size_t w = 0; w < width; w++)
    24. {
    25. for(size_t h = 0; h < height; h++)
    26. {
    27. data[w][h] = _p[w][h];
    28. }
    29. }
    30. };
    31. precision** get_data() const {return static_cast<precision**>(const_cast<precision**>(data));};
    32. void write_to_stream(ostream& str)
    33. {
    34. for(size_t w = 0; w < width; w++)
    35. {
    36. for(size_t h = 0; h < height; h++)
    37. {
    38. str << data[w][h] << ' ';
    39. }
    40. str << endl;
    41. }
    42. };
    43. private:
    44. precision data[width][height];
    45. };
    46. int main(int argc, char* argv[])
    47. {
    48. float f[4][3] = {{1, 2, 3}, {3, 4, 2}, {11, 24, 563}, {7, 4, 4}};
    49. matrix<4, 3> m(f);
    50. m.write_to_stream(cout);
    51. return EXIT_SUCCESS;
    52. }
    @Gonger96 Perfekt, das klappt prima und ist wunderbar zum Lernen! Danke.
    Jetzt habe ich aber noch ein Problem wenn ich eine Liste von Matrizen erstellen will.
    ​vector<IMatrix<0 , 0>> filter Würde ja nur Matritzen mit 0x0 entsprechen. Ich möchte aber ja XxY
    Eine Idee wäre natürlich eine Schnittstelle anzugeben die jede Matrix implementiert.
    Oder geht das irgendwie einfacher?
    matrix<0, 0> geht ja sowieso nicht, die muss mind. 1 Element haben. Du hast 2 Möglichkeiten. Entweder nimmst du ne Basisschnittstelle
    Spoiler anzeigen

    C-Quellcode

    1. class matrix_base
    2. {
    3. public:
    4. size_t get_width() const = 0;
    5. size_t get_height() const = 0;
    6. };
    (kommt in C++ kein I vor, sowas sind Microsoft Richtlinien) oder du lässt es wieder über Templates lauufen. Gibt ja Template-Template-Argumente. Die Schnittstelle wäre n bisschen blöd wegen dem ganzen gecaste. Das Schönste wäre ne eigene Collection, die kann das blöde gecaste dann intern übernehmen (ohne Typeerasure geht's nicht). Oooder du lässt die ganzen Funktionen (*, +, /, invert() etc) über die Schnittstelle laufen (kannst die da auch direkt implementieren, dann wird's ne Basisklasse) und dann einfach in eine list<> oder 'nen vector<> packen.
    @Gonger96
    Funktionen brauche ich keine. Das ganze soll einfach eine Struktur sein, die eine 2x2 (3x3 4x3 ...) Matrix speichert.
    Später muss ich nur einzelne Werte über die Indices abfragen oder über die Werte schleifen.
    Eine eigene Collection sagt mir nicht so zu, da ich das Ganze später wrappen will. Könnte dann kompliziert werden.
    Wäre also dann eine Basisschnittstelle das geeignetere?
    Wrappen kannst du das sowieso nicht. Das ist zu komplex für .Net, da haste keine Chance. Du müsstest die komplette Architektur im Wrapper umschmeißen. Am einfachsten gehst du über'n Interface, du musst ja nur die Methode get_data() rein machen.