String mit Zahlen oder Bool-Werten kombinieren
-
Hallo,
beim Lesen und Schreiben vom/zum Datenbanksystem, habe ich einen "Datenbuffer" in Form eines Char-arrays ( z.B. char datenbuffer[255] ). in diesen muss ich nun nicht nur meine Vars vom typ string, sondern auch die boolschen und soinstigen Variablen setztencName = datenbuffer.substr(1,30);Wenn aber z.B byte 31-34 ein int sein soll ..
int myInt = 123;wie bekomme ich das in den string?, resp. aus dem String zurück in myInt?
Als string umzuwandel geht nicht, weil man auf die Daten auch z.B. über SQL zugreifen kann!
Hanns
-
-
Schau mal in die FAQ.
-
Ich habe den Link nur kurz überflogen, ist es aber glaube ich nicht.
Das möchte ich nicht :
int a = 3.14;
// wandle in String..
str b = "3.14";ich suche die Wandlung in die binäre darstellung:
int a = 10; char aAsByte{2]; aAsByte[0] = 0x0; aAsByte{1] = 0x0A;und
databuffer [31] = aAsByte[0]; databuffer[32] = aAsByte[1];in Basic gibts da : a$ = MKI$ ( 10); // oder so ähnlich
Meine Zahl muss also so in den databuffer, daß ich z.b über den ODBC-Treiber eine INT ab Position 30 lesen kann?
Irgendwie fällt es mir schwer, das Problem zu beschreiben

Muss leider auch nebenbei tapezieren
Hanns
-
HannsW schrieb:
beim Lesen und Schreiben vom/zum Datenbanksystem, habe ich einen "Datenbuffer" in Form eines Char-arrays ( z.B. char datenbuffer[255] ). in diesen muss ich nun nicht nur meine Vars vom typ string, sondern auch die boolschen und soinstigen Variablen setzten
cName = datenbuffer.substr(1,30);Wenn aber z.B byte 31-34 ein int sein soll ..
int myInt = 123;wie bekomme ich das in den string?, resp. aus dem String zurück in myInt?
Als string umzuwandel geht nicht, weil man auf die Daten auch z.B. über SQL zugreifen kann!Hallo Hanns,
die 'saubere' Lösung wäre ein Binaer-Stream, der Dir Werte wie z.B. ein int genauso in einen streambuf und damit z.B. in ein Stück Memory schreibt, wie die Datenbank es benötigt. Skizzenhaft sähe das in der Anwendung so aus:
#include <sstream> #include "binstream.h" std::basic_stringbuf< char > buf; // besser als char[255] und kompatibel binstream strm( &buf ); strm.write( p30Byte, 30 ); // schreibe die ersten 30 Byte int i = 42; strm << i; // und int dahinter // an die Bytes kommt man ran.. buf.str().c_str();Und der binstream ist dann ein Pendant zum std::iostream
// Datei binstream.h #include <iostream> #include <streambuf> class binstream : public std::basic_ios< char > { public: typedef std::basic_ios< char > base_type; explicit binstream( std::streambuf* sb = 0 ) : base_type( sb ) {} // -- Schreiben binstream& operator<<( int x ) { // ich unterstelle hier mal, dass ein int im Memory // genauso aussieht, wie die DB es braucht return write( reinterpret_cast< const char* >( &x ), sizeof( int ) ); } binstream& write( const char* bytes, std::streamsize n ) { if( rdbuf()->sputn( bytes, n ) != n ) setstate( std::ios_base::failbit ); return *this; } // -- Lesen binstream& operator>>( int& x ) { return read( reinterpret_cast< char* >( &x ), sizeof( int ) ); } binstream& read( char* bytes, std::streamsize n ) { if( rdbuf()->sgetn( bytes, n ) != n ) setstate( std::ios_base::failbit ); return *this; } };Ist Dein Buffer immer gleich lang, bzw. muss er eine bestimmte Länge haben?
Gruß
Werner
-
Hallo Werner, Deine Ausführungen sehen sehr interessant aus.
werde ich mir morgen mal durcharbeiten.
Was mir so beim Tapeteabkratzen noch einfiel.:Wenn ich mir eine STRUCT bastele, die genau dem Datensatz meiner DB entspricht, müsste ich dies dann doch in eine union mit dem Datenbuffer kombinieren können.??
Deien Frage nach der Datenlänge: Ja, zwar je TABLE unterschiedlich, aber im gleichen TABLE immer Konstant: ein Byt mehr oder weniger ergibt einen STATUS-ERROR
Gruß Hanns
-
HannsW schrieb:
Wenn ich mir eine STRUCT bastele, die genau dem Datensatz meiner DB entspricht, müsste ich dies dann doch in eine union mit dem Datenbuffer kombinieren können.??
Hallo Hanns,
ja das wäre u.U. auch eine Lösung. Allerdings müssen ein paar Voraussetzungen erfüllt sein. Die erste ist, dass die Darstellung der verwendeten Typen in der DB und im Memory Deiner (!) Implementierung identisch sind.
Die zweite ist, dass Du die Struktur so definieren musst, dass sie das gleiche 'Package' wie die DB hat. Ich vermute mal aus Deinen Ausführungen, dass das Package der DB 1 hat, also die einzelnen Variablen dicht an dicht im Speicher abgelegt sind.
Schau einfach mal unter '#pragma pack' in Deiner Hilfe nach.Die union- oder auch reinterpret_cast-Lösung ist für kleinere Anwendungen einfacher; die binstream-Lösung ist flexibler und gibt Dir die Möglichkeit auf Abweichungen zwischen DB und Memory zu reagieren.
In jeden Fall empfehle ich Dir für jeden TABLE-Typ eine eigene Klasse oder Struct anzulegen, die über Get- und Set-Methoden für die einzelnen Member verfügt und einen Mechanismus, mit der ein Objekt dieses Typs aus der DB gelesen bzw. hinein geschrieben werden kann.
Bei einer Lösung, die auf eine Memory-Kopie abzielt, ist das natürlich sehr einfach, im Prinzip brauchst Du auch keine Get- und Set-Methoden, aber schon eine Zuweisung von char[30] ist nicht trivial. Für die Anwendung wäre ist es natürlich einfacher
struct TABLEEntry1 { char m_txt[30]; int m_i1; void SetTxt( const std::string& txt ); }; TABLEEntry1 e; e.SetTxt( <irgendwas> );zu schreiben, als sich mit strcpy inklusiver der notwendigen Überprüfungen der String-Länge herumzuschlagen.
Gruß
Werner
-
Schönen Monatgmorgen Werner
Werner Salomon schrieb:
ja das wäre u.U. auch eine Lösung. Allerdings müssen ein paar Voraussetzungen erfüllt sein. Die erste ist, dass die Darstellung der verwendeten Typen in der DB und im Memory Deiner (!) Implementierung identisch sind.
Das ist gesichert. Ich habe stets eine "bticonst.h" einzubinden, in der diverse
"BTI_????" #definded sind.Die zweite ist, dass Du die Struktur so definieren musst, dass sie das gleiche 'Package' wie die DB hat. Ich vermute mal aus Deinen Ausführungen, dass das Package der DB 1 hat, also die einzelnen Variablen dicht an dicht im Speicher abgelegt sind.
Ja, genau das ist der Fall, und deswegen bin ich auch schon in die Falle getappt, als ich den Datenbuffer in eine STRUCT ( z.B 60 char 30-Name-.30Vorname) zuwies und nur den Namen haben wollte, auch den Voirnamen mitbekam

Schau einfach mal unter '#pragma pack' in Deiner Hilfe nach.
Das wird prbolematisch zu finden sein, da ich mit g++ unter Linux auf der Konsole ( SSH) arbeite.
Die union- oder auch reinterpret_cast-Lösung ist für kleinere Anwendungen einfacher; die binstream-Lösung ist flexibler und gibt Dir die Möglichkeit auf Abweichungen zwischen DB und Memory zu reagieren.
ICh bin mir noch nicht sicher ( muss es erst versuchen); ob ich mit der union -Lösung überhaupt zurecht komme:
-Die DB-Funktion erwartet die Adressse eines CHAR-Arrays[n] ( i.e. n-char ohne Punkt und Komma hintereinander weg), und leifert die Ergbnisse in selbigen zurück.
- Meine Datensatz-structur möchte ich in eine Struct legen.STRUCT TableEntry{ Name char[3], Vorname char[30], IrgendneInt BTI_INT }UNd das Ganze in die Union mit databuffer
union UNION1{ TableEntry myStruct, std::string dataBuffer } buffer;In jeden Fall empfehle ich Dir für jeden TABLE-Typ eine eigene Klasse oder Struct anzulegen, die über Get- und Set-Methoden für die einzelnen Member verfügt und einen Mechanismus, mit der ein Objekt dieses Typs aus der DB gelesen bzw. hinein geschrieben werden kann.
Ich hatte ein ähnliches PRoblem mit Java zu lösen, und habe die c++Lösung ähnlich geplant.:
- Es gibt eine Klasse btrieveClass in der allgemeine Routinen sind,
- pro Datenbank-Tabelle eine abgeleitete "aliasIrgendwas" in welcher hauptsächlich das "Datenhandling" ( das was wir gerade abhandeln) stattfindet. ( und in die ich auch GET und SET functionen packe)
- in "main" erzeuge ich nach Bedarf "ArbeitsKlassen)aliasIrgendwas hauptIrgendwas; aliasIrgendwas hilfsIrgendwas; //.... hauptIrgendwas.Name = "Name"; //..zu schreiben, als sich mit strcpy inklusiver der notwendigen Überprüfungen der String-Länge herumzuschlagen.
Genau, das macht man nur einmal tief unten im Klassen-Ursprung.
Danke,Werner, für Deine ausführliche Antwort.Das tapezieren wasr doch aufwendiger ( incl Scharnak auf und abbauen). Zur binstream -Lösung bin ich noch nicht gekommen. mache ich aber heute.
Hanns