Hallo,
Eigentlich sollte es ja kein Problem sein ein String in ein Char umzuwandeln ....
Jetzt ist es aber leider etwas Schwerer ....
Es geht erstmal um den Code eines 433 MHz Senders / Emfängers
der Testcode Funktioniert ohne Probleme aber jetzt kommt der Knackpunkt
void sendMessage(String sMessage)
{
char *msg = "Testnachricht"; // this is your message to send
//char *msg;
//Serial.println("Sende: " + sMessage);
//sMessage.toCharArray(msg, sMessage.length());
//Serial.println(String(msg));
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait for message to finish
delay(200);
}
So Funktioniert es ohne Probleme
void sendMessage(String sMessage)
{
//char *msg = "Testnachricht"; // this is your message to send
char *msg;
Serial.println("Sende: " + sMessage);
sMessage.toCharArray(msg, sMessage.length());
Serial.println(String(msg));
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait for message to finish
delay(200);
}
und so nicht ;-(
ich weis das das Problem bei der Umwandlung vom String (sMessage) in die *msg variable auftritt...
Aber ich verstehe nicht warum ??!?!?!?
Ich habe dazu auch mal gleich ein Paar verständnis fragen 
- was bedeutet der * vor msg !?!?!? --> Ich dachte es wäre damit ein Char Arry ...
- was genau macht --> (uint8_t *)msg so wie ich das verstehe boxt er die msg Variable in ein INT ??!?!?!!?!?
- muss ich überhaupt den Umweg über das CharArray gehen oder kann ich da auch gleich den String reinballern ....
- oder soll ich den String vorab in ein bytearry umwandeln ?
Hilfe wäre echt super Klasse
Danke schon mal im Vorraus
In C sind Strings Null-Terminierte char Arrays. Und Array Variablen sind Zeiger auf das erste Element. Deshalb das *
Diese Library arbeitet aber mit Byte Arrays (d.h. unsigned char statt char). Deshalb der Cast. uint8_t* ist das gleiche wie byte* oder unsigned char*. Lediglich prozessor-unabhängig.
Boxing ist das nicht. Damit bezeichnet man in strikt OO Sprachen das verpacken eines primitiven Datentyps in ein Objekt.
Das hier ist absolut tödlich:
char* msg;
sMessage.toCharArray(msg, sMessage.length());
Für msg existiert kein Speicher!! Du musst du schon ein richtiges Array anlegen. Nicht nur einen Zeiger der irgendwo ins Nirwana zeigt:
char msg[20];
Nur dann existiert auch wirklich Speicher in den du was reinschreiben kannst
Noch besser ist wenn du auf String Objekte verzichtest und gleich char Arrays nimmst. Eine Funktion die einen C String als Parameter hat sieht so aus:
void sendMessage(char* sMessage)
also sollte es so klappen ?
void sendMessage(String sMessage)
{
//char *msg = "Testnachricht"; // this is your message to send
char msg[sMessage.length()];
Serial.println("Sende: " + sMessage);
sMessage.toCharArray(msg, sMessage.length());
Serial.println(String(msg));
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait for message to finish
delay(200);
}
Die Länge von Arrays muss zur Compile-Zeit bekannt sein:
char msg[20];
sMessage.toCharArray(msg, sizeof(msg));
Das ist Unsinn:
Serial.println(String(msg));
println() kann auch direkt C Strings ausgeben ohne dass du daraus ein String Objekt machst.
Und wenn es unbedingt String Objekte sein müssen:
void sendMessage(String& sMessage)
Dann wir der Parameter per Referenz und nicht als Wert übergeben, d.h. das Objekt wird nicht kopiert.
EDIT:
Es kann sein dass lokale Arrays Variabler Länge als gcc Erweiterung gehen:
Variable Length (Using the GNU Compiler Collection (GCC))
Irgendwas hatte ich da mal in Erinnerung. Standard C++ ist es aber nicht, weshalb man das leicht erst mal als falsch abtut.
Wenn es nur um das zusammensetzen verschiedener Texte geht, kannst du die "Texte" so zusammensetzen:
// Deklaration
char SenderMsg0[10];
char SenderMsg1[10];
char SenderMsg2[10];
char Sender_Msg[30];
// in der Loop oder Funktion
strcat(Sender_Msg, SenderMsg0);
strcat(Sender_Msg, SenderMsg1);
strcat(Sender_Msg, SenderMsg3);
// Sender_Msg wird dem Sender übergeben
und dann dem Sender übergeben.
Besser strncat() verwenden. Dann vermeidet man einen Puffer-Überlauf.
Serenifly:
Besser strncat() verwenden. Dann vermeidet man einen Puffer-Überlauf.
Anstatt "strcat"?
Ok, bisher hatte ich da noch kein Problem, werde es aber beherzigen.
Ich setze das ebenfalls für die Übertragung mit einem 433 MHz-TX ein, da werden verschiedene Messwerte und ein Kanalcode übertragen, das geht soweit sehr gut.
Wenn du darauf achtest dass der Puffer immer größer als die Summe der Teil-Strings ist geht das auch gut.
Pufferüberläufe sind aber eine der größten Fehlerquellen. Deshalb gibt es Funktionen wie strncpy(), strncat() und snprintf().
Serenifly:
Wenn du darauf achtest dass der Puffer immer größer als die Summe der Teil-Strings ist geht das auch gut.
Ok, bei meinem obigen Beispiel ist es ja überschaubar und sollte dann mit funktionieren.
Sind bei mir nur feste Texte bzw. Messwerte, das passt.
okay jetzt bin ich verwirrt !?!?!?!
also ich wollte das so zusammenbauen das die länge der Nachricht nicht feststeht oder bekannt ist .. (ich kenne Sie wirklich nicht) zur aktuellen Situation ist das vermutlich wirklich egal da ich nur einen Temperaturwert übermittle ... später wollte ich mehr Daten übertragen.
Beispielstring zur übertragung:
Datum Zeit | Messert | Einheit | Sensor |
oder lege ich das Char Proformer mit 500 an und muss die Nachrichtenlänge notfalls auf 500 begrenzen ?
okay das zusammenbauen der Char Arrays ist nun klar ....
aber die frage wie ich das Nachrichten Char Dimensioniere steht im raum ?
wie hat ihr das den gelöst ?
Und wenn es unbedingt String Objekte sein müssen:
Code: [Select]
void sendMessage(String& sMessage)
Dann wir der Parameter per Referenz und nicht als Wert übergeben, d.h. das Objekt wird nicht kopiert.
habe ich versucht bekomme das Programm dann aber nicht Kompeliert oder muss ich bei der Übergabe das & auch mit anhängen ?
invalid initialization of non-const reference of type 'String&' from an rvalue of type 'String'
MultiStorm:
Beispielstring zur übertragung:
Datum Zeit | Messert | Einheit | Sensor |
wie hat ihr das den gelöst ?
So wie oben beschrieben! Post #4
Dann machst du dein char eben lang genug.
So viele Werte sind das doch nicht.
Das kann man doch vorher bestimmen.
Du wirst doch wissen wie lange die Nachrichten maximal in etwa sind. Wie kommst du da auf 500 Bytes... 
Oder mache das:
w_send((uint8_t *)const_cast<char*>(msg.c_str()), strlen(msg));
Nicht getestet. Damit spart man sich diese dämliche Umwandlung. c_str() greift direkt auf das interne Array zu, aber liefert einen const Zeiger. Der const_cast castet das const weg. Dann wird der Zeiger nochmal auf byte* gecastet
muss ich bei der Übergabe das & auch mit anhängen ?
Nein. Tue dir einen Gefallen und lerne etwas C++ Grundlagen.
jupp habs umgebaut:
void sendMessage(String& sMessage)
{
//char *msg = "Testnachricht"; // this is your message to send
char msg[500];
Serial.println("Sende: " + sMessage);
sMessage.toCharArray(msg, sizeof(msg));
//Serial.println(String(msg));
vw_send((uint8_t *)msg, strlen(msg));
vw_wait_tx(); // Wait for message to finish
delay(200);
}
leider führt das & hinter String immer noch zu einem Fehler
void sendMessage(String& sMessage)
bekomme immer gesagt:
aber danke schonmal für die ganzen Lektionen !!!
invalid initialization of non-const reference of type 'String&' from an rvalue of type 'String'
Wieso 500 Bytes? Wenn du nicht viel machst, mag das ok sein, aber der UNO hat nur 2k RAM.
Wie rufst du die Funktion auf? Eigentlich sollte das gehen. Ansonsten lasse es weg. Ist zwar schöner, aber nicht essentiell.
die 500 waren nur ne schätzung .... habe es in zwischen auf 100 gesetzt
und ich habe ein Mega 
Quote
muss ich bei der Übergabe das & auch mit anhängen ?
Nein. Tue dir einen Gefallen und lerne etwas C++ Grundlagen.
Das versuche ich ja gerade ...
ich Programmiere meist in Hochsprachen wie C# oder Java und da ist das alles ein wenig anders 
Aktuell Sieht der aufruf so aus:
float temp1;
float temp2;
float temp;
temp1 = getTemp(adresseOfTopSensor1);
temp2 = getTemp(adresseOfTopSensor2);
temp = ((temp1 + temp2) / 2);
sendMessage(String(temp, 2));
wenn ich das & in im Funktionskopf weglasse läuft alles sauer ...
Wieso überhaupt die String Klasse hier? Floats lassen sich doch bequem mit dtostrf() in einen C String formatieren:
https://www.mikrocontroller.net/topic/86391
und Aktuell Sieht der String den ich mal übertragen will so aus:
(habe ihn gerade mal von der SD Karte Kopiert
14.01.2016 10:10:42|SensorValue|DS18B20|40 255 74 131 3 21 2 6|Grad|21.19
da kommen schnell mal ein paar byte zusammen 
Ich habe es mal ausprobiert. Lokale variable Arrays gehen in gcc tatsächlich:
void setup()
{
Serial.begin(9600);
String msg = "Test String";
printString(msg);
}
void loop()
{
}
void printString(String& str)
{
Serial.println(str.length());
char buffer[str.length() + 1];
Serial.println(sizeof(buffer));
str.toCharArray(buffer, sizeof(buffer));
Serial.println(buffer);
}
Das Array muss unbedingt eins größer sein als length(), damit noch Platz für den Null-Terminator ist!
Ist wie gesagt nicht Standard C++ (sondern ein Feature dass aus C90 übernommen wurde), deshalb habe ich es erst für falsch gehalten. Das +1 hattest du aber nicht.
Aber besser wäre das in Reply #12 wenn es geht...
habe das & weggelassen und alles ist schön 
Danke an dieser Stelle noch einmal für eure Hilfe 