csv in vector vom typ struct einlesen



  • Hallo

    Da ich gerade wegen Krankheit wohl länger ans Bett gefesselt bin
    habe ich wieder mal wieder etwas Zeit etwas C++ zu spielen und vieleicht sogar etwas praxisbezogenes zu schreiben

    Ich kann eine csv-Datei meiner aktuellen
    Blutdruckwerte aus der Vita-Dock(Cloud) herunterladen. Mein Ziel ist es diese Datei erstmal von den idiotischen Kommentaren zu befreien und dann die eigentlichen Daten in einen benutzerdefinierten Typ-Vector einzulesen um sie dann entweder wieder in eine sauber formatierte CSV Datei zu schreiben, oder später dann auch grafisch zu verarbeiten. Ich gehe jetzt mal davon aus das die Cloud-CSV Dateien in Zukunft das Format beibehalten werden.

    Ich bin bis jetzt so weit gekommen das ich mit getline die Kommentare, Anführungszeichen, Semikolon und leere Zeilen wegbekommen habe. Die eigentlichen Daten sind lediglich die letzten drei Zeilen, wobei die kompletten Daten natürlich wesentlich mehr Daten enthalten, die aber erstmal gelöscht wurden wegen der Übersichtlichkeit.

    Ich habe versucht einen neuen struct-Typ zu deklarieren der der Einfachheit halber erstmal nur string-typen enthält (wegen dem Datum/Zeit, das später evtl mal eine eigene Klasse werden soll). Konkret brauche ich nur die Felder Datum,Systole,Diastole und Puls. Die bekomme ich auch gut Zeilenweise wenn ich den Code ausführe.

    Nur schaffe ich es nicht einem Vector vom typ Reading damit zu füllen. Ich bekomme immer einen Vector mit 21 Elementen, dabei sollten es mit den Sample Daten doch nur 3 Elemente mit jeweils date,sys,dia,pul sein.

    Hier erstmal das Sample-Daten CSV:

    # Messwerte_Blutdruck_17-3-16.csv

    "Ihre Blutdruck-Messdaten vom 25.06.2015 bis 17.03.2016"
    
    Optimalwerte nach WHO:
    
    "Systole:";"90 - 139 mmHg"
    "Diastole:";"60 - 89 mmHg"
    "Puls:";"60 - 90 bpm"
    
    "Ihre letzte Blutdruck Messung war am  17.03.2016 "
    
    "Systole:";"99 mmHg"
    "Diastole:";"60 mmHg"
    "Puls:";"71 bpm"
    
    ;Maximalwert;Minimalwert;Durchschnitt;Gesamtzahl
    "Systole:";"138 mmHg";"79 mmHg";"105 mmHg";"727"
    "Diastole:";"89 mmHg";"40 mmHg";"66 mmHg";"727"
    "Puls:";"103 bpm";"56 bpm";"70 bpm";"727"
    
    Datum - Uhrzeit;Systole;Diastole;Puls;Stimmung;Aktivität;Anmerkungen
    
    "25.06.2015 - 19:14";"104 mmHg";"68 mmHg";"72 bpm";"0";"2";"  "
    "25.06.2015 - 21:27";"104 mmHg";"75 mmHg";"67 bpm";"0";"2";"  "
    "26.06.2015 - 08:03";"114 mmHg";"71 mmHg";"67 bpm";"0";"2";"  "
    

    Und hier der Code den ich bisher geschrieben habe:

    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <sstream>
    
    using namespace std;
    
    struct Reading {
      string date;
      string sys;
      string dia;
      string pul;
      Reading(string d, string s, string di, string p)
        :date(d),sys(s),dia(di),pul(p) {}
    };
    
    int main()
    {
      string date;
      string sys;
      string dia;
      string pul;
    
      vector<Reading> a;
    
      ifstream file("Messwerte_Blutdruck_17-3-16.csv");
      if(!file) cout << "ERROR !file" << endl;
    
      string dummy;
      for (int i=0;i<22;++i){                   // discard top non data lines
      getline(file,dummy);}
      string str;
    
      while (getline(file,str)) {               // read data lines
         istringstream ss(str);
         string str2;
         while (getline(ss,str2, '"')){         // discard quotation marks
           istringstream ss2(str2);
            string str3;
           while (getline(ss2,str3, ';')) {     // discard semicolon
               if (str3 == "") continue;        // discard blank lines
               cout << str3 << endl;            // looks ok so far
               istringstream ss3(str3);
                string str4;
               while (getline(ss3,str4))
               a.push_back(Reading(date,sys,dia,pul));  // wrong attempt?
             }
         }
        }
      cout << a.size() << endl;                 // should be 3 but is 21
      return 0;
    }
    

    Natürlich fehlt dann immer noch die Werte für sys,dia,pul von den "mmHg" und "bpm" zu entfernen aber das sollte dann nicht so schwierig sein.

    Kann mir jemand ein Wink geben was mein Hirn hier falsch macht, bzw. ob das alles totaler Müll ist und ich von vorn beginnen sollte oder ob ich auf dem richtigen Weg bin. 😕



  • Ich würde da gar nicht elendig lange rummachen und die Zeilen mit regex suchen und zerhacken:

    #include <regex>
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <iterator>  // back_inserter
    
    using namespace std;
    
    struct str_tuple{
    	string data[7];
    };
    
    ostream& operator<<(ostream& out, const str_tuple& t) {
    	for(const auto& d : t.data)
    		out << d << ' ';
    	return out;
    }
    
    template<typename It>
    void read(istream& in, It dst) {
    	const static regex re{
    		R"_(^"([^"]*)";"([^"]*)";"([^"]*)";"([^"]*)";"([^"]*)";"([^"]*)";"([^"]*)"$)_"};
    	smatch match;
    	for(string l; getline(in, l);) {
    		if (regex_match(l, match, re)) {
    			str_tuple t = {{ match[1],match[2],match[3],match[4],
    			               match[5],match[6],match[7] }};
    			*dst++=t;
    		}
    	}
    }
    
    int main() {
    	ifstream in("Messwerte_Blutdruck_17-3-16.csv");
    	if(!in)
    		return 1;
    	vector<str_tuple> str_tuples;
    	read(in, back_inserter(str_tuples));
    	for(const auto& t : str_tuples)
    		cout << t << '\n';
    }
    

    Damit hast Du schon mal das csv Gedöns aus dem Rücken.



  • Ok danke Furble Wurble, das ist aber ziemlicher overkill für mich total Anfänger. Soweit war ich ja auch fast schon, wenn auch etwas simpler.

    Alle die noch was zum lachen haben möchten hier mein zweiter Versuch, aber der spuckt immerhin schon mal nur das aus was ich haben will, sogar ohne mmHg..., aber ohne struct und vector:

    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <sstream>
    
    using namespace std;
    
    int main()
    {
      char qm1;
      int day;
      char pt1;
      char monthch1;
      char monthch2;
      char pt2;
      int year;
      char hyphen1;
      char hourch1;
      char hourch2;
      char colon1;
      char minutech1;
      char minutech2;
      char qm2;
      char semic;
      char qm3;
      int sys;
      char mmhg1;
      char mmhg2;
      char mmhg3;
      int dia;
      char qm4;
      char semic2;
      char qm5;
      char qm6;
      char mmhg4;
      char mmhg5;
      char mmhg6;
      char mmhg7;
      char qm7;
      char semic3;
      char qm8;
      int pul;
    
      ifstream file("Messwerte_Blutdruck_17-3-16.csv");
      if(!file) cout << "ERROR !file" << endl;
    
      string dummy;
      for (int i=0;i<22;++i){                   // discard top non data lines
      getline(file,dummy);}
      string str;
    
      while (getline(file,str)) {
        // cout << str << endl;
        stringstream ss(str);
        while (ss >> qm1 >> day >> pt1 >> monthch1 >> monthch2 >> pt2 >> year >> hyphen1 >> hourch1 >>
               hourch2 >> colon1 >> minutech1 >> minutech2 >> qm2 >> semic >> qm3 >> sys >> mmhg1 >>
               mmhg2 >> mmhg3 >> qm4 >> semic2 >> qm5 >> qm6 >> dia >> mmhg4 >> mmhg5 >> mmhg6 >>
               mmhg7 >> qm7 >> semic3 >> qm8 >> pul)
          {
            cout << day << '.' << monthch1 << monthch2 << '.' <<  year << '-' << hourch1 << hourch2 << minutech1 <<
                    minutech2 << ',' << sys << ',' << dia << ',' << pul<< endl;
          }
        }
      return 0;
    }
    

    Output:

    25.06.2015-1914,104,68,72
    25.06.2015-2127,104,75,67
    26.06.2015-0803,114,71,67
    


  • ok ich habe es. Ich kann jetzt den vector "bdata" vom Typ "Blood" mit den Werten füllen und auch wieder ausgeben.

    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <sstream>
    
    using namespace std;
    
    struct Blood {
      string date;
      int sys;
      int dia;
      int pul;
      Blood(string d, int s, int di, int p)
        :date(d),sys(s),dia(di),pul(p){}
    };
    
    int main()
    {
      char qm1;
      char day1;
      char day2;
      char pt1;
      char monthch1;
      char monthch2;
      char pt2;
      int year;
      char hyphen1;
      char hourch1;
      char hourch2;
      char colon1;
      char minutech1;
      char minutech2;
      char qm2;
      char semic;
      char qm3;
      int sys;
      char mmhg1;
      char mmhg2;
      char mmhg3;
      int dia;
      char qm4;
      char semic2;
      char qm5;
      char qm6;
      char mmhg4;
      char mmhg5;
      char mmhg6;
      char mmhg7;
      char qm7;
      char semic3;
      char qm8;
      int pul;
    
      ifstream file("Messwerte_Blutdruck_17-3-16.csv");
      if(!file) cout << "ERROR !file" << endl;
    
      string dummy;
      for (int i=0;i<22;++i){                   // discard top non data lines
      getline(file,dummy);}
      string str;
      vector<Blood> bdata;
      int i = 0;
      while (getline(file,str)) {
        // cout << str << endl;
        stringstream ss(str);
        while (ss >> qm1 >> day1 >> day2 >> pt1 >> monthch1 >> monthch2 >> pt2 >> year >> hyphen1 >> hourch1 >>
               hourch2 >> colon1 >> minutech1 >> minutech2 >> qm2 >> semic >> qm3 >> sys >> mmhg1 >>
               mmhg2 >> mmhg3 >> qm4 >> semic2 >> qm5 >> qm6 >> dia >> mmhg4 >> mmhg5 >> mmhg6 >>
               mmhg7 >> qm7 >> semic3 >> qm8 >> pul){
            ++i;
            stringstream ssdate;
            ssdate << day1 << day2 << '.' << monthch1 << monthch2 << '.' << year << '-' << hourch1 << hourch2 << minutech1 << minutech2;
            string sa2 = ssdate.str();
            bdata.push_back(Blood(sa2,sys,dia,pul));
          }
        }
      cout << "vector content:" << endl;
      for (unsigned int i=0;i<bdata.size();++i){
          cout << bdata[i].date << ',' << bdata[i].sys << ',' << bdata[i].dia << ',' << bdata[i].pul  << endl;
        }
      return 0;
    }
    

    output:

    vector content:
    25.06.2015-1914,104,68,72
    25.06.2015-2127,104,75,67
    26.06.2015-0803,114,71,67
    

Anmelden zum Antworten