C++ .. ne Zahl an was dranhängen

Gast #432124
Lesenswert?

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.
Gast #432187
Lesenswert?

@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);
Persönliche Seite #432209
Lesenswert?

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.
Persönliche Seite #432215
Lesenswert?

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.
Gast #432322
Lesenswert?

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?
#432389
Lesenswert?

> 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.
Gast #432534
Lesenswert?

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
#432547
Lesenswert?

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.
Gast #432577
Lesenswert?

@ 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.
Gast #432596
Lesenswert?

@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.
#432602
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren