Hallo zusammen, ich habe folgende Funktion: void usbInterface_LPC2148::methodSwitchLEDOn ( int LEDNr ) { BYTE datagram[16]; memcpy( datagram, ("\0sMI \3 \5"), 16 ); usbInterface::write( datagram ); } jetzt würde ich gerne da wo die \5 steht, den inhalt der LEDNr variable haben. wie bau ich das da noch dran memcpy( datagram, ("\0sMI \3 "+LEDNr), 16 ); geht leider nicht, ich denke da werden dann wohl die zahlen zusammenaddiert oder sowas.
datagram[x] = LEDNr; x ist durch Auszählen zu bestimmen. Das ganze muss natürlich nach dem memcpy geschehen und geht nur, wenn die Position fest ist, also der String davor unveränderlich.
@Thomas B. Bitte????? Ich gehe mal davon aus, dass der int-Wert LEDNr in einen String gewandelt werden soll. Dazu gibt es in C++ Stringstreams. Nach alter C-Sitte könntest du es auch mit sprintf machen: sprintf(datagramm, "\0sMI \3 %u", LEDNr);
Hat sich eigentlich schon mal jemand diese merkwürdige Stringkonstante näher angesehen, die da per memcpy kopiert werden soll? Die ist, wenn ich mich nicht völlig verzähle, gerade mal 8 Bytes lang; memcpy wird aber angewiesen, 16 Bytes zu kopieren. Als Argument für sprintf eignet sich dieser String gar nicht, da die \0 als erstes Zeichen den String bereits terminiert, sprintf also die Formatanweisung nicht versteht. Aber selbst wenn es das täte, wäre die Formatanweisung fehlerhaft, anstelle %u müsste schon %c verwendet werden.
Danke! Datagramm ist kein String, sondern ein Array von chars. Da macht sprintf wenig Sinn. Die LED Nummer ist im obigen Beispiel mit einem Backslash geschrieben, d. h. es ist offenbar gerade keine literale Interpretation der LED Nummer gewünscht, sondern der Wert selbst (obwohl \ mit dezimaler Notation eigentlich nicht auftreten dürfte). Wenn er ein Backslash übertragen will, müsste er es im String doppelt schreiben. Davon abgesehen kann man natürlich erstmal einen String bauen, in dem alles sauber drinn steht - dort kann man dann auch mit sprintf operieren - und danach alles nach Datagramm kopieren. Ist die sauberste, wartbarste, zur Laufzeit vermutlich uneffizientest und "hochsprachlichste" Lösung. Punkt 1 ist aber die Klärung, wie die Zahl dort gewünscht wird, in ASCII Repräsentation oder nicht.
Richtig! Ich habe die \\ beim kopieren vergessen. Warum aber der Integer LEDNr durch sprintf als char interpretiert werden soll ist mir ein Rätsel??? ! Kann natürlich so sein, ist aber genau so unwahrscheinlich (oder wahrscheinlich) wie %u oder %d In C gibt es keinen String-Datentyp sondern Strings werden als Arrays von chars dargestellt... (aber das wisst ihr ja eh beide) deshalb noch mehr???? von mir.... Und ob man in einem C++ Programm ohne Not mit memcpy rumeiern sollte darf zumindest in Frage gestellt werden. Wenn ich schon C++ verwende, dann kann ich ja deren Mechanismen verwenden, oder (stringstreams eben)?! string strData(dataStream.str()); stringstream dataStream; dataStream << "\\0sMI \\3 \\5" << LEDNr; strData = dataStream.str(); Wobei write ja nun auch noch irgend wo her wissen muss, wie groß das datagramm ist oder?
Mist schon wieder falsch kopiert!!! Soll heißen: string strData; stringstream dataStream; dataStream << "\\0sMI \\3 \\5" << LEDNr; strData = dataStream.str();
> Warum aber der Integer LEDNr durch sprintf als char interpretiert > werden soll ist mir ein Rätsel??? ! Oh. Das muss es nicht. Auch ein char ist letztendlich ein skalarer Typ, der eine ganze Zahl repräsentiert. Der wichtiste Unterschied (neben seiner Größe) besteht darin, dass char und int während Ausgaben / Eingaben (und natürlich bei der damit zusammenhängenden Formatierung) anders behandelt werden. Während bei einem int durch Verwendung von %d oder %u oder ... eine Konvertierung der Zahl in eine ASCII Repräsentierung erzwungen wird, wird bei der Ausgabe als char, erzwungen durch %c, der int direkt, quasi binär, in den Ausgabestream eingefügt. > Kann natürlich so sein, ist aber genau so unwahrscheinlich (oder > wahrscheinlich) wie %u oder %d Nö. Das ist tatsächlich so. Zum Rest kann ich nichts sagen, da mir immer noch unklar ist, wie denn das Ergebnis auf Byteebene aussehen soll. Der springende Punkt ist immer noch der: Soll die LedNr als ASCII-Repräsentierung der Zahl eingebaut sein oder soll im Datagramm der binäre Wert der LedNr auftauchen.
Hallo zusammen, danke, dass ihr euch so viele Gedanken zu meiner Frage gemacht habt. Das was übertragen werden soll ich tatsächlich 5 und nicht der ASCII Code von 5. Im Moment mache ich das zwar noch in einem C++ Programm, aber irgendwann soll ein LPC2148 das ganze auch sprechen. Diese komische Zeichenfolge gehört zu einem Protokoll, dass ich implementieren will. Es geht immer mit 0 los (für USB), dann kommt ein s und dann (M)ethod (i)nitialisierung, dann die nummer der funktion die aufgerufen werden soll und dann die Parameter. Im Moment hat das Board, was ich verwende 8 LEDs also die Frage ob dezimal oder hexadezimal war noch gar nicht relevant. Ich werde jetzt mal versuchen, mir nen schönen String vorher zu bauen und den dann mit memcpy reinzuschreiben. grüße Nils
Wenn ich was vorschlagen darf: Denk dir für die binäre \0 was anderes aus. Irgendwann benutzt du string Funktionen dafür, warum auch nicht, und dann ist dir diese \0 ewig im Weg. Du könntest zb folgendes machen: #define SET_LED_FUNCTION 3 void usbInterface_LPC2148::methodSwitchLEDOn ( int LEDNr ) { BYTE datagram[16]; sprintf( datagram, "%csMI%c%c", '\0', SET_LED_FUNCTION, LedNr ); usbInterface::write( datagram ); } Das zusätzliche Argument '\0' zu sprintf ist zb. nur deswegen notwendig, weil du '\0' so nicht in den Format-String einbauen kannst. Wenn du auf die str... Familie verzichten willst, dann musst du selbst auf die Längen acht geben. So was wie: memcpy( datagram, ("\0sMI \3 \5"), 16 ); ist kein Kavaliersdelikt! Der String "\0sMI \3 \5" ist nun mal keine 16 Zeichen lang. Genau genommen, hat er als String eine Länge von 0 Bytes (wieder: wegen dem \0 da ganz am Anfang). Man könnte auch argumentieren, dass er ein deklarierte Länge von 9 Bytes besitzt. Wie auch immer: Er ist auf jeden Fall keine 16 Bytes lang.
Ne das mit der 0 weglassen geht nicht, da das fest im USB Protokoll drin ist. Ich könnte Sie natürlich erst in der write Funktion, die ich geschrieben habe einbauen.
@ Karl heinz Buchegger " > Kann natürlich so sein, ist aber genau so unwahrscheinlich (oder > wahrscheinlich) wie %u oder %d Nö. Das ist tatsächlich so. Zum Rest kann ich nichts sagen, da mir immer noch unklar ist, wie denn das Ergebnis auf Byteebene aussehen soll. Der springende Punkt ist immer noch der: Soll die LedNr als ASCII-Repräsentierung der Zahl eingebaut sein oder soll im Datagramm der binäre Wert der LedNr auftauchen. " Ich glaube, da haben wir an einander vorbei geredet. Weil mit meiner Aussage nichts anderes ausdrücken wollte, als das was dein springender Punkt ist. Deinem zweiten Posting stimme ich im Übrigen uneingeschränkt zu.
@Karl Heinz: Danke schonmal, aber leider bekomme ich folgende Fehlermeldung: error C2664: 'sprintf' : cannot convert parameter 1 from 'BYTE *' to 'char *' und das bei diesem code: void usbInterface_LPC2148::methodSwitchLEDOn ( int LEDNr ) { BYTE* datagram = new BYTE[Capabilities.OutputReportByteLength]; sprintf( datagram, "%csMI%c%c", '\0', METHOD_SET_LED, LEDNr ); usbInterface::write( datagram ); } woran liegt das denn ? #define METHOD_SET_LED 3 hab ich auch drüber stehen.
sprintf will als ersten parameter einen char *, du gibst ihm einen BYTE *. BYTE ist bei dir warscheinlich ein typedef auf unsigned char... Wobei ich immer noch nicht verstehe, warum sich JEDER eigene Typedefs für solche int-Datentypen baut, wo's doch mit #include <stdint.h> schöne, standartisierte gibt, z.B. uint8_t, int8_t, int32_t usw... /Ernst
@ernst danke, aber leider weiss ich jetzt nicht was ich machen soll, wie kann ich sprintf trotzdem verwenden? grüße Nils
sprintf( static_cast<char *>(datagram), "%csMI%c%c", '\0', METHOD_SET_LED, LEDNr ); // C++ style cast oder sprintf( (char *)datagram, "%csMI%c%c", '\0', METHOD_SET_LED, LEDNr ); /* C style cast */
Na, du könntest direkt in dem sprintf-Aufruf datagramm auf char* casten. Allerdings nur, wenn du dir sicher bist, da die Datentypen soweit kompatibel sind, dass nix passiert. Ansonsten wäre zu empfehlen, diese PASCAL-Style Typedefs nicht zu verwenden ;-)
@ernst: also version 1: error C2440: 'static_cast' : cannot convert from 'BYTE *' to 'char *' und bei version2 klappts, danke
Nils wrote:
> error C2440: 'static_cast' : cannot convert from 'BYTE *' to 'char *'
Das darf eigentlich nicht sein, wie ist den dein "BYTE" deklariert?
@ernst: Oje, da fragst du mich was, ich bin leider (halb) blutiger Anfänger, wenn du mir sagt wie ich das rausfinde, dann schau ich nach.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.