dynamische arrays, vector, list... Länge unbekannt.



  • Hallo zusammen!
    Da ich neu hier im Forum bin möchte ich micht erstmal kurz vorstellen: Mein Name ist Martin, ich bin 24 Jahre alt und studiere Physik. Und wie es sich für einen angehenden Physiker gehört stehe ich mit Programmiersprachen ein wenig auf Kriegsfuß. 😃
    Naja, vielleicht ändert sich das ja noch... 🙂

    Es geht um die numerische Lösung einer Differentialgleichung, genauer gesagt um das Speichern der einzelnen Lösungsschritte in einem Container noch unbekannter Länge.

    Ich glaube ein Beispiel verdeutlicht mein Problem am besten.
    Ein einfaches Beispiel wäre etwa ein mit Luftwiderstand fallender Körper:

    ...
    //Variablen/Konstanten definieren
    const double G=9.81;
    const double K=0.5;
    double v0=0;             //Anfangsgeschwindigkeit
    double vEnd;             //Abbruchkriterium
    double v;                //Geschwindigkeit
    double dv;               //Änderung von v pro Iteration
    double t=0.01;           //Schrittweite
    
    //Benutzer gibt Abbruchkriterium ein
    cout<<"Eingabe Endgeschwindigkeit: "; cin>>vEnd; //z.B. vEnd=-100
    
    //Euler-Verfahren zur schrittweisen Lösung
    for(int i=0; v0>vEnd; i++)
        {
            dv=(-G+K*v0*v0)*t;
            v=v0+dv;
            //---->                //hier soll v (Index i) in jeder
                                   //Iteration in einem Container V
                                   //an der Position i gesichert werden
    
            v0=v;                  //Anfangswert wird für die nächste Iteration
                                   //mit dem neuen Wert überschrieben
        }
    //nach Abbruch der Iteration soll hier ein Container mit i Elementen
    //vorhanden sein welcher die schrittweise berechneten Werte von v enthält.
    ...
    

    Da die Anzahl der Iterationen vom eingegebenen Abbruchkriterium vEnd abhängt weiß ich erst nach einem kompletten Durchlauf der Schleife wie viele Schritte zur Lösung nötig waren.
    Nun könnte ich die Schleife einmal laufen lassen um die Anzahl der Iterationen zu bestimmen, nämlich i, dann das Array V mit dieser Länge erstellen und die Schleife ein zweites mal laufen lassen um das Array mit den Werten von v zu füllen.
    Das wäre aber eine sehr unschöne Lösung...

    Der Container V soll nach der Berechnung zur graphischen Darstellung ausgelesen werden.

    Nun habe ich mich ein wenig eingelesen und finde recht viele Alternativen zu einem Array, z.B. vector, list , queue, deque...
    Je nach gewählter Schrittweite müsste der Container schon recht groß werden...
    Welcher Container bietet sich hier an und wie könnte ich das am Besten implementieren?

    Ich habe bei stackoverflow ein Diagramm zur Auswahl gefunden, werd aber nicht so ganz schlau draus...
    Auswahlkriterien STL Container

    LG Martin


  • Mod

    vector (im Zweifelsfall immer eine gute Wahl) und einfach bei jeder Iteration das Ergebnis mit push_back anhängen.



  • OK, mit vector...

    #include<vector>
    ...
    //Variablen/Konstanten definieren
    const double G=9.81;
    const double K=0.5;
    double v0=0;             //Anfangsgeschwindigkeit
    double vEnd;             //Abbruchkriterium
    double v;                //Geschwindigkeit
    double dv;               //Änderung von v pro Iteration
    double t=0.01;           //Schrittweite
    
    //Benutzer gibt Abbruchkriterium ein
    cout<<"Eingabe Endgeschwindigkeit: "; cin>>vEnd; //z.B. vEnd=-100
    
    //Euler-Verfahren zur schrittweisen Lösung
    
    std::vector<double> V;         //Vector V erstellen
    
    for(int i=0; v0>vEnd; i++)
        {
            dv=(-G+K*v0*v0)*t;
            v=v0+dv;
    
            V.push_back(v);        //neuen Wert von v hinten an V anhängen
    
            v0=v;                  //Anfangswert wird für die nächste Iteration
                                   //mit dem neuen Wert überschrieben
        }
    

    Kann ich den Vektor V so initialisieren? Zu Beginn müsste er ja die Länge 0 haben damit der erste Wert von v auch an die erste Stelle kommt...

    Kann ein bestimmter Eintrag im Vektor V dann so ausgelesen werden?

    double Val;
    Val=V[3];         //vierten Eintrag auslesen und an Val übergeben
    

  • Mod

    Die Benutzung von vector sieht beim Drüberschauen richtig aus. Funktioniert's?



  • Noch nicht.
    Sobald ich den Vektor wie oben geschrieben testweise an einer Stelle auslese und den Wert ausgeben möchte wird das Programm mit der Meldung "meinProgramm.exe hat ein Problem festgestellt und muss beendet werden" beendet. Der Compiler meldet vorher kein Problem.

    Das Problem liegt wohl hier:

    double val;
    val=V[3];        //hier gehts wohl schief
    cout<<"Wert an Stelle 4 ist "<<val;
    

    Test mit:

    double val=50;
    //val=V[3];
    cout<<"Wert an Stelle 4 ist "<<val;
    

    verursacht kein Problem mehr. 😕


  • Mod

    Dann hat dein Testvector wohl weniger als 4 Elemente. Was ist denn V.size() an der Stelle?

    Deine Schleife sieht auch ein bisschen komisch aus. Sicher dass die überhaupt tut was sie soll?



  • Hmmm, mal schauen... wenns das Problem dort liegt find ichs....



  • Ja, lag an der Schleife. So klappts.

    #include<vector>
    ...
    //Variablen/Konstanten definieren
    const double G=9.81;
    const double K=0.5;
    double v0=0;             //Anfangsgeschwindigkeit
    double vEnd;             //Abbruchkriterium
    double v;                //Geschwindigkeit
    double dv;               //Änderung von v pro Iteration
    double t=0.01;           //Schrittweite
    
    //Benutzer gibt Abbruchkriterium ein
    std::cout<<"Eingabe Endgeschwindigkeit: "; std::cin>>vEnd; //z.B. vEnd=-100
    
    //Euler-Verfahren zur schrittweisen Lösung
    
    std::vector<double> V;         //Vector V erstellen
    V.push_back(v0);
    
    while(v0>vEnd)
        {
            dv=(-G+K*v0*v0)*t;
            v=v0+dv;
    
            V.push_back(v);        //neuen Wert von v hinten an V anhängen
    
            v0=v;                  //Anfangswert wird für die nächste Iteration
                                   //mit dem neuen Wert überschrieben
        }
    //Auslesen test
    double val;
    val=V[4];
    std::cout<<"Wert an Stelle 4 ist "<<val;
    

    Vielen Dank für die Hilfe!


Anmelden zum Antworten