csv datei duchrsuchen



  • Hallo zusammen, Ich hab die Aufgabe eine csv datei auslesen und eine bestimmte Zahl, die man in Konsole angibt, aus der zweite Spalte der datei suchen.
    Ist diese Zahl vorhanden dann muss ich alle andere Zahlen in dieser reihe aus anderen Spalten ausgeben.
    das mit auslesen und such nach der Zahl hab ich schon hinbekommen. ka wie ich die andere Zahlen aus anderen Spalten ausgeben kann.
    Kann mir einer bitte dabei helfen????

    Mein code ist:

    #include "stdafx.h"
    #include <vector>
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <iterator>
    #include <fstream>
    #include <sstream>
    using namespace std;
    
    template<class T> std::string toString(const T& t)
    {
    	std::ostringstream stream;
    	stream << t;
    	return stream.str();
    }
    
    template<class T> T fromString(const std::string& s)
    {
    	std::istringstream stream (s);
    	T t;
    	stream >> t;
    	return t;
    }
    
    vector<string> &split(const string &s, char delim, vector<string> &elems) {
    	stringstream ss(s);
    	string item;
    	while (getline(ss, item, delim)) {
    		elems.push_back(item);
    	}
    	return elems;
    }
    
    vector<string> split(string s, char delim) {
    	vector<string> elems;
    	split(s, delim, elems);
    	return elems;
    }
    
    vector<string> readData(const string &path)
    {
    	std::vector<std::string> lines;
    	ifstream fin(path);
    	std::string line;
    	while(getline(fin, line))
    	{
    		lines.push_back(line);
    	}
    	return lines;
    }
    bool searchValue(vector<string> data, int column, string value, vector<string> &row)
    {
    	for(unsigned int i=1; i<data.size();i++)
    	{
    		row = split(data[i],';');
    		string tc = row[column-1];
    		if(tc.compare(value)==0)
    			return true;
    	}
    	return false;
    }
    string replace(string str, char c, char newc)
    {
    	for(unsigned int i=0;i<str.size();i++)
    	{
    		if(str[i] == c)
    			str[i] = newc;
    	}
    	return str;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	vector<string> data = readData("data.csv");
    	vector<string>* row = new vector<string>();
    
    	string number = "";
    	while(number[0] != 'e')
    	{
    		cout << "Suche nach T[C]: ";
    		cin >> number;
    		bool wasfound = searchValue(data,2,number, *row);
    		if(wasfound == true)
    		{
    			\\TODO
    		}
    		else
    			cout << "T[C] nicht gefunden " << endl;
    	}
    	return 0;
    }
    

    THX



  • Hallo guguli,

    das ist Dein dritter Thread in dem Du mit einer Anfrage dieser Art kommst. Daraufhin hast Du bereits Antworte bekommen. Unter anderen von mir: http://www.c-plusplus.net/forum/p2355651#2355651. Von Dir kam darauf aber keine Reaktion.
    Ansonsten kann ich Dir noch diese Threads empfehlen: http://www.c-plusplus.net/forum/p2291927#2291927 oder http://www.c-plusplus.net/forum/p2016039#2016039

    Richtig geholfen wird Dir, wenn Du auch Feedback zu Antworten gibst.

    Gruß
    Werner

    PS.: kann es sein, dass durch den 'Forum-Crash' ein paar Postings verloren gegangen sind?



  • nein, aber auf diese Frage wurde noch nicht geantwortet :).
    Ich versuch mit den links, die du mir geschickt hast.
    THX



  • Die Beiträge bringen mich nicht weiter 😞



  • Werner Salomon schrieb:

    PS.: kann es sein, dass durch den 'Forum-Crash' ein paar Postings verloren gegangen sind?

    .. bin schon der Meinung, dass dieser Beitrag 'http://www.c-plusplus.net/forum/321392' verloren gegangen ist.

    Ich melde mich heute Abend noch mal.

    Ich postuliere mal, dass das Format Deiner csv-Datei so aussieht:

    // jeweils 1 int und 7 double durch ';' getrennt.
    20;1.23;4.23;9.1;2.02;2.91;3.01;0.02
    

    stimmt das?

    Bis dann
    Werner



  • Hi, Nicht ganz. die Datei sieht so aus:

    1;218;4.23;9.1;2.02;2.91;3.01;0.02

    DIe erste zahl ist ja die zeilen Nummerierung, und die zweite ist dann die Temperatur, also die X-Achse. zu jeder x_wert gibt es 6 Y-werte => 6 unterschiedlichen Kurven.



  • Hallo guguli,

    Zunächst solltest Du das, was in der Datei steht, 'vernünftig' lesen. Da stehen Zahlen drin, also lese auch Zahlen und keine Zeichenketten. Damit man das ganze auch noch sinnvoll unterbringt, schnitze man sich zunächst mal eine struct/class . Also z.B.:

    struct Entry
    {
        static const int N = 6; // das brauchen wir später noch, daher als Konstante
        double temp_; // die Temperatur ist hier auch ein double; rechnet sich besser
        double y_werte_[N];
    };
    

    das erste Ziel sollte es sein, dass nach dem Lesen der Datei ein gefüllter std::vector<Entry> vorliegt. Damit kann man dann bequem weiter arbeiten. Dazu benötigt man eine Funktion, die ein Entry-Objekt liest - die Zeilennummer kommt später. Zwischen den Zahlen steht jeweils ein ';' - das sollte man zum einen überlesen und zum anderen auch prüfen, ob das so ist - sonst wär's ein Lesefehler. Der erste Schritt ist demnach, eine Funktion zu schreiben, die man so aufrufen kann:

    Entry einEntryObjekt;
        if( cin >> einEntryObjekt ) { // diese Funktion liest ein Entry-Objekt
            cout << "Ok" << endl;
        }
    

    Alles zusammen:

    #include <iostream> // cout, cerr
    #include <string>
    
    struct Entry
    {
        static const int N = 6;
        double temp_;
        double y_werte_[N];
    };
    
    // --  diese Funktion liest ein Zeichen und setzt den Stream 'in' auf 'fail' falls es kein 'C' ist
    template< char C >
    std::istream& Char( std::istream& in )
    {
        char c;
        if( in >> c && c != C )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    // --  diese Funktion liest ein Entry-Objekt
    std::istream& operator>>( std::istream& in, Entry& e )
    {
        in >> e.temp_; // Temperatur lesen
        for( int i = 0; i < Entry::N; ++i )
            in >> Char<';'> >> e.y_werte_[i]; // N-mal ein ';' und ein Y-Wert lesen
        return in;
    }
    
    int main()
    {
        using namespace std;
        Entry einEntryObjekt;
        if( cin >> einEntryObjekt )
        {
            cout << "Ok" << endl;
        }
        return 0;
    }
    

    Wenn Du dieses Programm aufrufst, sollte etwa so was passieren:

    218;4.23;9.1;2.02;2.91;3.01;0.02
    Ok
    

    .. probiere das ruhig mal aus.

    Im nächsten Schritt wollen wir aber nicht nur einen Teil der Zeile von 'cin' lesen, sondern viele ganze Zeilen aus der Datei, also gilt es, die Funktion readData() entsprechend anzupassen:

    // --   liest viele 'Entry' aus der Datei 'path'
    //      falls es schiefgeht, wird ein leerer vector zurück gegeben
    std::vector< Entry > readData( const std::string &path ) // erfordert #include <string>
    {
        using namespace std;
        vector< Entry > entries; // erfordert #include <vector>
        ifstream fin( path.c_str() ); // erfordert #include <fstream>
        if( !fin.is_open() )
        {
            cerr << "Fehler beim Oeffnen der Datei" << endl;
            return entries; // ist leer, also Fehler
        }
        for( Entry e; fin.ignore( numeric_limits<streamsize>::max(), ';' ) >> e; ) // erfordert #include <limits>
            entries.push_back( e ); // Lesen war ok; also speichern
        if( !fin.eof() )
        {
            cerr << "Fehler beim Lesen der Datei" << endl;
            return vector< Entry >(); // mit leerem vector zurück, da Lesefehler
        }
        return entries; // alle iO.
    }
    

    In Zeile 13 wird mittels der Methode ignore alles bis und einschließlich dem ersten ';' überlesen, damit steht der Lesezeiger jetzt hinter dem ersten ';' in der Zeile. Der Rest des Lesens funktioniert wie oben bereits demonstriert.

    Zur Kontrolle solltest Du die gelesenen Werte auch wieder ausgeben können. Ich beschränke mich dabei nur auf die Y-Werte - das geht ähnlich wie das Lesen:

    std::ostream& operator<<( std::ostream& out, const Entry& e )
    {
        out << e.y_werte_[0];
        for( int i=1; i < Entry::N; ++i )
            out << ";" << e.y_werte_[i];
        return out;
    }
    

    damit ist das erste Ziel erreicht, wie folgende Demo zeigt:

    #include <fstream>
    #include <iostream> // cout, cerr
    #include <string>
    #include <vector>
    #include <limits>
    
    // struct Entry .. (s.o.)
    
    // template< char C >
    // std::istream& Char( std::istream& in ) (s.o.)
    
    // std::istream& operator>>( std::istream& in, Entry& e ) (s.o.)
    
    // std::ostream& operator<<( std::ostream& out, const Entry& e ) (s.o.)
    
    // std::vector< Entry > readData( const std::string &path ) (s.o.)
    
    int main()
    {
        using namespace std;
        vector< Entry > entries = readData( "data.csv" );
        if( !entries.empty() )
            cout << "Die letzen Y-Werte waren: " << entries.back() << endl;
        return 0;
    }
    

    Bevor ich Dir jetzt erkläre, wie man nach einem bestimmten Eintrag sucht, solltest Du zunächst schildern, was Du genau vorhast. Aus Deinen letzten drei Postings schließe ich, dass jetzt eine beliebige Temperatur eingegeben werden soll, und das Programm sechs Y-Werte ausgeben soll, die für diese Temperatur interpoliert werden sollen - oder!?
    Das setzt übrigens voraus, dass die Temperaturen stetig steigend (oder fallend) in der Datei stehen - ist das so? Soll das überprüft werden?

    Gruß
    Werner


Log in to reply