mikrocontroller.net

Forum: PC-Programmierung C++ .. ne Zahl an was dranhängen


Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: SiO2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
strcp() oder so aehnlich sollte gehen.

Autor: Thomas B. (yahp) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Thomas B. (yahp) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mist schon wieder falsch kopiert!!! Soll heißen:

  string strData;
  stringstream dataStream;

  dataStream << "\\0sMI \\3 \\5" << LEDNr;

  strData = dataStream.str();

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ernst

danke, aber leider weiss ich jetzt nicht was ich machen soll, wie kann 
ich sprintf trotzdem verwenden?

grüße Nils

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 */

Autor: Thomas B. (yahp) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;-)

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ernst:

also version 1:

error C2440: 'static_cast' : cannot convert from 'BYTE *' to 'char *'

und bei version2 klappts, danke

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nils wrote:

> error C2440: 'static_cast' : cannot convert from 'BYTE *' to 'char *'

Das darf eigentlich nicht sein, wie ist den dein "BYTE" deklariert?

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Nils (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok habs:

//windef.h
typedef unsigned char       BYTE;

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.