Neue Klasse erzeugen mit Varaiblennamen die aus Datei gelesen werden



  • Hallo, ich möchte wissen, ob es möglich ist eine Klasse zu erstellen, die ihre Instanzvariablen aus einer Datei bezieht? Das hat folgenden Grund: Für Berechnungen in einem Programm habe ich eine Liste mit 100 double-Variablen, die evtl. noch den Namen ändern, oder die eine oder andere Variable dazu kommt. ich speichere diese Namen in eine Datei ab. Dann würde ich gerne eine Klasse erzeugen, wo ich dann die ganzen Variablennamen automatisch zustellen kann. Somit muß ich bei einer Änderung nichts mehr an der Klasse rumtippseln. Hat jeman eine Idee, oder ist das überhaupt möglich?

    Gruß
    Moehrle



  • Ja, das ist möglich.

    Definiere dazu ein File Format (z.B. pro Zeile ein Wert) und lies das File dann zur Laufzeit ein und speichere die Werte in einem Array oder Liste o.ä.

    Simon



  • Danke Simon für dir Ermutigung, das es jedenfalls möglich sein soll. Aber wie soll das genau funktionieren? Ich habe mein Codescchnipsel beigelegt, das funktioniert aber so nicht. ibts da irgendwo eine Vorlage zum abspickseln? Oder wäre es besser ein globales Array zu verwenden? Da steht man aber vor der selben Problematik in einer .h-Datei etwas zu bewegen.

    Gruß
    Moehrle

    // *********** Abten.h *****************
    
    #pragma once
     using namespace System::Windows::Forms;
    using namespace System::IO;
    ref class Abrichten
    {
    	//System::Windows::Forms::MessageBox::Show();
    	//StreamReader ^dat_ein = gcnew StreamReader;
    	System::IO::StreamReader ^ sr = gcnew System::IO::StreamReader(openFileDialog1->FileName);
    	String ^strTmp;
    	while(sr->Peek() != -1)
    	{
    		 strTmp = sr->ReadLine();
    		 double strTmp;
    	}
    	sr->Close();
    };
    


  • using namespace System;
    using namespace System::IO;
    using namespace System::Collections::Generic;
    
    ref class DoubleValues
    {
    public:
    	DoubleValues() : m_values(gcnew array<double>(0)) {}
    
    public:
    	void ReadFromFile(String^ filename)
    	{
    		List<double>^ list = gcnew List<double>();
    		StreamReader^ reader = nullptr;
    		try
    		{
    			reader = File::OpenText(filename);
    			String^ line = nullptr;
    			while((line = reader->ReadLine()) != nullptr)
    			{
    				double value = 0.0f;
    				if (double::TryParse(line, value))
    				{
    					list->Add(value);
    				}
    			}
    		}
    		finally
    		{
    			delete reader;
    		}
    		m_values = list->ToArray();
    	}
    
    	property array<double>^ Values
    	{
    		array<double>^ get()
    		{
    			return m_values;
    		}
    	}
    
    private:
    	array<double>^ m_values;
    };
    
    int main(array<System::String ^> ^args)
    {
    	DoubleValues d;
    	d.ReadFromFile("values.txt");
    	array<double>^ values = d.Values;
    
        return 0;
    }
    


  • Hallo Simon, werde heute abend oder morgen früh den Code-Schnipsel verarbeiten. Gibts noch kleine Komentare dazu?

    Gruß
    Moehrle



  • Gibts noch kleine Komentare dazu?

    Naja, frag doch einfach, falls was unklar ist.
    Die Klasse ist straight- forward...

    Simon



  • BTW: sollte das in C# nicht auch über Reflection realisierbar sein? Bitte nicht als Empfehlung verstehen, ich würde das NIE über Reflection machen, da man sich damit eine schöne "can of worms" aufmachen würde, aber gehen müsste es doch eigentlich, nicht?



  • Hallo Simon, danke für die Hilfe. Habe nun ein paar Kommentarzeilen in den Code eingefügt. BRingt ja nichts wenn man das Zeug nur anwendet, man muß es auch richtig verstanden haben. Habe ich die Sache so richtig interpretiert? Mit dem : Operator komme ich nicht ganz klar, und mit der Array-Erzeugung im Main(). Kannst Du dazu kurz was sagen? Habe in der Online-Hilfe nichts in dem Stil gefunden. Was mich mitlerweile erfreut: Mit C++ .Net kann man doch sehr schnell Erfolge erzielen. Ist zwar manchmal ein bißchen umständlich mit ^ und gcnew, aber ist alles Gewöhnungssache.

    Gruß

    Moehrle

    C/C++ Code: 
    using namespace System; 
    using namespace System::IO; 
    using namespace System::Collections::Generic; 
    
    ref class DoubleValues												// neue KLasse anlegen
    { 
    public: 
        DoubleValues() : m_values(gcnew array<double>(0)) {}			// Was bedeutet das?? Zuordnung von array-Werten an die KLasse
    
    public: 
        void ReadFromFile(String^ filename)								// Funktion für Datenfile einlesen
        { 
            List<double>^ list = gcnew List<double>();					// neue List erstellen
            StreamReader^ reader = nullptr;								// Streamreader-Instanz erzeugen
            try 
            { 
                reader = File::OpenText(filename);						// der Instanz den Dateinamen mit Pfad übergeben
                String^ line = nullptr;									// Instanz erst mal NULL setzen
                while((line = reader->ReadLine()) != nullptr)			// zeilenweises einlesen bis Dateiende
                { 
                    double value = 0.0f;						
                    if (double::TryParse(line, value))					// Wenn, double-Wert mit doppelter Geanuigkeit übergeben
                    { 
                        list->Add(value);								// zur List hinzufügen
                    } 
                } 
            } 
            finally 
            { 
                delete reader;											// Instanz aus Speicher löschen
            } 
            m_values = list->ToArray();									// ??? In das Array von m_values übertragen ??
        } 
    
        property array<double>^ Values									// property für die get-Funktion
        { 
            array<double>^ get()										// Wert aus Array ausgeben
            { 
                return m_values; 
            } 
        } 
    
    private:								
        array<double>^ m_values;										// Array privat stellen, aber Grundlage für "property-FUnktionen get() und set()
    }; 
    
    int main(array<System::String ^> ^args) 
    { 
        DoubleValues d;													// neues Objekt von DoubleValues erzeugen
        d.ReadFromFile("values.txt");									// Datei angeben, die eingelesen werden soll
        array<double>^ values = d.Values;								// das versteh ich nicht. muß aber wohl mit der Zeile 8 zusammenhängen
    
        return 0; 
    }
    


  • DoubleValues() : m_values(gcnew array<double>(0)) {} // Was bedeutet das?? Zuordnung von array-Werten an die KLasse

    Nach dem Doppelpunkt (nur bei den Konstruktoren) kann eine Initialisierungsliste angegeben werden. In diesem Fall initialisiere ich den Member m_values mit einem Array (von doubles) mit der Länge 0. Ist also einfach ein leeres Array.

    StreamReader^ reader = nullptr; // Streamreader-Instanz erzeugen

    Da wird keine Instanz erzeugt, sondern eine Managed Referenz angelegt. Das Objekt selbst wird mit File::OpenText(..) erzeugt.

    Was mich mitlerweile erfreut: Mit C++ .Net kann man doch sehr schnell Erfolge erzielen. Ist zwar manchmal ein bißchen umständlich mit ^ und gcnew, aber ist alles Gewöhnungssache.

    *g* Einige wissen was ich dazu denke. 🙂

    Simon



  • Was ist mit der Zeile 52 ?? Werden da die ganzen Einträge der Klasse in dem Array für den Programmgebauch zur Verfügung gestellt?

    array<double>^ values = d.Values;                                // das versteh ich nicht. muß aber wohl mit der Zeile 8 zusammenhängen
    


  • Hallo,

    ja, values verweist ab der Zuweisung immer auf d.Values, und gestattet somit Zugriff auf die Werte im Array m_values.

    MfG,



  • So, der COde funktioniert soweit. Ich arbeite in einer Form.h, in der ich einige Buttons habe, mit dem ich die Ein-Auslesegeschichte der Dateien steuere. Nun habe ich den unteren Teil in die Main() geschrieben. Dort wird dann auch der Filefpad übergeben. Wie kann ich nun aber prüfen, ob alle Variablennamen korekt aus dem File eingelesen wurden? Im Debugger sehe ich dazu nicht sehr viel. Außerdem, kann ich dann das Array ode die Klasse global nutzen, wenn ich z.B. bei einem Button in der Form.h den Klassenvariablen Werte zuweisen möchte? wie kannich das realisieren?
    Bin noch am probieren ...



  • Warum siehst Du im Debugger nicht das was Du sehen möchtest?
    Simon



  • So, habe mir ein Button in der Form.h eingefügt und das Ding simuliert. Zuerst ging auch nichts. Dann hab eich mit die Klasse DoubleValues angesehen. Da sehe ich doch, dass die ganzen Felder der Arrays als double sind. Ich wollte doch aber der Klasse erst mal Variablennamen zuordnen, also Strings. Nichts desto trotz, habe meine Datei die ich einlese abgeändert und double Zahlenwerte reingepackt, eingelesen und in RichTextBox eingegeben, funtioniert. Schon mal etwas ... Schnauf...Schnauf. Aber ich will eine Klasse mit String-Variablen, denen ich dann später Werte zuweise (DoubleValues->Länge = List[1]; ...)
    Und diese Zuweisung soll dann auch automatisch über eine Schleife stattfindne, damit meine Klasse automatisch mit den Rechenwerten gefüllt wird.
    Ich werde nun zuerst mal die Arrays auf String umstellen, und sehen ob ich dann meine Variablennamen drin habe.
    Später dann die Werte der Variablen in ein Array einlesen, und dann irgendwie an die Klasse übergeben. Ach noch was. Wie kann ich denn ein Variable ode ein Array global anlegen?



  • Ach noch was. Wie kann ich denn ein Variable ode ein Array global anlegen?

    Gar nicht. Das gehört sich nicht.

    Da sehe ich doch, dass die ganzen Felder der Arrays als double sind. Ich wollte doch aber der Klasse erst mal Variablennamen zuordnen

    Tja, die Namen sind jetzt halt Indizes geworden.
    Wenn Du eine Zuordnung Name zu Wert brauchst, dann nimm ein Dictionary<...>.

    Simon



  • Also, so ie es aussieht war wohl das ganze ein Verständnisproblem, oder? Es wird also nicht funktionieren, eine Klasse automatisch zu erstellen, so wie ich das vorhabe. Wie gesagt, meine Idee war halt, ein Klassenkonstrukt zu erzeugen, dann die Textvariablen von der textdatei einlesen und die Klasse hat somit ihre internen Klassenvariablennamen. Dann sollten eben die double-werte zugewiesen werden. Somit hätte ich halt immer einen einfachen Zugriff auf die Variablen. Aber ich muß ja die Variablen der Klasse abrufen und setzen können. Da stellt sich dann das Problem mit dem Get() und Set() Befehl. Ich müßte ja dann mit Zeiger arbeiten, falls das funktioniert. Evtl. nehme ich einfach ein Array und trage lese die Werte dann hinein. Das Problem ist halt, dieses Array steht dann nicht in der ganzen Form.h zur Verfügung. Gibts da noch bessere Ansätze? Ansonsten könnte ich die Klasse auch händisch anlegen, wird normal nicht allzuviel verändert werden, aber wie mache ich das dann mit dem Zugriff, mittels einer Funktion?



  • Ja, lege doch dei Klasse an, mit all ihren double variablen.
    Dann liest du eben das file ein und weist den variablen den wert zu.

    Klassen (bzw. Code) zu Laufzeit zu erzeugen ist schon möglich, jedoch denke ich nicht, dass diese Technik hier angebracht ist.

    Simon



  • Mach das doch in C#, oder nicht Simon?

    Gruß



  • Soll das in C# soviel einfacher sein? Gits dazu einen Link? Eigntlich sollte das Projekt schon in C++ sein, habe mich mehr oder weniger auch schon eingearbeitet.

    Gruß
    Moehrle



  • *g*


Anmelden zum Antworten