Klasse die aus einer Datei Daten einließt



  • Nexus vielen dank für deine Antwort,

    Ich habe das nun mal umgesetzt, was du mir erläutert hast.

    Kannst du nochmal kurz drüber schauen ob die Konstruktoren nun so stimmen?

    class testreihe
    {
    protected:
    	int n;
    	float* px;
    	float* py;
    
    public:
    	testreihe();
    	testreihe(char* dateiname);
    	testreihe(const testreihe& t);
    	~testreihe();
    	void berechne_r();
    	void ausgabe();
    
    };
    
    testreihe::testreihe():n(0),px(NULL),py(NULL){}
    testreihe::testreihe(char* dateiname):n(0),px(NULL),py(NULL)
    {
    	//Anzahl der Wertepaare bestimmen
    	ifstream input;
    	input.open(dateiname);
    	if(!input) cerr << "FAILURE: File not opened";
    	float temp;
    	while(input>>temp) n++;
    	input.close();
    
    	//Werte in px und py schreiben
    	ifstream input2;
    	input2.open(dateiname);
    	if(!input) cerr << "FAILURE: File not opened";
    	px=new float[n];
    	py=new float[n];
    	for(int i=0; i<n; i++)
    		{	
    			input2 >> px;
    			input2 >> py;
    		}
    	input2.close();
    }
    testreihe::testreihe(const testreihe& t)
    {
    	n=t.n;
    	px=new float[n];
    	py=new float[n];
    	for(int l=0; l<t.n; l++)
    		{
    			px[l]=t.px[l];
    			py[l]=t.py[l];
    		}
    }
    
    testreihe::~testreihe()
    {
    	delete[] px;
    	delete[] py;
    }
    

    Wenn dieser Teil dann korrekt ist dann wage ich mich an die Methoden berechne_r(); und ausgabe();

    Ps: Es gibt ein problem mit dem einlesen der Float Werte

    The architect schrieb:

    Fehler 1 error C2679: Binärer Operator '>>': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operanden vom Typ 'float *' akzeptiert (oder keine geeignete Konvertierung möglich) c:\users\archi\documents\visual studio 2008\projects\testreihe\testreihe\testreihe.cpp 44

    In der Aufgabenstellung ist aber keine >> operator Überladung verlangt, wie kann ich dieses Problem beheben?

    //edit: Bearbeitet, denn es fehlte ein >>



  • Nimm für einen C-String const char*.

    testreihe::testreihe(const testreihe& t)
    

    Auch hier brauchst du eine Initialisierungsliste.

    Dann würde ich ( persönliche Preferenz ) nicht NULL benutzen, sondern auch 0.

    Du willst ja keinen Zeiger auf float einlesen, sondern das float selbst.

    float* f = new float;
    input >> *f;
    delete f;
    


  • The architect schrieb:

    input2  px;
                input2 >> py;
    

    Also erstens mal fehlt bei der oberen Anweisung ein >>. Zweitens erwartet der >>-Operator hier ein float und keinen Zeiger auf float . Das ist auch der Grund für deinen Fehler. Du musst also auf das jeweilige Element zugreifen

    input2 >> px[i];
    input2 >> py[i];
    
    input2 >> px[i] >> py[i];  // in einer Zeile
    

    Zudem:

    The architect schrieb:

    testreihe::testreihe(const testreihe& t)
    {
    	n=t.n;            // das hier würde ich in die Initialisierungsliste verlagern
    }
    


  • The architect schrieb:

    Ich habe hier eine Aufgabe die ich gerne lösen würde, könnt ihr mir dazu etwas unter die Arme greifen?
    Aufgabenstellung:

    a)
    Definieren Sie die Klasse testreihe mit den Datenelementen
    -Anzahl n der Zahlenpaare
    -Zeiger auf die x-Werte px und Zeiger auf die y-Werte py

    und mit
    -dem Parameter-Konstruktor testreihe(char* dateiname), (in dem auch n zu bestimmen ist)
    -dem Kopier-Konstruktor,
    -dem Destruktor,
    -der Methode berechne_r und
    -der Methode ausgabe, die den Korrelationskoeffizienten r, die Anzahl n und die ersten 4 Wertepaare schreibt.

    b) Definieren Sie alle Methoden von a)

    darf ich mal fragen, wo diese Aufgabenstellung herkommt. Uni, FH, Berufsschule .. anderes?

    :xmas2: Werner



  • Die Aufgabe stammt aus einer Fachhochschule.
    Darf man fragen wieso dich dies interessiert?

    Zu der Aufgabe:

    Ich habe versucht nun eure beiden (drakon und Nexus) Vorschläge zu integrieren, aber es klappt noch nicht. ( nur bezogen auf das Einlesen)
    Ich komme auch leider nicht drauf, könnt ihr mir nochmal nen Anhaltspunkt geben?
    Bitte nicht das Ergebnis sagen, nur darauf hin leiten.

    Hier habe ich es nun so gemacht wie Drakon beschrieben hat:

    float* px = new float[n];
    	float* py = new float[n];
    	for(int i=0; i<n; i++)
    		input2 >> *px[i] >> *py[i];
    

    ich könnte dies evtl. auf andere Weise lösen indem ich den Zeiger um 1Stelle immer verschiebe. px++;
    Aber dies ist eher nicht so gut da ich am schluss den Zeiger dann wieder korrigieren müsste.



  • The architect schrieb:

    Die Aufgabe stammt aus einer Fachhochschule.
    Darf man fragen wieso dich dies interessiert?

    Ääh - ich arbeite gerade an einem Vortrag über guten und schlechten Stil bzw. Design und die richtige Wahl von Schnittstellen. Das Thema steht noch nicht so genau fest. Und diese Aufgabenbeschreibung deckt sich fast zu 100% mit meinem Negativ-Beispiel - also wie man es genau nicht machen soll. 🙄

    :xmas2: Werner



  • The architect schrieb:

    Zu der Aufgabe:

    Ich habe versucht nun eure beiden (drakon und Nexus) Vorschläge zu integrieren, aber es klappt noch nicht. ( nur bezogen auf das Einlesen)
    Ich komme auch leider nicht drauf, könnt ihr mir nochmal nen Anhaltspunkt geben?
    Bitte nicht das Ergebnis sagen, nur darauf hin leiten.

    Hier habe ich es nun so gemacht wie Drakon beschrieben hat:

    float* px = new float[n];
    	float* py = new float[n];
    	for(int i=0; i<n; i++)
    		input2 >> *px[i] >> *py[i];
    

    Überlege durch welche Operatoren [] bzw. * welcher Typ in was umgewandelt wird.
    Schau Dir nochmal genau das letzte Posting von Nexus an - da steht die Lösung.

    The architect schrieb:

    ich könnte dies evtl. auf andere Weise lösen indem ich den Zeiger um 1Stelle immer verschiebe. px++;
    Aber dies ist eher nicht so gut da ich am schluss den Zeiger dann wieder korrigieren müsste.

    Das kannst Du schon so machen, wenn Du vorher eine Kopie der Zeiger anlegst und die Kopie zum iterieren benutzt.

    Gruß
    Werner



  • Werner Salomon schrieb:

    ich arbeite gerade an einem Vortrag über guten und schlechten Stil bzw. Design und die richtige Wahl von Schnittstellen.

    Veröffentlichst du den Vortrag, wenn er fertig ist? Hört sich wirklich interessant!



  • Badestrand schrieb:

    Werner Salomon schrieb:

    ich arbeite gerade an einem Vortrag über guten und schlechten Stil bzw. Design und die richtige Wahl von Schnittstellen.

    Veröffentlichst du den Vortrag, wenn er fertig ist? Hört sich wirklich interessant!

    Normal nicht, da es sich um eine firmeninterne Veranstaltung handelt.

    Gruß
    Werner



  • Nexus schrieb:

    Zweitens erwartet der >>-Operator hier ein float und keinen Zeiger auf float.

    Werner Salomon schrieb:

    Überlege durch welche Operatoren [] bzw. * welcher Typ in was umgewandelt wird.
    Schau Dir nochmal genau das letzte Posting von Nexus an - da steht die Lösung.

    Also damit der operator>> damit arbeiten kann muss ich ihm einen float und nicht einen *float übergeben.
    Momentan bekommt er durch px[i] einen Zeiger.
    px ist mein Zeiger auf den Arrayanfang, mit *px komme ich auf den Bereich auf den der Zeiger zeigt. ( Dereferenzieren).

    Ich kann leider nicht genau beurteilen ob meine jetztige Lösung stimmt, da ein Laufzeitfehler auftritt beim debuggen.

    Fehler schrieb:

    Unbehandelte Ausnahme bei 0x68ef31ea (msvcr90d.dll) in testreihe.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xccccccc0.

    float* px = new float[n];
    float* py = new float[n];
        for(int i=0; i<n; i++)
            input2 >> *(px+i) >> *(py+i);
    


  • Ne. Du hast keinen Zeiger. Du hast ein Array von floats und mit dem []-Operator kommst du auf die richtigen Werte..

    float a[5];
    std::cout << a [ 0 ];
    std::cin >> a [ 1 ];
    

    War ein wenig ungeschickt von mir das Beispiel mit Zeigern zu machen. Das war vlt. die Verwirrung. (auch wenn es schlussendlich das gleiche ist. ;))



  • Deine Lösung stimmt.

    Jedoch ist

    *(px+i)
    

    genau äquivalent zu

    px[i]
    

    Mit dem Index-Operator [] wird also auch dereferenziert.



  • Okay dann ist also die Definition des char* Parameterkonstruktors auch richtig

    testreihe::testreihe():n(0),px(0),py(0){}
    testreihe::testreihe(char* dateiname):n(0),px(0),py(0)
    {
    	//Anzahl der Wertepaare bestimmen
    	ifstream input;
    	input.open(dateiname);
    	if(!input) cerr << "FAILURE: File not opened";
    	float temp;
    	while(input>>temp) n++;
    	input.close();
    
    	//Werte in px und py schreiben
    	ifstream input2;
    	input2.open(dateiname);
    	if(!input2) cerr << "FAILURE: File not opened";
    	float* px = new float[n];
    	float* py = new float[n];
        for(int i=0; i<n; i++)
            input2 >> px[i] >> py[i];	
    
    	input2.close();
    }
    

    Beim Kopierkonstruktor taucht noch ein Fehler auf.

    testreihe::testreihe(const testreihe& t):n(t.n)
    {
    	float* px = new float[n];
    	float* py = new float[n];
    
    	for(int i=0; i<n; i++)
    	{
    		px[i]=t.px[i];
    		py[i]=t.py[i];
    	}
    }
    

    Fehler schrieb:

    Unbehandelte Ausnahme bei 0x00c41a52 in testreihe.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.

    Jemand eine Ahnung was ich hier wieder falsch mache?



  • Ich würde mal sagen, dass t.px[] ungültig, weil leer ist.
    Schau dir das mal mit dem Debugger an, dann siehst dus.



  • The architect schrieb:

    Jemand eine Ahnung was ich hier wieder falsch mache?

    Im Kopierkonstruktor erstmal nichts, Du solltest noch abfragen, ob t.n==0 ist. Falls ja kann man das Codesegment überspringen. Außerdem solltest Du die Zeiger immer in der Initialisierungsliste mit 0 initialisieren.
    Der Fehler kann z.B. dann auftreten, wenn n>0 ist, aber die Zeiger px,py noch 0 sind.

    Im Konstruktor zählt n die Anzahl der Zahlen, aber Du brauchst die Anzahl der Paare! Aber das löst den von Dir genannten Fehler nicht aus.

    :xmas2: Werner



  • The architect schrieb:

    Die Datei TESTREIHE.TXT sieht so aus:

    38,5 148,08
    33,6 103,51
    41,2 143,76
    46,4 171,27
    ...
    35,9 128,56
    37,9 142,79
    37,7 141,54

    Wenn die Zahlen mit Komma als Dezimaltrenner versehen sind, so muss man die entsprechende locale setzen. Im MS-Umfeld (z.B. VC8) sieht das etwa so aus:

    ifstream datei("TESTREIHE.TXT");
        datei.imbue( locale("german") ); // in der Folge werden Zahlen mit Komma als Dezimaltrennzeichen gelesen
    

    Gruß
    Werner



  • Danke Werner, das mit dem Einlesen klappt jetzt wunderbar.
    er ließt nun alle Werte ein, diese Anzahl nehme ich dann einfach durch 2

    ( mein File hat z.b 8 Werte)

    Der Fehler von dem ich gesprochen habe, besteht aber noch immer.

    Das was du vorhin geschrieben hast habe ich nun so umgesetzt:

    testreihe::testreihe(const testreihe& t):n(t.n),px(0),py(0)
    {
    	if(t.n!=0)
    		{
    			float* px = new float[n];
    			float* py = new float[n];
    			for(int i=0; i<n/2; i++)
    			{
    				px[i]=t.px[i];
    				py[i]=t.py[i]; 
    			}
    		}
    }
    

    Falls also n=0 ist wird das Codesegement übersprungen.



  • -Anzahl n der Zahlenpaare

    testreihe::testreihe(const testreihe& rhs)
       : n(t.n), px(0), py(0)
    {
        if(! n)//n == 0
             return;
    
        float* px = new float[n];
        float* py = new float[n];
        for(int i=0; i != n; ++i)
        {
             px[i]=rhs.px[i];
             py[i]=rhs.py[i]; 
        }
    }
    

    so kann man das doch schon mal lesen... dann gibts noch ne schöne stl-funktion:

    testreihe::testreihe(const testreihe& rhs)
       : n(t.n), px(0), py(0)
    {
        if(! n)//n == 0
             return;
    
        float* px = new float[n];
        float* py = new float[n];
        std::copy(px, px+n, rhs.px); //von rhs.px n werte nach px kopieren
        std::copy(py, py+n, rhs.py); //von rhs.py n werte nach py kopieren
    }
    

    Als kleine Anmerkung: Für Pointer würde ich im Übrigen nicht 0 nehmen - ich würd nullptr nehmen und das zunächst als NULL definen oder gleich den workaround bis zum nächsten standard nehmen, aber das sei nur mal so nebenebbei erwähnt

    testreihe::testreihe(const char* dateiname) //const zeigt dem aufrufenden an, dass seine zeichenkette nach dem funktionsaufruf die gleiche ist, wie zuvor
       n(0), px(0), py(0)
    {
        //Anzahl der Wertepaare bestimmen
        std::ifstream input;
        input.exceptions (std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); //es werden exceptions geworfen, falls etwas schief geht - die fangen wir aber zunächst mit dem try / catch selbst auf und werfen ne andere exception weiter:
        try
        {
          input.open(dateiname);
          float temp;
          for(float temp; !input.eof(); ++n)
              input >> temp;
          input.seekg(std::ios_base::beg); //wir nehmen den gleichen stream wieder - brauchen ja keinen anderen...
    
          if(!n)
             return; //evtl fehlermeldung?
    
          //Werte in px und py schreiben
          float* px = new float[n];
          float* py = new float[n];
          for(int i=0; i != n; ++i)
              input >> px[i] >> py[i];
       }
       catch (...)//evtl TODO ^^
       {
         //TODO
       }
    }
    

    Sehr nützliche Referenz (vor allem zu Streams nutze ich sie auch sehr gerne ^^):
    http://www.cplusplus.com/reference/

    ich würd ja gern weitermachen aber ich geh dann erstmal frühstücken 😉

    bb



  • unskilled schrieb:

    so kann man das doch schon mal lesen... dann gibts noch ne schöne stl-funktion:

    std::copy(px, px+n, rhs.px); //von rhs.px n werte nach px kopieren
        std::copy(py, py+n, rhs.py); //von rhs.py n werte nach py kopieren
    

    Die "schöne STL-Funktion" wurde hier aber falsch angewandt. 😉

    Richtig wäre Folgendes, du willst schliesslich von rhs nach *this kopieren:

    std::copy(rhs.px, rhs.px + n, px);
    


  • vielen dank an alle die mir bei dieser Aufgabe geholfen haben.
    Ich habe das Programm nun fertig

    gruß architect


Anmelden zum Antworten