Struct Array an Funktion übergeben. wie dort ansprechen error:Der ausdruck muss einen klassentyp aufweisen



  • Und dann -> verwenden, nicht . .

    Dies ist keine Vorgabe des Lehrers, sondern qsort wird von C++ mitgelifert

    Jein. qsort ist Bestandteil der C-Standardbibliothek. In C++ nutzt man std::sort.

    Dies ist keine Vorgabe des Lehrers, sondern qsort wird von C++ mitgelifert. genauso wie ich ja auch

    int
    

    in

    int zahl
    

    nutze.

    Das sind verschiedene Dinge!
    int ist ein Schlüsselwort in C++, qsort wird von der Standardbibliothek bereitgestellt, dazu muss aber der Header cstdlib inkludiert werden. Das ist ein Unterschied.



  • Mir ist das Wort Standardbibliothek nicht eingefallen, deswegen der Vergleich mit int.

    Ich würde es auch anders realisieren, aber wenn da steht wir sollen qsort und struct so nutzen, dann geht es nicht anders.

    So habe nen online-compiler gefunden, wenn ich double duch PunktT ersetze das klappt nicht.

    So ganz verstanden habe ich das mit dem casten nach nicht Nathan.



  • int Vergleich(const void* a, const void* b)
    {
        PunktT *a_punkt = reinterpret_cast<PunktT *>(a); // mache aus a einen PunktT
        PunktT *b_punkt = reinterpret_cast<PunktT *>(b);
    
        // mache irgendetwas mit den Werten
        if (a_punkt->x > b_punkt->x && ...)
            ...
    }
    


  • Sone schrieb:

    element_t length() const
    {
        return std::pow( x*x + y*y + z*z, 1./3 );
    }
    

    Auch für Punkte im dreidimensionalen Raum gehört hier die Quadratwurzel hin.

    Davon ab ist es für die Aufgabe unnötig, die Wurzel zu ziehen, da die quadrierten Abstände die gleiche Größenrelation haben. Gerade wenn man viele Punkte sortieren will, macht das einen signifikanten Geschwindigkeitsunterschied.


  • Mod

    Nathan schrieb:

    int Vergleich(const void* a, const void* b)
    {
        PunktT *a_punkt = reinterpret_cast<PunktT *>(a); // mache aus a einen PunktT
        PunktT *b_punkt = reinterpret_cast<PunktT *>(b);
        
        // mache irgendetwas mit den Werten
        if (a_punkt->x > b_punkt->x && ...)
            ...
    }
    

    reinterpret_cast entfernt kein const, für desen Entfernung gibt es keinen Grund und reinterpret_cast ist auch die falsche Form.

    double sqr(double x)
    {
        return x * x;
    }
    
    double sqrlength(const Punkt& p)
    {
        return sqr(p.x) + sqr(p.y) + sqr(p.z);
    }
    
    int Vergleich(const void* a, const void* b)
    {
        double sqrlength_a = sqrlength(*static_cast<const PunktT*>(a));
        double sqrlength_b = sqrlength(*static_cast<const PunktT*>(b));
    
        return sqrlength_a < sqrlength_b ? -1 : sqrlength_a > sqrlength_b;
    }
    


  • camper schrieb:

    reinterpret_cast entfernt kein const, für desen Entfernung gibt es keinen Grund und reinterpret_cast ist auch die falsche Form.

    Mir ist gar nicht aufgefallen, dass die Parameter const void waren. 🙄
    Wann verwendet man denn reinterpret_cast? Ich dachte immer, das kommt zum Zuge wenn man einen Speicherbereich neu interpretieren muss, wie hier wo man rohen Speicher als Strukt interpretieren muss. Oder irre ich mich?


  • Mod

    Nathan schrieb:

    Wann verwendet man denn reinterpret_cast? Ich dachte immer, das kommt zum Zuge wenn man einen Speicherbereich neu interpretieren muss, wie hier wo man rohen Speicher als Strukt interpretieren muss. Oder irre ich mich?

    Ja, Pointer auf andere Typen zu casten ist der Zweck. Man sagt dem Compiler also "das sieht für dich aus wie X, aber du sollst es wie Y behandeln". Das ist aber etwas anderes als const_cast, welcher sagt "das sieht aus als wäre es konstant, aber behandele es, als wäre es nicht so" (oder umgekehrt).



  • OK, also wäre in diesem Fall ein reinterpret_cast<const PunktT> richtig?
    Warum verwendet camper dann static_cast?



  • ananas schrieb:

    Sone schrieb:

    element_t length() const
    {
        return std::pow( x*x + y*y + z*z, 1./3 );
    }
    

    Auch für Punkte im dreidimensionalen Raum gehört hier die Quadratwurzel hin.

    Ups, hast Recht.

    Davon ab ist es für die Aufgabe unnötig, die Wurzel zu ziehen, da die quadrierten Abstände die gleiche Größenrelation haben. Gerade wenn man viele Punkte sortieren will, macht das einen signifikanten Geschwindigkeitsunterschied.

    Ja, da hast du auch Recht.



  • So,damit mein code bis zuhause niht verschindet.

    #include<iostream> 
    #include <stdlib.h>
    using namespace std; 
    
    struct PunktT { double x; double y; double z; }; 
    
    int Vergleich(const void* ap, const void* bp) 
    { 
        //quadrieren und wurzel fehlt noch 
    // fehler liegt hier a.x geht nicht (Der ausdruck muss einen klassentyp aufweisen) 
       PunktT *a = (PunktT *)ap;
       PunktT *b = (PunktT *)bp; 
    
        // mache irgendetwas mit den Werten 
        if (a->x+a->y+a->z > b->x+b->y+b->z)
          return -1; 
        else if (b->x+b->y+b->z > a->x+a->y+a->z)
          return 1; 
        else return 0; 
    } 
    
    int main() 
    { 
        PunktT* p = new PunktT[2]; 
    
        p[0].x = 1.0; 
        p[0].y = 1.0; 
        p[0].z = 1.0; 
    
        p[1].x = 2.0; 
        p[1].y = 2.0; 
        p[1].z = 1.0; 
    
        qsort(p,3,sizeof(double),Vergleich); 
    
        for (int i = 0; i < 2; i++) 
            cout<<p[i].x<<","<<p[i].y<<","<<p[i].z<<"\n";  
        return 0; 
    }
    

  • Mod

    Nathan schrieb:

    OK, also wäre in diesem Fall ein reinterpret_cast<const PunktT> richtig?
    Warum verwendet camper dann static_cast?

    Weil man von void* auf andere Zeigertypen mittels eines static_casts kommt. Ein void* zeigt schließlich auf keinen Typen, sondern ist eine Art allgemeiner Zeiger. Da wird nichts uminterpretiert, sondern überhaupt erst interpretiert.



  • OK, danke.


Anmelden zum Antworten