Gezielte Werte aus Datei auslesen



  • dixidix schrieb:

    Ja, der Code ist für C++.

    Der Code ist gar nicht C++ 😃



  • 😕 HÄ???? Hab ihn doch aber als getSetting.cpp so kompilert und auch das fertige Programm mit g++ getSetting.cpp -o getSet erstellt. Mit gcc geht das nicht. Sorry, bin nur Gelegenheitsprogger. Das muß mir mal jemand genauer erklären warum dieser Code nicht C++ ist?



  • Zeugs wie stdio.h, fopen, usw. sind Überbleibsel aus C, die zwar in C++ noch verfügbar sind, die man aber nicht mehr verwenden sollte (stattdessen benutzt man fstream).

    atoi muß auch nicht unbedingt sein. Dafür könnte man Klassen aus <sstream> verwenden.

    char[] ist unter C++ im Allgemeinen kein geeigneter Datentyp um Strings zu verarbeiten. Dafür benutzt man std::string.

    Und das hier:

    #define BIGBUFFERSIZE 2000
    

    geht schon mal gar nicht. In C++ würde man das als:

    const int BIGBUFFERSIZE = 2000;
    

    schreiben (mal abgesehen davon, daß man Buffer-Size Angaben meist überhaupt nicht mehr braucht, wenn man mit C++ Mitteln arbeitet).



  • Und in C++ würde das ungefähr auch so aussehen:

    #include <string>
    #include <iostream>
    #include <map>
    #include <sstream>
    #include <iterator>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    
    struct myValue {
    	string str;
    	int val;
    };
    
    istream& operator>>(istream& stream, myValue& mV)
    {
    	string str;
    	getline(stream,str);
    
    	if(!stream.eof())
    	{
    		mV.str = str.substr(0,str.find('='));
    
    		istringstream iss(str.substr(mV.str.size()+1,str.size() - mV.str.size()));
    		iss >> mV.val;
    	}
    
    	return stream;
    }
    
    class Helper {
    
    	private:
    			static map<string,int> mV_map;
    
    	public:
    
    			Helper()  {};
    			~Helper() {};
    
    			Helper& operator*()  { return *this; }
        		Helper& operator++() { return *this; }
    			//Helper& operator()() { return *this; }
    
    			Helper& operator=(const myValue& mV) 
    			{
    				mV_map.insert(make_pair(mV.str,mV.val));
    
    				return *this;
    			}
    
    		 	void show_map()
    			{
    				map<string,int>::const_iterator const_it = mV_map.begin();
    
    				while(const_it != mV_map.end())
    				{
    					cout << const_it->first << " = " << const_it->second << endl;
    					++const_it;
    				}
    
    				cout << endl;
    			}
    
    			int getValueof(const string& s)
    			{
    				map<string,int>::const_iterator const_it = mV_map.find(s);
    
    				if(const_it!=mV_map.end()) return const_it->second;
    
    				return -1;
    			}
    
    };
    
    map<string,int> Helper::mV_map;
    
    int main()
    {
    
     	ifstream file("fu.txt");
    	Helper helper;
    
    	copy(istream_iterator<myValue>(file),istream_iterator<myValue>(),helper);
    	file.close();
    
    	helper.show_map();
    
    	cout << helper.getValueof("u") << endl;
    	cout << helper.getValueof("b") << endl;
    
    	return 0;
    
    }
    

    Jetzt wäre ich dem jenigen sehr verbunden, wenn er mir sagen könnte wie ich auch ohne dem static auskommen könnte 😉



  • Buuh 😮 ... Das is' ja 'n Haufen Holz. So viel!!!? Respekt für die Mühe. Na gut. In VB kenne ich mich da besser aus. Da hätten 20 Zeilen gereicht.
    Der g++ Compiler (Linux) meckert aber in der Zeile:

    copy(istream_iterator<myValue>(file),istream_iterator<myValue>(),helper);
    

    Kann das damit zu tun haben, dass ich das unter Linux mit dem g++ kompiliere?



  • dixidix schrieb:

    Kann das damit zu tun haben, dass ich das unter Linux mit dem g++ kompiliere?

    Nein 🙂 Habe es auch unter Linux mit dem g++ kompiliert. Welche Version hast du ?
    Wie gesagt der Code ist eh nicht sauber da ich nicht genau weiß wie ich helper am besten Copy übergebe und somit das static vermeiden könnte.

    Mal sehen, es meldet sich eh gleich ein Stl Guru 😃



  • Ich nutze LinuxSuse10 mit dem g++ 4.0.2.
    Na gut, wird sich schon lösen lassen.

    Aber nochmal zur Sache ansich. Ich kenne mich da besser mit VB aus. Da hätte ich das mit einigen wenigen Zeile gelöst, aber möchte das auch mit C++ lösen können.

    Sehe ich das richtig, dass alles Zeilenweise eingelesen wird?
    Ginge es nicht auch so etwas schlanker:
    - dass man den kompletten Dateiinhalt als String in eine Variable übergibt.
    - dann sucht man den gewünschten Eintrag und übergibt die Position ebenfalls in eine Variable
    - von dieser Position ermittelt man die Position des nächsten "="-Zeichens
    - von dieser Position aus bis zum "\n" ermittelt man nun noch den Wert als String, den man dann noch in Integer wandeln müsste und übergibt den Wert noch in eine Variable.
    - dann return variable.

    Die Schritte 2,3,4 wüsste ich gerne wie man das macht. Gibt es in C++ wie in VB spezielle Funktionen mit dem man die Positionen von Strings ermitteln kann und gibt es Funktionen mit denen man einen String von einer einer bestimmten Position mit einer bestimmten Länge ermitteln kann?



  • Inwiefern ist das schlanker?
    Das geht natürlich aber auch so. Die Klasse string hat einige Funktionen zum Suchen die alle mit find beginnen.
    http://www.cppreference.com/cppstring/index.html



  • dixidix schrieb:

    Ich nutze LinuxSuse10 mit dem g++ 4.0.2.
    Na gut, wird sich schon lösen lassen.

    Habe den 3.6.4 er, weil der 4er unter Gentoo noch nicht stable ist. Wie gesagt ist bestimmt irgendwas unsauber daran...



  • Dank Euerer Tipps habe ich mir das jetzt mal zusammengeschraubt, so dass es das macht was ich will. Der Link von Braunstein hat da wirklich geholfen.
    Bitte nicht dran stören, wenn da etwas mehr Code drin steht, als sein muss.
    Für den Zweck wofür ich es brauche, reicht dieser Code völlig aus, aber es geht sicherlich auch anders und einfacher.

    #include <string>
    #include <cstdlib>
    #include <iostream>
    #include <map>
    #include <sstream>
    #include <iterator>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    
    int instr(int, string, string);
    int len(string);
    string mid(string, int, int);
    string readfile(string);
    int getSetting(string, string);
    bool FileExist(string);
    
    //-----------------------------------------------------------------------------
    //Kleine Funktion, um die Datei auf Existenz zu prüfen, Warum siehe weiter unten!
    bool FileExist(string path)
    {
    if( (access( path.c_str(), 0 )) != -1 )
        return true;
    else
        return false;
    }
    //-----------------------------------------------------------------------------
    
    string readfile(string path)
    //hier wird die Datei eingelesen und der Inhalt als String übergeben
    {
    	string str;
    	string datei;
    
    //hier die Antwort auf das Warum von oben, Bei Bedarf hole ich mir hier eine Alternativdatei.	
    	if (FileExist(path.c_str())==true)
    	 {
    	  string datei(path.c_str());
    	 }
            else
            {
              string datei("Pfad zur alternativen Datei");
    	 }	 
    
        ifstream Quelle(path.c_str());
             char ch;
             while(Quelle.get(ch))
    	     {
                 str += ch;
             }
    
        Quelle.close();
        return str; 
    }
    //-----------------------------------------------------------------------------
    
    //-----------------------------------------------------------------------------
    //weil ich "VB-geschädigt" bin, habe ich mir die benötigten Funktionen InStr(), Mid() und Len() zusammengebaut.
    //Das macht den Code zwar nicht schlanker,
    //aber es hatte für mich sowas wie einen Lerneffekt...
    string mid(string str, int startpos, int strlen)
    {	
    string s(str.c_str());
     string sub2 = s.substr(startpos, strlen); 
    
       return sub2;
    }	
    
    //-----------------------------------------------------------------------------
    
    int instr(int start, string str, string sstr)
    {
    
      string str1(str.c_str()), str2(sstr.c_str());
    
      string::size_type pos = str1.find( str2, start );
    
       if( pos != string::npos )
    	{
         return pos;
    	}	
       else
        {   
         return 0;
    	}	
    
    }
    //-----------------------------------------------------------------------------
    
    int len(string str)
    {    
    
       string str2(str.c_str());
       string::size_type rlen = str2.size()	;
       return rlen;
    }	
    //-----------------------------------------------------------------------------
    
    //Hier die eigentliche Function, welche mir die Werte rausholt
    int getSetting(string settext, string gessetting)
    {
    int SetPos;
    int readPos;
    int EndPos;
    int	readlen;
    string s1(settext.c_str());
    string s2(gessetting.c_str());	
    
    SetPos = (instr(1, s1, s2));
    readPos = (instr(SetPos, s1, "=")) + 1;
    EndPos = (instr(readPos, s2, "\n"));
    
    if (EndPos == 0)
    	{
    	EndPos = len(s1);
    	}	
    
    readlen = EndPos - readPos + 1;
    string s3(mid(s1, readPos, readlen));	
    
        stringstream Str;
        Str << s3;
        int d;
        Str >> d;
        //cout << d << endl; 
    
    return d;
    }
    
    //-----------------------------------------------------------------------------
    //in Main kann diese Funktion ganz einfach eingesetzt werden
    int main() 
    
    {
    
    string text(readfile("Pfad zur gewünschten Datei"));
    
    cout<<(getSetting(text,"Die Bezeichnung des gewünschten Wertes"))<<endl;
    
    return 0;
    }
    


  • ich sehe gerade operatoren...
    frage warum muss der operator* eine referenz zurückgeben? ist das irgendwo festgelegt?

    int& foo::operator*() const
    {
          return p->it;
    }
    

    und warum sieht das so aus? gibt pointer zurück...was heisst das &(p->it) hier?

    int* foo::operator->() const
    {
          return &(p->it);
    }
    

    ciao



  • Nur noch ein paar Hinweise an dixidix

    Übergebe strings in Funktionen nie als Kopie (string str) sondern besser als konstante Referenz (nicht konstant falls geändert werden) soll. Also als Beispiel

    string mid(const string& str, int startpos, int strlen)
    

    Warum diese Stringkopie in deinen Funktionen. Das ist unnötig. Du kannst direkt mit den Parametern arbeiten. Bsp.
    aus

    int len(string str)
    {    
       string str2(str.c_str());
       string::size_type rlen = str2.size();
       return rlen;
    }
    

    wird dann

    size_t len(const string& str)
    {    
       return str.size();
    }
    

    Du kannst die Ergebnisse von Vergleichen auch direkt zurückgeben statt ein if dafür zu verwenden.
    aus

    bool FileExist(string path)
    {
    if( (access( path.c_str(), 0 )) != -1 )
        return true;
    else
        return false;
    }
    

    wird dann

    bool FileExist(const string& path)
    {
       return access( path.c_str(), 0 ) != -1;
    }
    


  • @Braunstein
    Danke für die Hinweise.

    Warum diese Stringkopie in deinen Funktionen. Das ist unnötig. Du kannst direkt mit den Parametern arbeiten. Bsp.
    aus

    Wie gesagt, war sowas wie ein Lerneffekt. Einige Hinweise habe ich übernommen. Wird ja auch kürzer.
    Danke! Bis bald!


Anmelden zum Antworten