Bytewert in String bzw Zeichen umwandeln

Webdesign, Programmierung, PC-Hardware und allgemeine Computerprobleme.

Moderatoren: MaxZ, ebastler, SeriousD

Antworten
Benutzeravatar

Thread-Ersteller
L_B_S
Beiträge: 543
Registriert: Fr 24. Jul 2015, 10:13
Schule/Uni/Arbeit: KFZ-Elktr.
Hat sich bedankt: 23 Mal
Danksagung erhalten: 23 Mal

Bytewert in String bzw Zeichen umwandeln

Beitrag von L_B_S »

Hallo zusammen,
Es soll ein Bytewert in einen String umgewandelt werden.
In diesem Beispielcode der Bytewert 65 in den String bzw. Zeichen 'A'

mit dem nachfolgenden Code klappt es natürlich nicht. Der Bytewert wird hier in die Zeichenkette "65" umgewandelt.

Code: Alles auswählen

byte Wert = 65;    // entspricht ANSI-Code 65 = 'A'
String Zeichen;

void setup() {
}

void loop() {
     Zeichen = String(Wert);
}
Es sollte aber "A" sein. Ich hab im Netz und in der Referenz mal nachgesehen aber nicht so wirklich einfache Beispiele gefunden.

So etwas wie: Integer in String umwandeln mit itoa (integer to array) gibt es ja aber das sollte etwa analog (als Beispiel) wie Serial.write(val); funktionieren.
Dort wird ja ein Wert als einzelnes Byte (= 65) und nicht wie mit Serial.print(val); als Zeichenkette (= "65") gesendet.
Hat jemand da eventuell einen Vorschlag ?

Gruss
Ludwig
Benutzeravatar

VDX
Beiträge: 1994
Registriert: Fr 13. Jul 2018, 18:23
Spezialgebiet: Laser und Mikro-/Nanotechnik
Hat sich bedankt: 11 Mal
Danksagung erhalten: 207 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von VDX »

... schau mal in die Beschreibung von printf() oder fprintf() - z.B. sowas:
int i = 0x65;
char x = i;

fprintf( stdout, "%c", x );
Viktor
Aufruf zum Projekt "Müll-freie Meere" - https://reprap.org/forum/list.php?426 -- Facebook-Gruppe - https://www.facebook.com/groups/383822522290730
Call for the project "garbage-free seas" - https://reprap.org/forum/list.php?425
Benutzeravatar

Thread-Ersteller
L_B_S
Beiträge: 543
Registriert: Fr 24. Jul 2015, 10:13
Schule/Uni/Arbeit: KFZ-Elktr.
Hat sich bedankt: 23 Mal
Danksagung erhalten: 23 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von L_B_S »

Danke an VDX,
sehr hilfreicher Tip . Ich wusste noch nicht , dass es so etwas gibt. Im Netz gib's auch Menge darüber zu lesen.

Gruss
Ludwig

Nachtrag..... hatte ich noch vergessen zu fragen...

die Ausgabe mit printf() in der Form funkt prima, wird jedenfalls nicht vom Compiler angemeckert

Code: Alles auswählen

'
String Zeichen;
int i = 0x65;
byte x = 0x65;  // entspricht ANSI-Code 65 = 'A

void setup() {
}

void loop() {
char c = i;     
printf( "%c", 0x65 );
printf( "%c", x );
printf( "%c", c );
}
ich weiss nur nicht, wie ich den "formatierten" Byte Wert in die Variable Zeichen "reinbekomme"
Ich möchte die Ausgabe mit printf() nicht auf einem Bildschirm sondern zB. auf einem LCD-Display
Benutzeravatar

Alexander470815
Beiträge: 1968
Registriert: Mi 14. Jul 2010, 22:00
Spezialgebiet: Kältetechnik, Frequenzumrichter, E-bikes
Wohnort: D:\Hessen\Gießen
Hat sich bedankt: 32 Mal
Danksagung erhalten: 134 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von Alexander470815 »

Dann nimm eben sprintf und schreibe das in einen String.
Ggf. snprintf wenn man verhindern will das über das Ende hinweg geschrieben wird.
Den String sendet man dann an das LCD, da kommt es natürlich immer auf die Bibliothek an die man nutzt.
Benutzeravatar

MaxZ
Beiträge: 1168
Registriert: So 28. Jun 2015, 10:20
Schule/Uni/Arbeit: Mechatronik, Karlsruher Institut für Technologie
Wohnort: Luxemburg / Karlsruhe
Hat sich bedankt: 261 Mal
Danksagung erhalten: 160 Mal
Kontaktdaten:

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von MaxZ »

Moin,


Diese "Umwandlung" ist nur Formsache. Ob dieser Platz im Speicher jetzt Teil eines Strings ist oder eines ints, letztendlich sind genau die gleichen Bits gesetzt. Deswegen funktioniert auch "Serial.write" - der Wert 65 (nicht der String "65") wird nämlich als 'A' interpretiert - ohne Konvertierung oder sonst was.
Der Umweg über printf und ähnliches ist daher mit Kanonen auf Spatzen geschossen.

Ignorieren wir mal für eine Sekunde Arduino String und schauen uns stattdessen die primitivere Form, ein char Array an. Folgende Zeilen sind allesamt äquivalent; sie bedeuten exakt das gleiche, nur anders geschrieben.

Code: Alles auswählen

char someText[12] = "Hello World";

byte someText[12] = "Hello World";

byte someText[12] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0x00};

byte someText[12] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00};
Wenn also Buchstaben und Zahlen exakt das gleiche sind, wie können sie unterschieden werden? Wie kann Arduino String() dazwischen unterscheiden? Ganz einfach, String, und so ziemlich alles andere geht davon aus, dass wenn es sich um ein Array von bytes handelt, dass es dann Text darstellen soll. Ein byte (kein Array), ein int, ein int Array, etc wird dagegen nicht so gedeutet. Weiteres wichtiges Merkmal: es ist Konvention, dass ein char Array mit einem Null byte endet. Da Arrays in C/C++ nicht wissen (können) wie groß sie sind, können Funktionen wie *.print so - und nur so - ganz leicht herausfinden, wo der Text zu Ende ist. Nutzt man "abcd" zum anlegen eines char Array, wird die Null automatisch hinzugefügt. Ansonsten muss man sie - wie oben gezeigt - selbst anhängen.
Anmerkung: Falls du dich gewundert hast, was der Unterschied zwischen 'a' und "a" ist, die Antwort lautet, 'a' ist ein einzelnes byte mit dem ASCII Code des Zeichens a. "a" ist ein char Array mit einem byte für das Zeichen a und einem Null byte. Entsprechend ist "abc" möglich, 'abc' jedoch nicht.

Was bedeutet das alles? Nun, deine Frage läuft letztendlich auf die Frage hinaus, wie du ein byte in ein byte Array umwandeln und mit einer angehängten Null versehen kannst. Antwort: z.B. so:

Code: Alles auswählen

byte someLetter = 'A'; // Äquivalent zu ... = 65;
char someText[2] = "x";
someText[0] = someLetter;
Anschließend funktioniert auch das Erstellen eines Arduino Strings:

Code: Alles auswählen

String s = String(someText);

Nachtrag zur Antwort von @Alexander470815: Wenn es schon eine so komplexe Funktion wie *printf sein muss, dann immer snprintf nehmen. Es ist eigentlich nie erwünscht, dass das Ergebnis zu groß werden kann, und dann andere Variablen im Speicher überschreibt.

Hoffe das hilft!
Max
Benutzeravatar

Thread-Ersteller
L_B_S
Beiträge: 543
Registriert: Fr 24. Jul 2015, 10:13
Schule/Uni/Arbeit: KFZ-Elktr.
Hat sich bedankt: 23 Mal
Danksagung erhalten: 23 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von L_B_S »

Dank für die Antworten,

@Max
dein Code in dieser Form:

Code: Alles auswählen

byte someLetter = 'A'; // Äquivalent zu ... = 65;
char someText[2] = "x";
someText[0] = someLetter;

void setup() {
}

void loop() {
        String s = String(someText);
}
funkt leider nicht

Fehlermeldung vom Compiler:

Code: Alles auswählen

Arduino: 1.8.7 (Windows XP), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

Byte_in_String_Konvertieren_Test_Max:4:1: error: 'someText' does not name a type

exit status 1
'someText' does not name a type
hab mir statt dessen mal einen "Workaround" gebastelt und in die eigene Funktion ByteToString(byte byt) gepackt

Code: Alles auswählen

byte i;

void setup() {
     Serial.begin(9600);
}

void loop() {
     for (i = 33; i < 123; i++){   
        
         Serial.print("Dez.-Wert ");
         Serial.print(i);
         Serial.print(" = Zeichen ");
         Serial.println(ByteToString(i));
         delay(300);
         }
}

String ByteToString(byte byt)
{
     byte Wert[] = {byt};
     String Zeichen;
     Zeichen = String((char *)Wert); 
     return Zeichen; 
}
nicht so elegant aber funktioniert

@Alexander
Dann nimm eben sprintf und schreibe das in einen String.
Genau das ist das Problem, was ich habe. Im Netz habe ich dazu einige Erklärungen gefunden https://www.tutorialspoint.com/c_standa ... printf.htm
kann aber nicht so recht was damit anfangen, zB hier mit

Code: Alles auswählen

#include <stdio.h>
#include <math.h>

int main () {
   char str[80];

   sprintf(str, "Value of Pi = %f", M_PI);
   puts(str);
   
   return(0);
}
Benutzeravatar

Thread-Ersteller
L_B_S
Beiträge: 543
Registriert: Fr 24. Jul 2015, 10:13
Schule/Uni/Arbeit: KFZ-Elktr.
Hat sich bedankt: 23 Mal
Danksagung erhalten: 23 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von L_B_S »

@Max

sorry Max. Dein Code funkt.

Code: Alles auswählen

someText[0] = someLetter;
darf nicht vor void setup stehen
so geht'S

Code: Alles auswählen

byte someLetter = 'A'; // Äquivalent zu ... = 65;
char someText[2] = "x";


void setup() {
  someText[0] = someLetter;
}

void loop() {
        String s = String(someText);
}
Benutzeravatar

MaxZ
Beiträge: 1168
Registriert: So 28. Jun 2015, 10:20
Schule/Uni/Arbeit: Mechatronik, Karlsruher Institut für Technologie
Wohnort: Luxemburg / Karlsruhe
Hat sich bedankt: 261 Mal
Danksagung erhalten: 160 Mal
Kontaktdaten:

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von MaxZ »

Ich wollte dir das gerade schreiben. Muss auch nicht in setup stehen, sondern kann in einer beliebigen Funktion stehen.

Deine Lösung macht quasi das gleiche wie mein Vorschlag, mit einem Problem: du wandelst das byte zwar in einen char Array um, jedoch ohne das obligatorische Null byte am Ende. Du müsstest also zumindest "byte Wert = {byt, 0};" schreiben. Ansonsten wird String() (und jede andere Funktion) nicht wissen, wo die Zeichenkette aufhört, und liest so lange weitere Werte aus dem Speicher aus, bis es auf eine Null trifft.

Weitere Anmerkung: der Cast zu (char *) sollte nicht notwendig sein. Falls bei Arduino byte und char nicht ohnehin das gleiche ist, kannst du in den Zeilen darüber auch einfach statt "byte Wert" "char Wert" schreiben, dann ist der Cast nämlich ganz sicher nicht mehr notwendig.


Liebe Grüße,
Max
Benutzeravatar

MaxZ
Beiträge: 1168
Registriert: So 28. Jun 2015, 10:20
Schule/Uni/Arbeit: Mechatronik, Karlsruher Institut für Technologie
Wohnort: Luxemburg / Karlsruhe
Hat sich bedankt: 261 Mal
Danksagung erhalten: 160 Mal
Kontaktdaten:

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von MaxZ »

Nachtrag zu deiner Frage zu snprintf: Die Funktion ist hier recht gut dokumentiert: https://cplusplus.com/reference/cstdio/snprintf/
Du musst ihr etwas mehr übergeben, als das was du in deinem Beispiel hast. Insbesondere musst du vor dem Aufruf schon ein char Array angelegt haben, in welches das Ergebnis geschrieben werden soll. Das ist vermutlich etwas ungewohnt, da eine Funktion üblicherweise das Ergebnis zurückliefert, statt es in eine bestehende Variable/Array zu schreiben, ist bei Arrays aber üblich (wegen der Art wie Arrays in C/C++ umgesetzt sind, kann man sie nicht wirklich mit "return array" zurückgeben).
Neben dem was in deinem Code steht musst du also noch ein Array und dessen Größe an snprintf übergeben. Letzteres ist übrigens der Unterschied zwischen sprintf und snprinft. Ersterem ist egal wie groß das Array für das Ergebnis ist. Wenn das Ergebnis zu groß ist, wird es trotzdem komplett geschrieben, und schießt dir damit andere Teile des Programmes ab. snprintf hört dagegen auf, wenn es die genannte Länge erreicht hat. Deswegen nur snprintf verwenden.
Im Anschluss kannst du das Array, welches nun die gewünschte Zeichenkette enthält, beliebig weiterverwenden. Sei es mit lcd.write(...), Serial.print(...), oder einfach nur String(...).

Liebe Grüße,
Max
Benutzeravatar

Thread-Ersteller
L_B_S
Beiträge: 543
Registriert: Fr 24. Jul 2015, 10:13
Schule/Uni/Arbeit: KFZ-Elktr.
Hat sich bedankt: 23 Mal
Danksagung erhalten: 23 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von L_B_S »

Hallo max,
du schriebst:
du wandelst das byte zwar in einen char Array um, jedoch ohne das obligatorische Null byte am Ende. Du müsstest also zumindest "byte Wert = {byt, 0};" schreiben. Ansonsten wird String() (und jede andere Funktion) nicht wissen, wo die Zeichenkette aufhört, und liest so lange weitere Werte aus dem Speicher aus, bis es auf eine Null trifft.
also das steht in der Referenz
Text-Strings können auf zwei Arten gebildet werden:
1. Man kann den Datentyp „String“ (String-Object) verwenden.
2. Man bildet ein Array von Typ „char“. Dieses muß mit einem Null-Terminator beendet werden. Das macht der Compiler entweder selbst (unteres Beispiel Str2), oder man hängt diese ‚\0‘ selbst an (Beispiel Str3). Hier geht es um das Array vom Typ char.

Code: Alles auswählen

char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o',};
char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'};
es sieht bei mir so aus, als ob der Compiler bei mir das selbst macht. Ich kann meine Funktion auch sicherheitshalber so :

Code: Alles auswählen

byte Wert[] = {byt,0};
abändern.

Gruss
Ludwig
Benutzeravatar

MaxZ
Beiträge: 1168
Registriert: So 28. Jun 2015, 10:20
Schule/Uni/Arbeit: Mechatronik, Karlsruher Institut für Technologie
Wohnort: Luxemburg / Karlsruhe
Hat sich bedankt: 261 Mal
Danksagung erhalten: 160 Mal
Kontaktdaten:

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von MaxZ »

Offen gestanden hatte ich den Grund, weshalb das zitierte Beispiel funktioniert, beim Schreiben meiner vorherigen Beiträge vergessen. Es gibt bei deinem Code dennoch ein Problem.

Es ist in C/C++ so, dass jeder Speicher, der einer Variable zugewiesen wird, auf Null initialisiert wird. Wenn du also char Str2[8] schreibst, werden 8 bytes des Speichers für Str2 vorgesehen und auf Null gesetzt. Schreibst du nun nur 7 oder weniger Buchstaben in Str2, so hast du im Ergebnis einen Null-terminierten String. Der Compiler fügt, bei der Array Schreibweise {..., ...} mWn keine Elemente automatisch hinzu; bei keinem Datentyp. Der "string", den du auf die gezeigte Art in Str2 schreibst, ist für sich genommen also "fehlerhaft" (nicht null-terminiert), und wird erst dadurch brauchbar, dass Str2 erstens größer ist und zweitens davor auf Null initialisiert wurde.

In deinem abgewandelten Beispiel hast du gar keine Größe für dein byte Array gesetzt. Die Größe muss also automatisch bestimmt werden aufgrund dessen, was du dem Array zuweisen möchtest. Und dort steht ein Array mit genau einem Element. Entsprechend wird für "Wert" auch nur 1 Byte vorgesehen. Willst du, dass der Trick von oben funktioniert, musst du es explizit als byte Wert[2] = {byt}; schreiben - oder eben byte Wert[] = {byt, 0};. Nur dann wird das nötige, zusätzliche byte im Speicher reserviert und auf Null gesetzt.

Ich persönlich bin kein Freund davon, auf diese automatische Null-Initialisierung zu vertrauen. Ich bevorzuge es, meine Variablen explizit auf die Werte zu initialisieren, die sie haben sollen. In dem Sinne finde ich byte Wert[] = {byt, 0}; (Absicht deutlich, ich will ne Null anfügen) auch klarer und verständlicher als byte Wert[2] = {byt}; (Absicht unklar; ich nutze mein Array nicht komplett).


Viele Grüße,
Max
Benutzeravatar

Thread-Ersteller
L_B_S
Beiträge: 543
Registriert: Fr 24. Jul 2015, 10:13
Schule/Uni/Arbeit: KFZ-Elktr.
Hat sich bedankt: 23 Mal
Danksagung erhalten: 23 Mal

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von L_B_S »

Wenn ich das richtig verstanden habe,
Wenn du also char Str2[8] schreibst, werden 8 bytes des Speichers für Str2 vorgesehen und auf Null gesetzt
wäre also:

Code: Alles auswählen

byte Str2[8];
absolut identisch mit

Code: Alles auswählen

byte Str2[] = {0,0,0,0,0,0,0,0};
richtig ?

Und wenn ich es so schreiben würde:

Code: Alles auswählen

byte Str2[] = {60,60,60,60,60,60,60,60};
wäre das Array also NICHT Null-terminiert, richtig ?
Benutzeravatar

MaxZ
Beiträge: 1168
Registriert: So 28. Jun 2015, 10:20
Schule/Uni/Arbeit: Mechatronik, Karlsruher Institut für Technologie
Wohnort: Luxemburg / Karlsruhe
Hat sich bedankt: 261 Mal
Danksagung erhalten: 160 Mal
Kontaktdaten:

Re: Bytewert in String bzw Zeichen umwandeln

Beitrag von MaxZ »

Sofern ich nicht was grundlegend falsch verstanden habe, ja. Genau richtig.

Liebe Grüße,
Max
Antworten