"array" aus Funktionen



  • Ok. Ich bitte um Verständnis, wenn ich keine Lust habe, noch einen Beispielcode zu schreiben, deshalb zweige ich gleich das Einsatzgebiet. Allerdings zeigt dieser auch nur das, was ich meine vorhin beschrieben zu haben. Kann aber auch tatsächlich ein Irrtum meinerseits sein.

    //die diversen Berechungsfunktionen
    int calc_plasma_1 (intptr_t col_size, unsigned int x, unsigned int y, double, double)
    {
        int color = int
                    (
                        (col_size/2) + ((col_size/2) * sin(x / 8.0))
                        + (col_size/2) + ((col_size/2) * sin(y / 6.0))
                    ) / 2;
        return color;
    }
    
    int calc_plasma_2 (intptr_t col_size, unsigned int x, unsigned int y, double, double)
    {
        int color = int
                    (
                        col_size/2 + (col_size/2 * sin(x / 16.0))
                        + col_size/2 + (col_size/2 * sin(y / 8.0))
                        + col_size/2 + (col_size/2 * sin((x + y) / 16.0))
                        + col_size/2 + (col_size/2 * sin(sqrt(double(x * x + y * y)) / 6.0))
                    ) / 4;
        return color;
    }
    
    int calc_plasma_3 (intptr_t col_size, unsigned int x, unsigned int y, double, double)
    {
        int color = int
                    (
                        col_size / 2 + (col_size / 2 * sin(x / 10.0))
                        + col_size / 2 + (col_size / 2 * sin(y / 16.0))
                        + col_size / 2 + (col_size / 2 * sin(sqrt(double((x - Width / 2.0) * (x - Width / 2.0) + (y - Height / 2.0) * (y - Height / 2.0))) / 6.0))
                        + col_size / 2 + (col_size / 2 * sin(sqrt(double(x * x + y * y)) / 6.0))
                    ) / 4;
        return color;
    }
    
    const std::function <int (intptr_t, unsigned int, unsigned int, double, double)> Plasma::calc_plasma[4] =
    {
        &calc_plasma_1,
        &calc_plasma_2,
        &calc_plasma_3,
        &calc_plasma_4
    };
    
    //mein gemeinter "Methodenkörper"
    void showPlasmaScroller(HANDLE set,
                            std::vector <CHAR_INFO> palette,
                            std::vector <CHAR_INFO> palette_Chars,
                            std::vector <Char> charSet,
                            Plasma callPlasma,
                            size_t plasma_idx,
                            std::string text, double delay_col)
    {
        std::array <std::array <unsigned int, Height>, Width> plasma, buffer;
        std::array <CHAR_INFO, Width * Height> outBuffer;
        intptr_t col_size = (intptr_t)palette.size();
        size_t color;
        /*generate colors*/
        for(unsigned int x=0; x<Width; x++)
        {
            for(unsigned int y=0; y<Height; y++)
            {
                //Aufruf der diversen Berechnungsfunktionen
                color = callPlasma.calc_plasma[plasma_idx](col_size, x, y, 0.0, 0.0);
                plasma[x][y] = color;
            }
        }
        /*cycle colors & charScroll*/
      [EDIT: ab hier unerheblich fürs Thema]
    }
    

    (Die beiden doubles und die vierte Funktion gehören zu einer weiteren etwas komplexeren Methode, die ich noch mal extra ausschreiben musste, wollte die Funktion aber trotzdem schon dabei haben)

    Ich kann so unterschiedliche PlasmaScroller aufrufen, nur über die Variable plasma_idx.
    Der Punkt aber ist: Ich habe keine Ahnung, wie ich obige diverse Berechnungsfunktionen ohne diesen Index aufrufen kann.


  • Mod

    Gibt es einen tieferen Grund, wieso nicht einfach direkt die gewünschte Funktion an showPlasmaScroller übergeben wird?



  • Mmh ... ich schätze, weil ich im Moment auf dem Schlauch stehe. Kann sein, das es mir morgen oder später noch einfällt, im Moment habe ich aber keine Vorstellung, wie ich eine Funktion einer Funktion übergebe und wie ich sie dort aufrufen kann?


  • Mod

    lemon03 schrieb:

    Mmh ... ich schätze, weil ich im Moment auf dem Schlauch stehe. Kann sein, das es mir morgen oder später noch einfällt, im Moment habe ich aber keine Vorstellung, wie ich eine Funktion einer Funktion übergebe und wie ich sie dort aufrufen kann?

    Mit Funktionszeigern? Also dem Mittel, um das sich dieser Thread dreht?

    Besser wäre natürlich ein Template oder eventuell std::function, damit man flexibler bleibt in dem, was man als Funktion übergeben kann.



  • Da sich der Aufruf hier in einer relativ engen Schleife befindet hätte std::function möglicherweise einen merkbaren Overhead.
    Wenn nix dagegen spricht würde ich also eher nen Funktionszeiger nehmen oder aus der Funktion ein Template machen.

    Wobei... die Funktionen machen ja doch einiges. Da wird ja viel gerechnet u.a. mit Winkelfunktionen. Wird also vermutlich doch keinen grossen Unterschied machen.

    @lemon03
    Statt dem Array mit Datentyp T[4] macht du nen Funktionsparemter mit Datentyp T. Und rufst den dann einfach wie ne Funktion auf. Wie du es jetzt schon mit callPlasma.calc_plasma[plasma_idx] machst.



  • Ist zwar OT, trotzdem möchte ich auf std::hypot hinweisen. Eine Funktion, die leider ein Schattendasein fristet... 😞



  • Gut ok, danke. Muss mich noch ein wenig einlesen in die Vorschläge 😉



  • Habe es mal mit einem Funktionszeiger versucht.

    int formel_1(int a, int b){
    
        return a*b;
    }
    
    int formel_2(int a, int b){
    
        return a/b;
    }
    
    void calc_(int (*formel)(int, int))
    {
        int a = 40, b = 8;
        int ergebnis = formel (a, b);
        std::cout << ergebnis << '\n';
    }
    
    void aufruf_(int (*formel)(int, int))
    {
        formel = &formel_1;
        formel = &formel_2;
    
        calc_(formel_1);
        calc_(formel_2);
    
    }
    
    int main()
    {
    
        int (*formel)(int, int) = 0; // Anlegen eines Funktionszeigers, Initialisierung mit 0
    
        aufruf_(formel);
    
    }
    

    Wäre der soweit in Ordnung oder kann man das besser formulieren?



  • Was soll jetzt die aufruf_ Funktion und der Funktionspointer dort als Parameter? Ansonsten sieht das dann schon OK aus. Angewandt auf deinen Code würde deine showPlasmaScroller Funktion statt dem size_t plasma_idx Parameter dann einfach einen Funktionspointer nehmen und diese Funktion aufrufen.



  • Ich wollte das Beispiel eben näher bei meinem aktuellen Einsatzzweck schreiben. Und calc_() soll nicht in der main aufgerufen werden, sondern in einer weiteren Funktion.

    Mit Funktionspointer kann ich jetzt aber nichts anfangen. Ist ein Zeiger nicht ein Pointer bzw?



  • Ja Zeiger = Pointer. Jedenfalls ist der Parameter in der aufruf_ Funktion ziemlich sinnlos. Du übergibst von der main Funktion einen Zeiger der aber auf 0 zeigt, dann schreibst nacheinander die Adressen von zwei Funktionen da rein, nutzt den Pointer aber nie. So würde die Funktion genau das gleiche tun:

    void aufruf_()
    {
        calc_(formel_1);
        calc_(formel_2);
    }
    


  • Ok, dann ist aber nur hier überflüssig:?

    void aufruf_(int (*formel)(int, int))
    {
        //formel = &formel_1;
        //formel = &formel_2;
    
        calc_(formel_1);
        calc_(formel_2);
    
    }
    
    int main(){
    
        int (*formel)(int, int) = 0; // Anlegen eines Funktionszeigers, Initialisierung mit 0
    
        aufruf_(formel);
    
    }
    


  • Der ganze Parameter und die Variable in der main Funktion kann weg.



  • Ah, also?

    int formel_1(int a, int b)
    {
    
        return a*b;
    }
    
    int formel_2(int a, int b)
    {
    
        return a/b;
    }
    
    void calc_(int (*formel)(int, int))
    {
        int a = 40, b = 3;
        int ergebnis = formel (a, b);
        std::cout << ergebnis << '\n';
    }
    
    void aufruf_()
    {
    
        calc_(formel_1);
        calc_(formel_2);
    
    }
    
    int main(){
    
        aufruf_();
    
    }
    

    Aber bzw und beschwert sich der Compiler über die ungenutzte Variable 'formel'?

    EDIT: geändert



  • Uh, wenn das jetzt stimmt, ist mir das direkt ein wenig unheimlich, wie einfach das am Ende ist 😉



  • Ja stimmt. Eigentlich sind Funktionspointer auch nicht so kompliziert, außer der etwas merkwürdigen Syntax und wenn man sich mit dem Konzept angefreundet hat, dass man Funktionen als Parameter an andere Funktionen übergibt.



  • Jupp, danke vielmals 🙂 Wieder was gelernt.


  • Mod

    Und nun siehst du, wieso man nach dem fragt, was man erreichen möchte, nicht nach dem, wie man denkt, wie man zum Ziel kommt.



  • Amen 😉



  • Äh ... sorry, meinte natürlich danke 😉 War wohl gestern im falschen Film.


Anmelden zum Antworten