Zum Inhalt springen

Dynamisches Feld


cadman

Empfohlene Beiträge

Hallo,

habe folgendes Problem:

Ich habe eine Gerade und eine Polylinie (mehrgliedrige Linie) an eine Funktion zu übergeben. Die Funktion soll mir die Schnittpunkte in einem 2-dimensionalem array zurückgeben.

Da ich zu Anfang nicht weiß, ob und wieviele Schnittpunkte es gibt muss das Rückgabearray irgendwie dynamisch arbeiten.

Ich habe mir schon malloc angesehen. Aber die Beispiele bestanden nur aus 1-dimensionalen arrays.

wat nu ?

Link zu diesem Kommentar
Auf anderen Seiten teilen

... struktur ? du meinst so eine art klasse mit einer methode für x, eine für y und eine für den fehlercode, wenn kein schnittpunkt vorhanden ?
Nein, eine einfache Struktur, die einen Schnittpunkt darstellt:

struct Punkt
{
double x;
double y;
};[/code] Unter der Annahme, dass dein Koordinatentyp double ist. Und davon gibt deine Funktion einen vector zurück:
[code]std::vector<Punkt> deinefunktion(params)
Einen eigenen Fehlercode für "keinen Schnittpunkt" brauchst du nicht. In dem Fall kannst du ja einfach einen leeren Vector zurückgeben. In der Funktion legst du einen Vector an, und immer, wenn du einen Schnittpunkt gefunden hast, hängst du den hinten an den Vector an:
std::vector<Punkt> deinefunktion(params)
{
std::vector<Punkt> ergebnis;

// ... Schnittpunkt suchen ...

Punkt p;
p.x = bla;
p.y = blubb;
ergebnis.push_back(p); // Punkt p an Vector ergebnis anhängen

// ... weitersuchen ...

return ergebnis;
}[/code]

Link zu diesem Kommentar
Auf anderen Seiten teilen

habe folgende funktion, aber das mit dem realloc funktioniert nicht:

// Schnittpunkt einer Geraden mit einer Polylinie berechnen

//  epx1, epy1,zpx1, zpy1    -> Koordinaten der 1. Geraden

//  f                        -> =1 Gerade unendlich lang

//  double poly [][2]        -> Koordinatenfeld der Polylinie (1. Punkt = letzter Punkt)

//    int orianzep            -> Anzahl der Eckpunkte

//  f1                        -> wenn f1=1 wird die 1. Gerade unendlich verlängert

//  f2                        -> wenn f2=1 wird die 2. Gerade unendlich verlängert

//    rueckgabe                -> punktfeld mit schnittpunkten: double (*rueckgabe) [2] = new double [anzeckp][2];

//    fehler                    -> =-1 keine Schnittp4n2te gefunden

void fc_calc_sp_g1_poly (double epx1, double epy1,double zpx1, double zpy1, int f,

                         double poly [][2], int orianzep,

                         double rueckgabe[][2], int fehler)

{

    //fehlerpuffer

    fehler=-1;

    //Zähler zum Durchlauf der Polylinie

    int z;

    //Zwischenpuffer für Schnittpunkt

    double r1[3];

    //Zähler für Schnittpunkte

    int spz=0;

    //Rückgabepuffer "rueckgabe" wird erst beim 1 Fund initialisiert

    double **matrix;

    //

    int i;



    //Alle Punkte der Polylinie durchlaufen        

    for (z=0;z<(orianzep-1);z+=1)

    {

        //funktion sucht schnittpunkt

        fc_calc_sp_g1_g2 (epx1,epy1,zpx1,zpy1,

                          poly [z][0],poly [z][1],poly [z+1][0],poly [z+1][1],

                          f,0,r1);

        //wenn schnittpunkt gefunden

        if (r1[2]==1)

        {

            fehler=1;

            //wenn noch kein schnittpunkt gefunden

            if (spz==0)

            {

                cout << "\nmalloc !";

                //Zeile

                matrix = (double **) malloc (1*sizeof(double *));

                //Spalte

                matrix[0] = (double *)  malloc (2*sizeof(double));

            }

            //für weitere schnittpunkte

            if (spz>0)

            {

                cout << "\nrealloc !";

                //Zeile

                matrix = (double **) realloc (matrix, (spz+1)*sizeof(double *));

                //Spalte

                matrix[spz] = (double *) realloc (matrix, 2*sizeof(double));

            }



            cout << "\nSchnittpunkt gefunden !";

            cout << "\nspz: " << spz;

            cout << "\n" << z << "\t" << r1[0] << "\t" << r1[1];

            matrix[spz][0]=r1[0];

            matrix[spz][1]=r1[1];

            spz++;


        }

    }

    cout << "\nspeicher freigeben !";

    if (spz>0)

    {

        for (i=0;i<spz;i++) {free (matrix[i]);}

        free (matrix);

    }


}

Link zu diesem Kommentar
Auf anderen Seiten teilen

das mit dem realloc funktioniert nicht:
"Funktioniert nicht" ist keine ausreichende Fehlerbeschreibung ;)

Für matrix[spz] darfst du natürlich nicht realloc benutzen. Das ist ja ein ganz neuer, uninitialisierter Zeiger, der nie mit malloc belegt wurde.

Aber warum plagst du dich in C++ mit malloc & Co. ab? Hast du Einfluss auf die Signatur dieser Funktionen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ob ich EInfluss auf die Signatur der Funktion habe ? Was meinst Du damit ?

Kannst du die Parametertypen von fc_calc_sp_g1_poly und fc_calc_sp_g1_g2 ändern, oder ist das vorgegeben?

Dein Code sieht nämlich bis auf cin/cout wie C aus. In C++ würde man das anders lösen. Dazu müsste man aber die Parametertypen ein wenig ändern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Code zeigt, wie man dieses Problem in C lösen würde (wenn man mal von cin/cout absieht). In C++ kann man das zwar genauso machen, man tut es aber normalerweise nicht. C++ biete viele Möglichkeiten, wie man sich hier das Leben vereinfachen kann. Man muss dazu auch nicht sofort alles auf Objektorientierung umstellen.

So könnte das aussehen:

// Struktur für einen 2D-Punkt
struct punkt
{
double x;
double y;
};

vector<punkt> fc_calc_sp_g1_poly (punkt ep, punkt zp, int f,
vector<punkt> const& poly)
{
vector<punkt> rueckgabe;

//Alle Punkte der Polylinie durchlaufen
for (size_t z=0; z<poly.size()-1; ++z)
{
punkt r;
//funktion sucht schnittpunkt
if( fc_calc_sp_g1_g2 (ep, zp, poly[z], poly[z+1], f, 0, r) )
{
rueckgabe.push_back(r);

cout << "\nSchnittpunkt gefunden !";
cout << "\nspz: " << matrix.size();
cout << "\n" << z << '\t' << r.x << '\t' << r.y;
}
}
return rueckgabe;
}[/code]

Der Code ist damit übersichtlicher und gleichzeitig ausnahmesicher. Er enthält kein lästiges Speichermanagement mehr, darum kümmert sich die Vector-Klasse. fc_calc_sp_g1_g2 müsste natürlich ähnlich angepasst werden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

habe jetzt eine funktion auf die vector geschichte umgestellt. rueckgabe ist eine punkt struktur

wie stelle ich es denn an, dass die aufrufende funktion merkt, dass kein punkt gefunden wurde ?

fc_point fc_calc_sp_g1_g2 (fc_point ep1, fc_point zp1,

                           fc_point ep2, fc_point zp2,

                           int f1, int f2)

{

    fc_point rueckgabe;

    int fehler=1;

    fc_point schnittp;

    // Felder für transformierte Endpunkte

    double tep1[2],tzp1[2],tep2[2],tzp2[2];

    // Daten der 1. Geraden im Originalzustand

    double l1=pow(pow((ep1.x-zp1.x),2) + pow((ep1.y-zp1.y),2),0.5);

    double alpha1=acos((zp1.x-ep1.x)/l1);

    // Die Koordinatensystem wird so gedreht, dass der Anfangspunkt der 1. Geraden 

    // horizontal durch den Ursprung verläuft

    fc_calc_coortrans_point(ep1.x,ep1.y,ep1.x,ep1.y,alpha1,tep1);

    fc_calc_coortrans_point(zp1.x,zp1.y,ep1.x,ep1.y,alpha1,tzp1);

    fc_calc_coortrans_point(ep2.x,ep2.y,ep1.x,ep1.y,alpha1,tep2);

    fc_calc_coortrans_point(zp2.x,zp2.y,ep1.x,ep1.y,alpha1,tzp2);

    // Ist auch die 2. Gerade horizontal ? Dann Fehler = -1 setzen

    if (tep2[1]==tzp2[1])

    {

        //cout << "\nDie Linien sind parallel !";

        fehler = -1;

        if (tep1[1]==tep2[1])

        {

            //cout << "\nDie Linien liegen übereinander !";

        }

    }


    if (fehler==1)

    {

        // Zweite Gerade senkrecht ?

        if (tep2[0]==tzp2[0])

        {

            schnittp.x=tep2[0];

            schnittp.y=0.0;

        }

        else

        {

            schnittp.x=tep2[0]+(tzp2[0]-tep2[0])*(-tep2[1])/(tzp2[1]-tep2[1]);

            schnittp.y=0.0;

        }


        // Bei entsprechender Einstellung (f1,f2) muss der Schnittpunkt auf denn Geraden liegen


        // Bedingung f1 prüfen

        if (f1!=1) { if (schnittp.x<0.0 || schnittp.x>tzp1[0]) { fehler=-1; }}


        // Bedingung f2 prüfen, wenn kein Fehler

        if (fehler==1)

        {

            if (f2!=1)

            {

                if ((schnittp.y-tep2[1])/(tzp2[1]-tep2[1])<0.0 ||

                    (schnittp.y-tep2[1])/(tzp2[1]-tep2[1])>1.0)

                    {fehler=-1;}

            }

        }

        // Rücktransformation

        double tmp[2],bcs[2];

        fc_calc_coortrans_point(0.0,0.0,ep1.x,ep1.y,alpha1,bcs);

        fc_calc_coortrans_point(schnittp.x,schnittp.y,bcs[0],bcs[1],-alpha1,tmp);

        rueckgabe.x=tmp[0];

        rueckgabe.y=tmp[1];

    }

    return rueckgabe;

}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ohne jetzt detailliert den Code gelesen zu haben ...

wie stelle ich es denn an, dass die aufrufende funktion merkt, dass kein punkt gefunden wurde ?

vector<punkt> rueckgabe;
return rueckgabe;
[/PHP]

Der Vector enthält schlimmstenfalls eben 0 Elemente.

vector::size

Returns the number of elements in the vector container.

Wenn Dich die Größe interessiert.

[PHP]for ( it=myvector.begin() ; it < myvector.end(); it++)

Und so iterierst Du über alle Elemente. Wenn Du dann 0 Elemente hast, ist die For-Schleife eben schnell beendet ;)

vector - C++ Reference

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich Klotzis Beipsiel nehme:

vector<punkt> fc_calc_sp_g1_poly (punkt ep, punkt zp, int f,
vector<punkt> const& poly)[/PHP]

So ist bei dem Beispiel

[PHP]vector<punkt>

der Rückgabetyp.

Ohne jetzt im Einzelnen zu wissen, was die Funktion macht:

if( fc_calc_sp_g1_g2 (ep, zp, poly[z], poly[z+1], f, 0, r) )

sollte die Abfrage sicherstellen, ob ein Schnittpunkt existiert oder nicht

und

rueckgabe.push_back(r);

sorgt dafür, dass "r" -welches den zurückgegebenen Punkt enthält- an's Ende des Vectors angefügt wird.

In jedem Falle wird nach durchlaufen der for-Schleife der Vector zurückgegeben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

das ist der datentyp von rueckgabe:

structure fc_point

{

double x;

double y;

}

ist KEIN vector

Das kannst du nicht als Rückgabetyp benutzen, weil eben auch die Möglichkeit besteht, dass es keinen Schnittpunkt gibt. Du könntest einen std::auto_ptr<fc_point> zurückgeben, der kann gegebenenfalls auch einen Nullzeiger kapseln.

Alternativ kannst du das Ergebnis über einen Referenzparameter zurückgeben und über den Rückgabewert, beispielsweise true oder false, anzeigen, ob es einen Schnittpunkt gibt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...