Stream direkt verarbeiten
-
Hallo Zusammen,
ich habe vor kurzem angefangen mich mit C / C++ zu beschäftigen um ein GPS Projekt durchzuführen.
Leider habe ich ein Problem bei dem ich nicht weiterkomme.
Ich erhalte von meinem GPS Sensor die Daten in der Form :
GPRMC,080917.000,A,42.8881,N,0218.1801,E,0.01,351.01,0907,,,A62
$GPGGA,080918.000,42.80,N,0218.1806,E,1,06,1.5,120.3,M,27.5,M,,000058Im Augenblick speichere ich die Char-Daten in einem logfile und lese sie dann aus. Ich möche jedoch gerne ohne das Speichern auskommen und die Daten dirkt aus dem Buffer verwenden.
Ich möchte eigentlich das *.txt file duch einen Buffer, fester größe, ersetzen. Dieser soll in jedem schleifendurchlauf neue Daten erhalten. Leider bekomme ich das nicht richtig hin da ich ja in der Abfrage einen char benötige.
Eine zweite Frage hätte ich noch. Gibt es eine Möglichkeit das mit der verwendete Befehl "strtok" (Zeile 26) , für den fall z.B. "A,B,,D", für das fehlende C eine 0 gesetzt wird?
Hier noch mein Code wie ich Ihn gerade verwende.
Ich würde mich freuen wenn Ihr ein paar Tipps für mich habt.
Vielen Dank
Gruß
Berndvoid serial::ReadPort() { int numBuff = 255; char szBuff[255]; int numtemp; ofstream myfile; myfile.open("/home/GPSTemp.txt"); int i; while (1) { numtemp = read(hndlserial, &szBuff, sizeof (szBuff)); if (szBuff != 0) { FILE *file = fopen("/home/GPSTemp.txt", "r"); char Buffer[255] = {0}; while (fgets(Buffer, 255, file) != NULL) { if (Buffer[0] == '$') { if (memcmp(Buffer + 1, "GPGGA", 5) == 0) { char *token = strtok(Buffer + 6, ","); Auswertung der Daten } } myfile << szBuff<< << endl; szBuff[0] = 0; } }
-
Hallo und guten Tag
Dein Post leider etwas verwirrend weil er im C++/CLI Forum ist und du etwas von C und C++ schreibst.
Ich nehme nicht an, dass du wirklich C++/CLI Programmieren möchtest - das würde ziemlich sicher auch keinen Sinn machen, da diese Sprache einen sehr klaren Einsatzbereich hat.
Deshalb bleibt noch die Frage ob C oder C++ - ich persönlich würde das nicht mischen ausser du musst. Wenn du dich dann entschieden hast, verschiebt dich bestimmt ein netter Moderator.

Nur so als Hinweis - ev. wäre C# etwas für dich, da dort die Einstiegsschwelle niedriger ist als bei C++.
Gruss Simon
-
Hallo Simon,
danke für die Info. Das hab ich völlig übersehen das hinter dem C++ noch CLI stand, das ist mein Fehler, da sollte der Beitrag auch nicht hin.
Da ich mit C schon etwas erfahrung habe wollte ich eben bei C und C++ bleiben. Zu C# kann ich nichts sagen, da ich mich damit noch nicht beschäftigt habe.
Ich würde mich freuen wenn ein Moderator diesen Beitrag in das C++ Forum schieben könnte.
Danke schon mal.
-
Ok, dann ist mir nicht ganz klar, ob du ein File mit den Daten parsen möchtest oder direkt von der seriellen Schnittstelle lesen und parsen möchtest. Also wie?
-
Ich möchte die die Daten direkt von der seriellen Schnittstelle lesen und parsen.
-
Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ (auch C++0x und C++11) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
proesel schrieb:
Da ich mit C schon etwas erfahrung habe wollte ich eben bei C und C++ bleiben.
Was denn nun? C und C++ gleichzeitig geht nicht. Dein Code versucht das zwar zu mischen, aber das wird schiefgehen. C und C++ sind verschiedene Sprachen mit jeweils unterschiedlichen Herangehensweisen und inkompatiblen Standardbibliotheken.
proesel schrieb:
Ich möchte die die Daten direkt von der seriellen Schnittstelle lesen und parsen.
Die entscheidende Frage ist: Wie liest du die Daten von der seriellen Schnittstelle? Dazu nutzt du ja sicherlich irgendeine Bibliothek. Falls diese Bibliothek ein C++ Interface benutzt, dann hast du schon was du möchtest (sofern du C++ machen willst). Wenn sie ein C-Interface hast und du C++ möchtest, dann kapselst du die Schnittstelle in einen streambuf und koppelst diesen an einen istream. Wenn du C machen möchtest und die Bibliothek hat eine C-Schnittstelle, dann bist du ebenfalls schon direkt fertig. Wenn du C machen möchtest und die Bibliothek bietet nur eine C++-Schnittstelle: Oh, das, äh, das geht...irgendwie. Wird aber nicht so ganz einfach :p .
-
Stream direkt verarbeiten
Vermische bitte nicht C und C++!
-
Hallo Bernd,
Willkommen im C++-Forum.
proesel schrieb:
Im Augenblick speichere ich die Char-Daten in einem logfile und lese sie dann aus. Ich möche jedoch gerne ohne das Speichern auskommen und die Daten dirkt aus dem Buffer verwenden.
Da hast Du Dir gleich am Anfang eine anspruchsvolle Aufgabe vorgenommen. Gehe den Weg, den Dir SeppJ grob beschrieben hat. Er deutete ja bereits an
SeppJ schrieb:
Wird aber nicht so ganz einfach :p .
Wenn Du mit C++-Mitteln direkt von der seriellen Schnittstelle lesen möchtest, so benötigst Du einen konkreten Streambuf.
So weit ich das aus Deinem Code-Schnipsel schließen kann, werden die Daten mit einer Funktionread( hndlserial, ..von der Schnittstelle gelesen.Probiere mal folgenden Code aus - bitte die kommentierten Stellen vorher natürlich noch ausfüllen:
#include <streambuf> // #include "<serieller Schnittstellen Kram>" class SerialIn : public std::streambuf { public: typedef void* handle_type; // hier 'void*' ggf. gegen den Typ von 'hndlserial' ersetzen SerialIn( /* hier notwendige Parameter zum Öffnen der seriellen Schnittstelle einfügen */ ) : hndlserial() { // hier Code einfügen, um hndlserial zu setzen } ~SerialIn() { // hier Code einfügen, um die serielle Schnittstelle zu schließen // close( hndlserial ) } protected: virtual int_type underflow() { int len = read( hndlserial, Buff, sizeof(Buff) ); // blockiert, wenn keine Daten anstehen - oder?! if( len <= 0 ) return traits_type::eof(); // Ende des Input -> Fehler setp( Buff, Buff, Buff + len ); return traits_type::to_int_type( *Buff ); // Ok; mit erstem Zeichen aus dem Buffer zurück } private: handle_type hndlserial; char Buff[255]; // -- Kopieren Verhindern SerialIn( const SerialIn& ); SerialIn& operator=( const SerialIn& ); };Damit ausgerüstet kannst Du jetzt Deine Funktion
readPort()neu schreiben:#include <string> #include <iostream> // cout #include <limits> // numeric_limits<> // hier noch den obigen Code oder entsprechendes include einfügen void readPort() { using namespace std; SerialIn device( /* hier notwendige Parameter zum Öffnen der seriellen Schnittstelle einfügen */ ); istream in( &device ); // istream 'in' mit streambuf 'device' verbinden // -- folgendes ist nur zur Demo der Funktionsweise, parsen des Inputs sieht anders aus! in.ignore( std::numeric_limits< streamsize >::max(), '$' ); // Überlese alles bis zum '$' for( string token; getline( in, token, ',' ); ) // liest das erste Wort bis zum ',' { string rest; getline( in, rest, '$' ); cout << "Datensatz: " << token << " Rest: " << rest << endl; } }Versuche zunächst das so zum Laufen zu bringen, und meld' Dich dann noch mal.
proesel schrieb:
Eine zweite Frage hätte ich noch. Gibt es eine Möglichkeit das mit der verwendete Befehl "strtok" (Zeile 26) , für den fall z.B. "A,B,,D", für das fehlende C eine 0 gesetzt wird?
'
strtok' vergiss mal am besten, wie das geht machen wir später.Gruß
Werner
-
Super vielen Dank für die nette Hilfe.
Ich werd mir den Code nächste Woche genau anschauen. Eure Tipps haben mir aber jetzt schon soweit geholfen das es läuft

Somit hoffe ich, das ich mir mein wochenende verdient hab
Ich sag bescheid sobald ich den Code richtig und vollständig umgesetzt hab.
Danke nochma und ein schönes Wochen.
-
Hallo Bernd,
Bei dem Input Deines Programms handelt es sich um ein NMEA 0183-Protokoll. Da gibt es eine Menge Dinge, die 'input-technisch' ein wenig knifflig sind.
Und es exisitert bereits eine in C geschrieben Lib, die Dir die einzelnen Pakete parsen kann. Ich habe mir das mal kurz angeschaut und finde sie recht ordentlich gemacht.Entscheide Du Dich, ob das Programm in C oder C++ erstellt werden soll. Ich habe ein wenig experimentiert - hier ein (noch unvollendeter) Ausschnitt aus meinem Programmversuch, ein GGA-Paket zu parsen:
std::istream& operator>>( std::istream& in, GGA& gga ) { char g; return in >> gga.time >> comma >> geo_coordinate<'N','S'>(gga.latitude) >> comma >> geo_coordinate<'E','W'>(gga.longitude) >> comma >> gga.qualifier_indicator >> comma >> gga.n_sats >> comma >> gga.horizontal_dilution_of_precision >> comma >> gga.antenna_altitude >> comma >> g >> comma >> gga.geoidal_separation >> comma >> g >> comma >> opt(gga.age_of_differential_GPS_data=0) >> comma >> opt(gga.station_ID=0); }und das Pendat dazu aus der nmea-lib (Datei parse.c):
int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack) { char time_buff[NMEA_TIMEPARSE_BUF]; NMEA_ASSERT(buff && pack); memset(pack, 0, sizeof(nmeaGPGGA)); nmea_trace_buff(buff, buff_sz); if(14 != nmea_scanf(buff, buff_sz, "$GPGGA,%s,%f,%C,%f,%C,%d,%d,%f,%f,%C,%f,%C,%f,%d*", &(time_buff[0]), &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew), &(pack->sig), &(pack->satinuse), &(pack->HDOP), &(pack->elv), &(pack->elv_units), &(pack->diff), &(pack->diff_units), &(pack->dgps_age), &(pack->dgps_sid))) { nmea_error("GPGGA parse error!"); return 0; } if(0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))) { nmea_error("GPGGA time parse error!"); return 0; } return 1; }Der Autor der nmea-lib hat sich ein eigens
scanf('nmea_scanf' s.o.) geschrieben. In C++ habe ich das mit einigen Manipulatoren wie z.B.:comma,geo_coordinateundoptgelöst.Falls Du Dich für C++ entscheidest, werde ich versuchen Dir zu erklären, wie das geht.
Bis dann & Gruß
Werner