[gelöst] array an Funktion übergeben/bzw array zurückgeben



  • Hallo,

    bin totaler Anfänger.
    Habe in anderen Sprachen aber schon Kenntnisse gesammelt.

    Mein großes Problem ist folgendes:

    ich möchte mein Array an eine Funktion übergeben, dieses Array soll nicht verändert werden.
    In der Funktion soll dann die "Matrix" transponiert werden. (was nicht das Problem ist)
    Und danach soll das Ergebnis zurückgegeben werden und in D gespeichert werden.

    Das Problem ist, dass ich nicht weiß, wie ich ein Array an eine Funktion übergebe bzw ein Array aus einer Funktion zurückgebe und in einer neuen Variable speichere.

    Am ende möchte ich dann im Hauptprogramm C haben und D wobei D = CT.

    Habe bei meinen Recherchen im Internet leider nichts dazu gefunden, so dass ich vermute, dass es nicht möglich ist.

    #include <iostream>
    #include <cmath>
    
    [Rückgabewert ?] transpose(double C,n)
    {
         // hier wird dann C modifiziert und zurückgegebn  
    }
    
    int main(int argc, char* argv[])
    {
    
        double C[n*n] =  {1, 2, 3,
                          4, 5, 6,
                          7, 8, 9 };
    
        D = transpose(C,n); // rückgabewert soll in D gespeichert werden
    
        system ("pause");
        return 0;
    }
    

    Hoffe man kann mir noch helfen^^

    Mfg Lirave


  • Mod

    Nimm statt eines Arrys einen std::vector. Dieser hat im Gegensatz zu Arrays die gleiche Übergabesemantik wie all die anderen Datentypen die du schon kennst.

    edit: Oder alternativ eine einfache Matrixklasse:

    template<int zeilen, int spalten> struct matrix
    {
     double data[zeilen][spalten];   // Oder auch nicht verschachtelt, je nach Geschmack
    };
    

    Dies hat dann all die Eigenschaften des Arrays, aber ebenfalls eine vernünftige Kopiersemantik.



  • "vector" wurde auch vielen anderen mit ähnlichen Problemen empfohlen als ich nach Antworten gesucht habe.

    Ich habe vergessen zu schreiben, dass wir bei den Problem Cholesky Zerlegung nur arrays benutzen sollen und keine Felder oder sonstiges.

    Hatte vorher probiert 2darray zu nehmen, da ich mit Matrizen so besser vorstellen kann, aber bin damit auch nicht viel weiter gekommen, deshalb wollte ich wissen, wie man das generell mit Arrays überhaupt macht.

    Bei 2darrays habe ich pointer an die Funktion übergeben, aber dann wird meine Matrix die ich an die Funktion übergebe ja überschrieben, außer ich erstelle eine neue, aber ich wusste dann nicht, wie ich ein 2darray aus einer Funktion zurückgebe.


  • Mod

    Lirave schrieb:

    "vector" wurde auch vielen anderen mit ähnlichen Problemen empfohlen als ich nach Antworten gesucht habe.

    Und aus gutem Grund. Arrays sind in C++ einfach nur unnötig umständlich.

    Ich habe vergessen zu schreiben, dass wir bei den Problem Cholesky Zerlegung nur arrays benutzen sollen und keine Felder oder sonstiges.

    😕 Erklär doch mal den Unterschied zwischen Feld und Array. Der einzige den ich sehe ist die Sprache.

    Hatte vorher probiert 2darray zu nehmen, da ich mit Matrizen so besser vorstellen kann, aber bin damit auch nicht viel weiter gekommen, deshalb wollte ich wissen, wie man das generell mit Arrays überhaupt macht.

    Indem man sie vermeidet 😉 . Mach wenigstens eine Klasse drum, wie mein zweiter Vorschlag (den ich noch oben reineditiert habe und den du evtl. noch nicht gelesen hast). Meinetwegen auch ohne Templates(von denen du vermutlich noch nie gehört hast)) und ohne jede Klassenmethoden(dito) als reiner Datenhalter. Hauptsache ist, dass dadurch die für Anfänger verwirrende Arraysemantik vermieden wird, ohne Nachteile.

    Bei 2darrays habe ich pointer an die Funktion übergeben, aber dann wird meine Matrix die ich an die Funktion übergebe ja überschrieben, außer ich erstelle eine neue, aber ich wusste dann nicht, wie ich ein 2darray aus einer Funktion zurückgebe.

    Ja, das ist trickreich, nicht wahr 😃 ? Genau deswegen auch die Ratschläge die du bekommen hast. Du müsstest zwei Arrays übergeben, eine unveränderliche Quelle (mach die Elemente const) und ein veränderliches Zielarray. Oder einen Zeiger auf ein dynamisch angefordertes Array aus der Funktion zurückgeben, was wiederum wenig lehrreich bezüglich des C++-Stils wäre, da es RAII massiv verletzt.
    All diese Probleme hast du nicht, wenn du das Array in einem struct kapselst. Denn dies kannst du dann ganz normal hin und herkopieren wie du es schon kennst.



  • #include <iostream>
    #include <cmath>
    
    double[] transpose(double C[],n)
    {
         // hier wird dann C modifiziert und zurückgegebn  
    }
    
    int main(int argc, char* argv[])
    {
    
        double C[n*n] =  {1, 2, 3,
                          4, 5, 6,
                          7, 8, 9 };
    
        D = transpose(C,n); // rückgabewert soll in D gespeichert werden
    
        system ("pause");
        return 0;
    }
    

    Das wars schon 😃 😃 😃


  • Mod

    Die erinnerung schrieb:

    Das wars schon 😃 😃 😃

    Mit zahlreichen Fallen die ein Anfänger noch nicht einmal sieht und schlechter Stil ist es auch noch.



  • SeppJ schrieb:

    Die erinnerung schrieb:

    Das wars schon 😃 😃 😃

    Mit zahlreichen Fallen die ein Anfänger noch nicht einmal sieht und schlechter Stil ist es auch noch.

    ich hab einfach seinen Code genommen und auf seine "Bdürfnisse" oder seine Problemstellung angepasst. 😉



  • Die erinnerung schrieb:

    SeppJ schrieb:

    Die erinnerung schrieb:

    Das wars schon 😃 😃 😃

    Mit zahlreichen Fallen die ein Anfänger noch nicht einmal sieht und schlechter Stil ist es auch noch.

    ich hab einfach seinen Code genommen und auf seine "Bdürfnisse" oder seine Problemstellung angepasst. 😉

    Woher weisst du was seine Bedürfnisse sind? Wenn er das Problem einach nur lösen wollte, dann würde er dafür wohl am besten Matlab o.ä. nehmen oder das gleich von Hand lösen..

    Und da er das nicht gemacht hat geht es ihm offensichtlich darum etwas zu lernen, was er von dem dir gezeigten Code nicht tut.

    @Lirave
    Wenn du tatsächlich keine anderen Sachen, wie std::vector benutzen darfst, dann würde ich dir empfehlen dafür einfach ein "Result"-Parameter zu machen.

    void transpose(const double* A, double* R, int n)
    {
    //...
    }
    

    A übergibst du dann einfach und veränderst du ja nicht, also const und das Resultat speicherst du in R.



  • ich habe erst einmal das von "Die erinnerung" ausprobiert, da meckert aber mein Compiler.

    Bild

    Hoffe es liegt nicht an Dev c++

    Drakon wenn ich die Funktion so gestalte wie von dir vorgeschlagen,

    void transpose(const double* A, double* R, int n)
    {
    //...
    }
    

    wie kopiere ich dann das Array vorher ?

    double C[n*n] =  {1, 2, 3,
                          4, 5, 6,
                          7, 8, 9 };
    
    double R[n*n];
    for ( int i=0;i<n*n;i++)
        R[i] = C[i];
    
    transpose(C,R,n);
    

    So wie oben ist es mMn zu viel Aufwand. Und sollte ich wiedereinmal ein Array kopieren wollen, müsste ich erneut die drei Zeilen hinschreiben.
    Am liebsten wäre es mir in einer Funktion, wo ich aber wieder bei dem selben Problem bin.



  • Er hat gesagt er will ein array übergeben, und eins zurückerhalten.

    Ach ja, wenn du eine Matrix als Ergebnis zurück haben willst dann musst du double[][] schreiben, als Rückgabetyp. Das gleiche gilt natürlich für den parameter C



  • Die erinnerung schrieb:

    Er hat gesagt er will ein array übergeben, und eins zurückerhalten.

    Du weisst aber schon, dass man Arrays weder als Parameter noch als Rückgabetyp verwenden kann? 🙄



  • Nexus schrieb:

    Du weisst aber schon, dass man Arrays weder als Parameter noch als Rückgabetyp verwenden kann? 🙄

    Also geht es nur mit Pointern so wie Dragon gezeigt hat ?



  • Nein, es wurden ja andere Alternativen wie std::vector genannt. Wenn die Anzahl Elemente zur Kompilierzeit bekannt ist, würde ich std::tr1::array empfehlen (sofern vorhanden).

    Ansonsten kannst du auch ein Array in ein struct packen, dann bekommt es Wertsemantik ( std::tr1::array ist im Prinzip das, mit zusätzlichen netten Features).


  • Mod

    Hier mal ein hoffentlich anfängerverständlicher Ansatz. Naja, nicht vollverständlich, aber zumindest verständlich wie man es benutzt.

    template<unsigned int size> struct matrix
    {
     double data[size*size];
    };
    
    template<unsigned int size> matrix<size> transpose(matrix<size> D)
    {
     // D.data transponieren, dabei size als Größe nehmen. Dann D zurückgeben:
      return D;
    } 
    
    int main()
    {
      matrix<3> C =  {{1, 2, 3,  // Müssen jetzt doppelte Klammern sein
                       4, 5, 6,
                       7, 8, 9} };
     matrix<3> result=transpose(C);
    }
    


  • Die erinnerung schrieb:

    Er hat gesagt er will ein array übergeben, und eins zurückerhalten.

    Und ich sage dass das ohne einen anständigen Wrapper keine gute Idee ist.

    Ach ja, wenn du eine Matrix als Ergebnis zurück haben willst dann musst du double[][] schreiben, als Rückgabetyp. Das gleiche gilt natürlich für den parameter C

    Nein. Schau dir die Grundlagen über Zeiger und Arrays nochmal an. Auch dein obiger Code zeugt davon, dass du das tun solltest.

    @Lirave
    Man kann das ganze in einer Klasse wrappen (wie es z.B boost::array oder std::tr1::array für statisch Arrays oder std::vector für dynamische macht) oder aber man macht es so, wie ich es gezeigt habe. Native Arrays kann man nicht per Wert zurückgeben (es wird nichts von selbst kopiert).



  • Gut, ich dachte, so funktionierts, aber dann halte ich mir hier raus, da ich hier sonst überhaupt keine Ahnung habe.



  • Wir sind leider noch nicht so weit gekommen im Stoff.

    Aber es klappt perfekt mittels

    void transpose(const double* Input, double* Result, int n)
    {
    //...
    }
    

    Denke kann als gelöst geschlossen werden, danke euch vielmals für eure schnelle Hilfe.

    Mfg Lirave


Anmelden zum Antworten