Fehlermeldung "... not declared in this scope" - tricky...



  • Hallo,

    ich studiere Physik und lese gerade ein Buch zur Einführung in C++ für Physiker. Habe mit folgendem Programm, dass die Bewegung eines Balls im Schwerefeld der Erde schrittweise errechnen und plotten soll (mit dislin) ein mittelschweres Kompilierproblem:

    #include <iostream>
    #include "dislin.h"
    
    const float grav = 9.81;
    
    class Ball{
    private:
    	float iPlace[2], iVelocity[2];
    	float elasticity; //Wert zwischen 0 und 1
    public:	
    	Ball(float x, float y, float vx, float vy, float elas)
    	{
    	iPlace[0]=x;
    	iPlace[1]=y;
    	iVelocity[0]=vx;
    	iVelocity[1]=vy;
    
    	if (elas>0 && elas<=1)	elasticity=elas;
    	else elasticity=0.5;
    	}
    
    	float returnx(){
    		return iPlace[0];}
    
    	float returny(){
    		return iPlace[1];}
    
    	void propagate(){
    		if(0 > (iPlace[0] + iVelocity[0]))
    		iPlace[0] = iPlace[0] + iVelocity[0];
    		else iPlace[0] = -(iPlace[0] + iVelocity[0])*elasticity;
    
    		iPlace[1] = iPlace[1] + iVelocity[1];
    									//x-Komponente bleibt unberührt
    		iVelocity[1] = iVelocity[1] - grav;
    	}
    };
    
    int main(){
    
    	cout<<"x, y, vx, vy und elas angeben!"<<endl;
    	float x,y,vx,vy, elas;
    	cin>> x >> y >> vx >> vx >> endl;
    
    	Ball benutzerball(x,y,vx,vy,elas);
    
    	float plotX[100], plotY[100];
    
    	int i=0;
    
    	for(i;i<100;++i){
    		plotX[i] = benutzerball.returnx();
    		plotY[i] = benutzerball.returny();
    
    		benutzerball.propagate();
    	}
    
    	metafl("BMP");
    
    	disini();
    	name("X-axis","plotX");
           	name("Y-axis","plotY");
    
    	qplsca(plotX,plotY, 100);
    	disfin();
    
    	return 0;
    }
    

    Kompilierversuch bringt folgendes:

    [sluser@slinux examples]$ clink -cpp Ball-Klasse
    Ball-Klasse.cpp: In function ‘int main()’:
    Ball-Klasse.cpp:42: error: ‘cout’ was not declared in this scope
    Ball-Klasse.cpp:42: error: ‘endl’ was not declared in this scope
    Ball-Klasse.cpp:44: error: ‘cin’ was not declared in this scope

    Also, okay, Google sagt dann, ich hätte using namespace std; vergessen... Wenn ich das dann aber in der dritten Zeile einfüge und es wieder versuche, kommt folgendes:

    In file included from /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/backward/iostream.h:31,
                     from Ball-Klasse.cpp:1:
    /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
    Ball-Klasse.cpp: In function ‘int main()’:
    Ball-Klasse.cpp:44: error: no match for ‘operator>>’ in ‘((std::basic_istream<char, std::char_traits<char> >*)((std::basic_istream<char, std::char_traits<char> 
    ... und so weiter
    

    hat jemand einen Rat? Daanke!



  • Da fehlt

    using namespace std;

    würde ich mal sagen 😃



  • Aus

    cin>> x >> y >> vx >> vx >> endl;
    

    muss

    cin>> x >> y >> vx >> vx;
    

    werden, da du sonst versuchst in endl etwas hineinzuschreiben 😉



  • Danke für die Antwort, die hat geholfen! In der gleichen Zeile war auch gleich der nächste Fehler versteckt, nämlich, dass vx zweimal eingegeben wurde, vy und elas aber uninitialisiert geblieben sind.

    Die Resultate des Programms sind jetzt für bestimmte Eingaben schon recht brauchbar, für die allermeisten jedoch ziemlicher Blödsinn... Wenn man nicht zu häufig auf Fehlersuche gehen muss, macht das sogar Spaß. 🙂



  • Die Fehlersuche ist auch viel einfacher, wenn man (für Laufzeitfehler) den Debugger benutzt. Informiere dich lieber zu früh als zu spät, was der Debugger ist und was du alles mit ihm machen kannst. Beispielsweise kannst du das Programm zur Laufzeit anhalten, schrittweise einzelne Zeilen ausführen, währenddessen Variableninhalte überprüfen und sogar ändern und noch mehr (google einfach mal). Sobald du also einen logischen Fehler hast, den du nicht auf Anhieb findest, sollte der Debugger das Werkzeug deiner Wahl sein. 🙂



  • undercovergenius schrieb:

    ... C++ für Physiker ...

    float iPlace[2]

    float returnx() { return iPlace[0]; }
    float returny() { return iPlace[1]; }

    Irgenwie habe ich das nach dem ersten Satz schon befürchtet.



  • undercovergenius schrieb:

    Die Resultate des Programms sind jetzt für bestimmte Eingaben schon recht brauchbar, für die allermeisten jedoch ziemlicher Blödsinn... Wenn man nicht zu häufig auf Fehlersuche gehen muss, macht das sogar Spaß. 🙂

    Muss es in der Methode 'propagate' nicht heißen:

    void propagate( float dt ){
            //x-Komponente bleibt unberührt
            iPlace[0] += iVelocity[0] * dt;
    
            //y-Komponente am Boden bei Y==0 reflektieren
            iPlace[1] += iVelocity[1] * dt;
            iVelocity[1] +=  -grav * dt;
            if(0 > iPlace[1]) // nächste Position ist <0
            {
                iPlace[1] = -iPlace[1];
                iVelocity[1] = -elasticity*iVelocity[1];
            }
        }
    

    😕

    .. und das dt sollte doch deutlich kleiner als 1s sein - oder?



  • Wenn du dir einen Stil angewöhnen würdest, hättest du noch mehr Spaß mit deinem Zeichen-Salat.

    Ich hab mir nicht die Mühe gemacht, das zu lesen.



  • 314159265358979 schrieb:

    Wenn du dir einen Stil angewöhnen würdest, hättest du noch mehr Spaß mit deinem Zeichen-Salat.

    Ich hab mir nicht die Mühe gemacht, das zu lesen.

    Wen interessiert, ob du es gelesen hast?



  • Also, dann interessiert mich das doch mal mit den Stilfragen. Wer's schon gelesen hat, kann ja bitte mal einen kurzen Kommentar dazu abgeben, an welcher Stelle ein richtiger Programmierer was warum anders gemacht hätte. Danke dafür!


  • Mod

    undercovergenius schrieb:

    Also, dann interessiert mich das doch mal mit den Stilfragen. Wer's schon gelesen hat, kann ja bitte mal einen kurzen Kommentar dazu abgeben, an welcher Stelle ein richtiger Programmierer was warum anders gemacht hätte. Danke dafür!

    Ich weiß nicht ob ich als "richtiger"Progammierer gelten darf, aber ich hätte vieles ganz anders gemacht.

    1. Technisches: Warum float und nicht double welches fast ohne Nachteile viel genauer rechnet?
    2. Technisches: Guck mal, was eine Initialisierungsliste ist.
    3. Design: Bei dir sind Orte und Geschwindigkeiten vom gleichen Datentyp, eine Elastizität ist vom gleichen Datentyp wie eine Ortskoordinate. Schreibe entsprechende Klassen und Operatoren die das Verhalten der Klassen untereinander regeln. Dann fällt dir auch auf, dass du wild Orte, Geschwindigkeiten und Beschleunigungen addierst, was physikalisch nicht sinnvoll ist.
    4. Design: Überall hat's magische Zahlen wie z.B die 100.
    5. Objektorientierung darfst du auch gerne auf den Plot anwenden. Dies wird auch schön, weil du dann die Koordinatenklasse von oben nutzen kannst und die Zusammenhänge klarer weerden.
    6. Design: Meiner Ansicht nach ist "zu Propagieren" keine Eigenschaft eines Balles. Sollte Propagieren nicht eine freie Funktion (oder eine Methode der Welt) sein, die auf Objekte mit Ort und Geschwindigkeit wirkt?

    Das sind erst einmal die wichtigsten Sachen die mir einfallen.



  • #include <iostream>
    #include <cassert>
    #include "dislin.h"
    
    const float GRAVITY = 9.81;
    
    class Ball
    {
    private:
        float fPosition[2], fVelocity[2];
        float fElasticity; //Wert zwischen 0 und 1
    
    public:
        Ball(float x, float y, float vx, float vy, float elas)
    		: fElasticity(elas)
        {
    		assert(elas >= 0 && elas <= 1);
    
    		fPosition[0] =  x;
    		fPosition[1] =  y;
    
    		fVelocity[0] = vx;
    		fVelocity[1] = vy;
    	}
    
    	float x() { return fPosition[0]; }
    	float y() { return fPosition[1]; }
    
    	void propagate()
    	{
    			if(fPosition[0] + fVelocity[0] < 0)
    				fPosition[0] += fVelocity[0];
    			else
    				fPosition[0] = fPosition[0] + fVelocity[0] * -fElasticity;
    
    			fPosition[1] += fVelocity[1];
    			fVelocity[1] -= GRAVITY;
        }
    };
    
    int main()
    {
    	std::cout << "x, y, vx, vy und elas angeben!" << std::endl;
        float x, y, vx, vy, elas;
        cin >> x >> y >> vx >> vx >> elas;
    
        Ball ball(x, y, vx, vy, elas);
    
        float plotX[100], plotY[100];
    
        for(int i = 0; i < 100; ++i)
    	{
            plotX[i] = ball.x();
            plotY[i] = ball.y();
            ball.propagate();
        }
    
        metafl("BMP");
        disini();
    
        name("X-axis", "plotX");
        name("Y-axis", "plotY");
    
        qplsca(plotX, plotY, 100); 
        disfin();
    }
    

    Nur mal stilmäßig umgeformt. Designmäßig gilt das, was im vorherigen Post gesagt wurde.



  • Wenn du schon dabei bist, entferne auch gleich die unnötigen f-Präfixe.

    Und was für einer ist eigentlich auf Namen wie metafl, qplsca und disini gekommen? 😮



  • Nennt sich ungarische Notation, dude.



  • Voll Alter! Aber qplsca ist klingonische Notation.



  • 2718281828459045235360287 schrieb:

    Voll Alter! Aber qplsca ist klingonische Notation.

    😃 👍



  • 314159265358979 schrieb:

    Nennt sich ungarische Notation, dude.

    Und ungarische Notation verwenden nur B00ns und Leute die in den 90ern hängen geblieben sind.
    Dude.


Anmelden zum Antworten