Übergabe eines Arrays an funktion



  • wie wärs mit einem vector?

    greetz, Swordfish



  • CStoll schrieb:

    Die Größe eines Arrays muß bereits zur Compilezeit feststehen, deshalb dürften deine Ansätze, Arrays beliebiger Größe übergeben zu wollen, alle nicht funktionieren.

    Die Größe meines arrays steht von vornherein fest. Die imax jmax und kmax sind ja const int . Ich brauche diese nur an mehreren Stellen und möchte bei einer Änderung (ich muss das Programm nachher für viele verschiedene Größen laufen lassen) nicht immer an 20 Stellen die Größen ändern (außerdem übersehe ich dann irgendwann einmal eine.

    Oder gibt es eine Möglichkeit das array global zu definieren, wenn ich die einzelnen Funktionen jeweils in eigenen Dateien habe? Da es sich um einige Funktionen handelt, wird es sehr unübersichtlich, wenn ich einfach alles in eine Datei schreibe. Und zudem brauche ich mehrere Versionen, bei denen die Funktion gleich bleiben, aber eben unterschiedlich aufgerufen werden.

    Mit Vectoren kann ich nicht gut arbeiten, da ich immer wieder auf Nachbarn (3-Dimensional) zugreifen muss, sich aber die Dimensionen jeweils bei jedem Versuch ändern. Ich kann also nicht sagen, daß ich genau 20 Einträge in jeder Spalte habe oder so ähnlich.



  • floriank schrieb:

    CStoll schrieb:

    Die Größe eines Arrays muß bereits zur Compilezeit feststehen, deshalb dürften deine Ansätze, Arrays beliebiger Größe übergeben zu wollen, alle nicht funktionieren.

    Die Größe meines arrays steht von vornherein fest.

    Kennst du den Unterschied zwischen Laufzeit-Konstanten und Compilezeit-Konstanten? (nur so viel: als Arraygröße brauchst du letztere).

    Wenn die Größe des Arrays wirklich konstant ist, kannst du sie auch als globale Konstanten festlegen - dann erübrigt sich auch die Übergabe als Parameter 😉

    Mit Vectoren kann ich nicht gut arbeiten, da ich immer wieder auf Nachbarn (3-Dimensional) zugreifen muss, sich aber die Dimensionen jeweils bei jedem Versuch ändern. Ich kann also nicht sagen, daß ich genau 20 Einträge in jeder Spalte habe oder so ähnlich.

    Das hört sich nicht sonderlich konstant an - und schreit geradezu nach vector<>en 😉 (im Gegensatz zu einem Array kannst du bei einem vector nämlich festlegen, wie groß er werden soll).

    PS: Noch einmal: Wirf einen Blick in die FAQ.



  • //A:
    template<size_t imax, size_t jmax, size_t kmax>
    int erzeugung(float (&data)[imax][jmax][kmax])
    {
        // ...
        return 0;
    }
    
    // B:
    int erzeugung(size_t imax, size_t jmax, size_t kmax, float* data)
    {
        // ...
        return 0;
    }
    
    void foo()
    {
        float a[7][8][666];
        int rc = erzeugung(a); // call version A
        int rc2 = erzeugung(7, 8, 666, &(a[0][0][0])); // call version B
    }
    

    Das "+1" hab' ich weggelassen, weil mein Compiler (MSVC8) sonst die Template Arguments von "A" sonst nichtmehr "deducen" kann, bei Version "B" dann genauso damit's gleich wie "A" ist 😉



  • Ein Zeiger auf Dein dreidimensionales Array sieht so aus: float ()[jmax+1][kmax+1]
    mach nicht so'n Scheiss mit drei Sternen ( float
    **)!
    Schreib dir ein typedef z.B. so:

    int main() 
    { 
        const int imax =  10;  // dim1
        const int jmax =  20;  // dim2
        const int kmax =  30;  // dim3
    
        typedef float (*Ptr)[jmax+1][kmax+1];
    
        float data[imax+1][jmax+1][kmax+1];  
    
        Ptr pointer = data;
    
        pointer[0][2][3] = 4711.0;
    
        float test = data[0][2][3];  // test = 4711.0;
       // int erzeugung (Ptr pointer, int dim1);  Übergabe an Funktion Ptr + dim1
    }
    

    😉



  • alternativ kannst du auch so ein array mavhen

    data[imax * jmax * kmax]
    

    zugriff is dann so
    i + j*imax + k*jmax.



  • hustbaer schrieb:

    //A:
    template<size_t imax, size_t jmax, size_t kmax>
    int erzeugung(float (&data)[imax][jmax][kmax])
    {
        // ...
        return 0;
    }
    
    // B:
    int erzeugung(size_t imax, size_t jmax, size_t kmax, float* data)
    {
        // ...
        return 0;
    }
    
    void foo()
    {
        float a[7][8][666];
        int rc = erzeugung(a); // call version A
        int rc2 = erzeugung(7, 8, 666, &(a[0][0][0])); // call version B
    }
    

    Das "+1" hab' ich weggelassen, weil mein Compiler (MSVC8) sonst die Template Arguments von "A" sonst nichtmehr "deducen" kann, bei Version "B" dann genauso damit's gleich wie "A" ist 😉

    Vielen Dank. Leider funktioniert es bei mir nicht wirklich. Im Fall B, kann ich nicht die einzelnen Werte bei a (z.B. a[i][j][k] beschreiben, es kommt immer die Fehlermeldung, daß ich zuviele Argumente bei a habe, und im Fall A, akzeptiert er die globale Definition von imax... nicht. Wie gesagt, ich habe ein Hauptprogramm und die Funktionen in eigenen Dateien.

    balduin schrieb:

    Ein Zeiger auf Dein dreidimensionales Array sieht so aus: float ()[jmax+1][kmax+1]
    mach nicht so'n Scheiss mit drei Sternen ( float
    **)!
    Schreib dir ein typedef z.B. so:

    int main() 
    { 
        const int imax =  10;  // dim1
        const int jmax =  20;  // dim2
        const int kmax =  30;  // dim3
    
        typedef float (*Ptr)[jmax+1][kmax+1];
    
        float data[imax+1][jmax+1][kmax+1];  
        
        Ptr pointer = data;
    
        pointer[0][2][3] = 4711.0;
    
        float test = data[0][2][3];  // test = 4711.0;
       // int erzeugung (Ptr pointer, int dim1);  Übergabe an Funktion Ptr + dim1
    }
    

    😉

    Auch hierfür danke. Ich habe es ausprobiert, aber es scheint wieder daran zu scheitern, daß ich in verschiedenen Dateien arbeite.

    öko schrieb:

    alternativ kannst du auch so ein array mavhen

    data[imax * jmax * kmax]
    

    zugriff is dann so
    i + j*imax + k*jmax.

    So habe ich es jetzt hinbekommen (auch wenn es nicht die schönste Variante ist, aber sie klappt).

    Jetzt wirft mir der Compiler aber immer folgende Fehlermeldung raus:

    1>Lorenzo.obj : error LNK2005: "unsigned int __cdecl konvertierung(float)" (?konvertierung@@YAIM@Z) ist bereits in Konvertierung.obj definiert.
    1>Main.obj : error LNK2005: "int __cdecl erzeugung(int,int,int,float *)" (?erzeugung@@YAHHHHPAM@Z) ist bereits in Erzeugung.obj definiert.
    1>Main.obj : error LNK2005: "unsigned int __cdecl konvertierung(float)" (?konvertierung@@YAIM@Z) ist bereits in Konvertierung.obj definiert.
    1>Main.obj : error LNK2005: "int __cdecl lorenzo(int,int,int,int,float *,unsigned int *)" (?lorenzo@@YAHHHHHPAMPAI@Z) ist bereits in Lorenzo.obj definiert.
    1>Schreiben.obj : error LNK2005: "int __cdecl schreiben(int,int,int,int,float *,unsigned int *)" (?schreiben@@YAHHHHHPAMPAI@Z) ist bereits in Main.obj definiert.
    1>MSVCRTD.lib(crtexew.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WinMain@16" in Funktion "___tmainCRTStartup".
    1>C:\Dokumente und Einstellungen\FlorianK\Eigene Dateien\Visual Studio 2005\Projects\Lorenzo\Debug\Lorenzo.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
    1>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\FlorianK\Eigene Dateien\Visual Studio 2005\Projects\Lorenzo\Lorenzo\Debug\BuildLog.htm" gespeichert.
    1>Lorenzo - 7 Fehler, 7 Warnung(en)
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

    Kann mir dabei einer helfen. Die Meldungen verstehe ich überhaupt nicht.



  • floriank schrieb:

    Jetzt wirft mir der Compiler aber immer folgende Fehlermeldung raus:

    Das ist nicht der Compiler, sondern der Linker, der sich da beschwert. Er findet mehrere Definitionen der Funktionen konvertierung, erzeugung, lorenzo und schreiben, und weiß nun nicht, welche er benutzen soll. Das liegt vermutlich daran, dass du die Funktionen in einer Headerdatei definiert hast, oder .cpp-Dateien mittels Includedirektive in andere .cpp-Dateien eingebunden hast.

    Andererseits findet der Linker keine WinMain-Funktion, was daran liegt, dass du den falschen Projekttyp erstellt hast. Du wolltest wohl ein Konsolenprojekt, hast aber ein Windows-Anwendungsprojekt angelegt.



  • MFK schrieb:

    Das ist nicht der Compiler, sondern der Linker, der sich da beschwert. Er findet mehrere Definitionen der Funktionen konvertierung, erzeugung, lorenzo und schreiben, und weiß nun nicht, welche er benutzen soll. Das liegt vermutlich daran, dass du die Funktionen in einer Headerdatei definiert hast, oder .cpp-Dateien mittels Includedirektive in andere .cpp-Dateien eingebunden hast.

    Headerdateien habe ich nicht, aber ich habe .cpp-Dateien in andere .cpp-Dateien eingebunden das ist richtig.

    Andererseits findet der Linker keine WinMain-Funktion, was daran liegt, dass du den falschen Projekttyp erstellt hast. Du wolltest wohl ein Konsolenprojekt, hast aber ein Windows-Anwendungsprojekt angelegt.

    Das ist richtig. Kann ich das nachträglich noch ändern?



  • @floriank:

    Wenn du das template verwenden willst dann pack es in eine Header Datei, und inkludiere die überall. Der Code für das template muss (!) dann auch mit in die Header Datei, sonst geht es nicht.

    Wenn du die andere Funktion verwenden willst musst du den Index "mit Hand" zusammenbasteln wie öko es geschrieben hat.


Anmelden zum Antworten