C++: Zeitstempel aus Datei auslesen

orffyre

Erfahrenes Mitglied
Hallo Tutorials!

Ich habe folgendes Problem:

Ich soll aus einer Datei Zeitstempel auslesen. Die Zeitstempel sehen immer so aus:

Code:
3043.507160
3043.507280
3043.540622
3043.564604
3043.564655
3043.684621
usw.

Diese Zahl erscheint immer am Anfang einer Zeile.

Der erste Schritt wäre nun, C++-Code zu schreiben, dass er sich diese Zeitstempel überhaupt merkt.

Danach muss ich immer den kleinsten und grössten Zeitstempel für ein jeweiliges Steuergerät rausfinden, aber dazu dann später mehr.

Bin für jede Hilfe dankbar!

Viele Grüsse,
orffyre
 
@jokey: Mein Problem ist, dass ich leider nur eine geringe Peilung von C++ habe und für jeden Code-Schnipsel oder Ratschlag, wie man auf den Code kommen kann, dankbar bin!

Grüsse,
orffyre
 
Ich weiß zwar net 100%ig was du genau willst aber falls du eine Datei hast die folgendes Format hat:
3043.507160 we rwe
3043.507280 dqwer we
3043.540622 sdfsdfs
3043.564604 sdfsd
3043.564655 fsdfsd
3043.684621 fsdfs
also Zeitstempel gefolgt von einem Leerzeichen und dann weiterer Text.

Wenn du nun einfach nur die Zeitstempel auslesen und sortieren willst könntest du das z.B. wie folgt machen
C++:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    string zeile;
    string zeitstempel;
    fstream file;
    vector<string> vec;

    file.open("C:\\zeitstempel.txt", ios_base::in);

    file.seekg(0, ios::beg);

    while(!file.eof()) {
        getline(file, zeile);
        zeitstempel = zeile.substr(0, zeile.find_first_of(' ', 0) - 1);
        vec.push_back(zeitstempel);
    }
    sort(vec.begin(), vec.end());

    for(unsigned int i = 0; i < vec.size(); ++i)
        cout << vec[i] << "\n";

    return 0;
}

Damit enthält der Vector vec nachher alle Zeitstempel aufsteigend sortiert.
 
Zuletzt bearbeitet von einem Moderator:
@drhastig: Vielen Dank für den Code! Aber leider soll ich das irgendwie anders machen...

Mein Programm liest eine Datei ein, sucht nach den Schlüsselwörtern "CH: ", "request is:" und "response is:" und schreibt die dazugehörigen Ergebnisse in einzelne Steuergerätedateien.

Diese Zahlen -

Code:
3043.507160 we rwe 
3043.507280 dqwer we
3043.540622 sdfsdfs
3043.564604 sdfsd
3043.564655 fsdfsd
3043.684621 fsdfs

- stehen immer am Anfang der jeweiligen durchsuchten Zeilen (also vor "CH: ", "request is" und "response is").

Jetzt merkt er sich natürlich alle Zahlen. Er soll aber nur den kleinsten Zeitstempel und den grössten pro Steuergerät rausschreiben!

Wie könnte ich das machen?

Also ich habe mir schon überlegt, das eventuell mit MIN/MAX zu machen, weiss aber nicht, ob es mein Anliegen zulässt.

Vielen Dank schonmal im Vorraus!

Viele Grüsse,
orffyre
 
Dann such doch einfach Nach dem Einlesen Nach dem entsprechenden Teilstring (z.B. Funktion find auf <string>). Nutze dann anstatt dem Vector einfach eine entsprechende Anzahl an Arrays.

Ungetestet:
C++:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdlib>
 
using namespace std;

void addZeit(string &array, string zeit) {
    if(array[0] == "leer")
        array[0] = zeit;
    else if(array[1] =0 "leer")
        array[1] = zeit;

    if(atof(array[0].data()) > atof(zeit.data())
        array[0] = zeit;
    else if(atof(array[1].data()) < atof(zeit.data())
        array[1] = zeit;
}
 
int main(int argc, char** argv) {
    string zeile;
    string zeitstempel;
    fstream file;
    //vector<string> vec;
    string ch[2] = {"leer", "leer"};
    string request[2] = {"leer", "leer"};
    string response[2] = {"leer", "leer"};
 
    file.open("C:\\zeitstempel.txt", ios_base::in);
 
    file.seekg(0, ios::beg);
 
    while(!file.eof()) {
        getline(file, zeile);
        zeitstempel = zeile.substr(0, zeile.find_first_of(' ', 0) - 1);
        if(zeile.find("CH:") != string::npos)
            addZeit(ch, zeitstempel);
        if(zeile.find("request is:") != string::npos)
            addZeit(request, zeitstempel);
        if(zeile.find("response is:") != string::npos)
            addZeit(response, zeitstempel);
        //vec.push_back(zeitstempel);
    }
    /*
    sort(vec.begin(), vec.end());
 
    for(unsigned int i = 0; i < vec.size(); ++i)
        cout << vec[i] << "\n";
    */
    return 0;
}

Der Code ist bestimmt mieserabel aber vom Prinzip her sollte es so gehn :P
 
@drhastig: Wieder mal danke für deine grosse Hilfe!

Nun, eigentlich sind die "response is" und "request is" für diesen Teil der Programmierung nicht nötig.

Das jeweilige Steuergerät steht nach "CH: ". (zb. CH: EIS oder CH: RON usw)

Die Zeitstempel sollen nur den Steuergeräten zugeordnet werden und auch nur der kleinste und der grösste Stempel.

Habe gestern ein wenig rumprobiert und hab es bisher noch nicht hinbekommen.

Vielleicht fällt jemandem ja noch was ein.

Viele Grüsse,
orffyre
 
Poste mal bitte 2 Zeilen aus einem original File. Und dann sach nochmal genau, was du haben willst. Dann schreib ichs dir von mir aus kurz ;)
 
@devdevil: Das wär echt Hammer!

Also so sieht das in dem Trace-File aus:

Code:
3063.951403 00 CH: EIS_20x   response is: 50 03 00 14 00 c8 
3064.035580 00 CH: EIS_20x    request is: 22 f1 00 
3064.051335 00 CH: EIS_20x   response is: 62 f1 00 00 00 0e 03 
3064.057087 00 CH: EIS_20x    request is: 22 f1 54 
3124.551631 10 CH: CGW_20x   response is: 50 01 00 14 00 c8 
3124.557071 07 CH: ROOF_20x   response is: 50 01 00 14 00 c8 
3124.557577 04 CH: TSLM_20x   response is: 50 01 00 14 00 c8 
3124.557709 09 CH: DMFL_20x   response is: 50 01 00 14 00 c8

Hier sind die diversen Steuergeräte (EIS_20x, CGW_20x, ROOF_20x) sehr gut zu sehen. Vorne sieht man die jeweiligen Zeitstempel.

Ich muss jetzt praktisch immer den niedrigsten Zeitstempel und den letzten Zeitstempel PRO Steuergerät rausschreiben.

Für das Rausschreiben gibt es eine Methode "setZeitstempel" und zwei Variablen vom Typ "double", genannt "minZeitstempel" und "maxZeitstempel".

Viele Grüße,
orffyre
 
Darf man erfahren, welche Bedeutung die vor CH stehenden 00, 10 usw. als Bedeutung haben? Und soll der String nach is: noch weiter interpretiert werden?

Nja erstmal so:
C++:
#if !defined (ENTRY_HPP__INCLUDED)
#define ENTRY_HPP__INCLUDED

#pragma once

#include <cstddef>
#include <iostream>
#include <string>

struct entry 
{
    double timestamp;
    std::string control;
    enum type_t { response, request } type;
    std::string data;
    
    entry()
        : timestamp(0.0), type(request)
    {}

    const bool operator<(entry const& rhs) const
    { return timestamp < rhs.timestamp; }

    const bool operator>(entry const& rhs) const
    { return timestamp < rhs.timestamp; }


    friend std::istream& operator>>(std::istream& in, entry& data)
    {
        // read timestamp
        if (!(in >> data.timestamp)) { in.setstate(std::ios_base::failbit); return in; }
        
        // read line
        std::string line;
        std::getline(in, line);

        // interpret control name
        const std::string::size_type pos_control_begin(line.find("CH: "));
        if (pos_control_begin == std::string::npos) { in.setstate(std::ios_base::failbit); return in; }
        
        const std::string::size_type pos_control_end(line.find(" ", pos_control_begin));
        if (pos_control_end == std::string::npos) { in.setstate(std::ios_base::failbit); return in; }
        data.control = line.substr(pos_control_begin, pos_control_end - pos_control_begin);

        // interpret message type
        std::string::size_type pos_data(0);
        if ((pos_data = line.find("response is: ", pos_control_end)) != std::string::npos) data.type = response;
        else if ((pos_data = line.find("request is: ", pos_control_end)) != std::string::npos) data.type = request;
        else  { in.setstate(std::ios_base::failbit); return in; }

        // interpret message data
        data.data = line.substr(pos_data + (type == response ? 13 : 12));

        return in;
    }

    friend std::ostream& operator<<(std::ostream& out, entry const& data)
    { return out << data.timestamp << " 00 CH: " << data.control << "   " << (data.type == response ? "response" : "request") << " is: " << data.data << std::endl; }
};

#endif // ENTRY_HPP__INCLUDED

C++:
#include "entry.hpp"
#include <iterator>
#include <fstream>
#include <vector>
#include <algorithm>

int main()
{
    std::ifstream file_stream("trace.log");
    if (!file_stream) return 1;

    std::vector<entry> data;
    std::copy(std::istream_iterator<entry>(file_stream), std::istream_iterator<entry>(), std::back_inserter(data));
    if (!file_stream) return 1;

    std::sort(data.begin(), data.end());
}

So hast du die Zeitstempel nach Größe sortiert ... geht noch effektiver zu implementieren ... is jetztn 5min ansatz gewesen, sry ;)

Jetzt halt gucken, dass du jeden Controler nur 2 mal (mit min und max) hast ... dafür müsste man jetzt wissen, ob du die Anzahl der verschiedenen Controler kennst ...
 
Zuletzt bearbeitet:
Zurück