Leidiges Thema Char und String

Hi,

ich stamme eigentlich aus der Basic-Welt. (VB, VBA und viele andere ältere Basics). Da ist und war Stringbehandlung immer ein Kinderspiel. Man hat sie einfach aneinander gehängt, abgeschnitten oder getrimmt. Alles easy.

Arduinobedingt versuche ich mich nun mit C++. Das klappte bisher ganz gut. Mit Steuerungsprogrammen. Ich habe aber dabei bisher sehr wenig Stringbehandungen und bisher keine Probleme mit den ordinären "Strings" gehabt.

Bei meinem aktuellen Projekt allerdings hatte ich nun erstmalig vermutlich irgendwelche internen Probleme. U.a. bei größerer Stringmanipulation in einer Loop. Zusammensetzung von Messwerten zu einer csv-Zeile. Also meinstring = meinstring + irgendwas. Und das waren ca. 20 einzelne Elemente, die so aneinandergehängt wurden. Das Programm ist mir nicht nachvollziehbar immer wieder mit Pointer-Fehlern abgestürzt. Zumindest habe ich die kryptischen Meldungen als das verstanden.

Bei meinen ganzen "Lesungen" habe ich viel über char und String erfahren. Aber so ganz richtig kapiere ich das nicht, wann was wie angewendet werden kann oder soll.

Meine Aufgabe ist hauptsächlich Messdaten zu csv-Logfiles zu schreiben.

In den Lesebeispielen war u.a.

1 char fileName[] = "helloworld.txt";
2 const char* ntpServer = "pool.ntp.org";
3 char* switchtext[] = {"A=off","A=on","B=off","B=on"};

Also char mit Name[ ], const char* Name (ohne Klammer) oder char* Name[ ]

Jetzt ist die Verwirrung perfekt. Ok - letztes Beispiel ist ein Array mit 4 Feldern. Ich will aber ein Text-Array mit 2x2 Feldern. Die ich mit 0,0 0,1 1,0 und 1,1 adressieren kann.

Die erste Zeile ist auch noch klar. Aber die zweite Zeile mit const char* dient auch nur für einen "Satz" ?? Wozu "const", wozu der "*"

const heißt "read only"
Und der Stern.... da frage mal dein C++ Buch nach Zeiger/Pointer

Araay[anzahl Elemente][Anzahl Elemente im Element]
Wäre ein. 2dimensionales.
Aber warum will man das für Zeichenketten?

Nein! "const steht für Konstante. Soweit bin ich schon gewesen. Und dass Konstanten "readonly " sind weiß ich auch.

Danke - für diese tolle Hilfe!

Ich weiß, was ein 2-dimensionales Array ist. Genauso eines will ich ja machen. Habe das doch wohl mehr als deutlich beschrieben.

Wenn du das nicht weißt, solltest du mal ein Lehrbuch zum Thema mehrdimensionale Arrays lesen. Da kann man tolle Sachen machen. Und bei mir ist es nur ganz einfach.
Wenn du dazu ein Beispiel hast, könntest du mir damit helfen.

Du irrst.

Literale sind konstant.
Und dann gibts da noch constexpr und consteval.

Aber als const definierte Dinge sind keinesfalls zwingend konstant.
Man darf sie nicht ändern, das heißt allerdings nicht, dass sie nicht von anderer Seite geändert werden könnten.
Aus dem Grund ist auch die Kombination aus den const und volatile Modifikatoren durchaus üblich.

Offensichtlich nicht.
Aber das schaffst Du schon.

Ich könnte es nicht besser beschreiben:

nein!

Siehe Microsoft Learn

## const-Werte

Das const-Schlüsselwort gibt an, dass der Wert einer Variablen konstant ist, und weist den Compiler an, eine Änderung des Werts durch den Programmierer zu verhindern.

Ganz doof bin ich auch nicht! Auch wenn das manche hier bei Fragestellern wie mir ja oft annehmen.

Wenn du zu meine(n) Frage(n) keine passende verständliche Erklärungen abgeben kannst, bitte ich dich, mir einfach nicht mehr zu antworten! Du bist mir jetzt schon mehrmals nur als negativ aufgefallen. :frowning:

Ich bitte dich höflich mir nicht mehr zu antworten.

Das ist richtig.

Das ist falsch!

Bedenke:
Nur weil man den Wert nicht ändern darf, muss er noch lange nicht unveränderlich sein

Ich bitte dich höflich mir nicht mehr zu antworten!

Ich habe nämlich keine Lust auf deine Antworten, die mir nie weiterhelfen und nur sinnlose Diskussionen, teil mit Streit, ereugen. Zumindest bis jetzt.

Und wenn du schon MS-Lehrbücher u.a. nicht akzeptierst oder anders interpretierst, dann ist das deine Sache. Aber ich lasse mir deine Meinung nicht aufreden, wenn ich sie für unpassend halte.

Ich habe eine relativ einfache Frage gestellt. Zu der ganzen Verwirrung mit Strings. Wenn du das nicht anfängerfreundlich und verständlich beantworten kannst, dann bleibe einfach weg.

Ich habe keine Lust bei jeder eventuellen Frage meinerseits mich mit Leuten von deinem Schlage in sinnlose Diskussionen führen zu lassen.

Also - bleib bitte weg. Auch wenn ich es dir nicht verbieten kann zu antworten.

Ich werde auf jeden Fall auf deine Antworten, egal wie sie ausfallen, nicht mehr antworten. EOD!

Im ROM als Interpreter oder später auch mit Compiler. Hat mir gute Dienste geleistet :grinning:

Ja, ich auch, ich muß Dich daher vor mir warnen :stuck_out_tongue_winking_eye:

Wenn ich mal von "unofan" auf die verwendete Hardware schließe, dann wäre mein erster Tipp, eventuell eine andere Hardware mit mehr Speicher zu nutzen. Es ist zwar grundsätzlich keine gute Lösung, ein "schlechtes" Programm durch leistungsfähigere Hardware zu retten, könnte für Dich aber eventuell der einfachere und damit schnellere Weg sein. Ich beschäftige mich in letzter Zeit mit einem ESP32, der auch per Arduino-IDE programmiert werden kann, der aber wegen des größeren Speichers unempfindlicher auf String-Objekte reagiert. Da setze ich csv-Dateien im Dateisystem des ESP32 zusammen und kopiere sie dann auf meinen FTP-Server.

Konstanter Text oder variabel?

Testprogramm
const char feldText[2][2][sizeof("Arduino") + 1] = {{"Hallo", "Welt"}, {"Arduino", "Fan"}};

void setup()
{
  Serial.begin(9600);
  Serial.println(F("\nStart"));
  Serial.print(feldText[0][0]);
  Serial.print(feldText[0][1]);
  Serial.print(feldText[1][0]);
  Serial.print(feldText[1][1]);
  Serial.println();

  char buf[(4 * sizeof("Arduino") + 1)] = {"\0"};
  snprintf(buf, sizeof(buf), "%s %s %s%s", feldText[0][0], feldText[0][1], feldText[1][0], feldText[1][1]);
  Serial.println(buf);
  snprintf(buf, sizeof(buf), "Schluß");
  Serial.println(buf);
}

void loop() {}

Betrachte das Feld als um eine Dimension für die Buchstaben größer. Du kannst auf jeden Buchstaben oder jeden Text zugreifen.

Um csv-Dateien zusammenzustellen verwende ich snprintf, da steht der formatierte Text in der Variablen buf.

Wenn Dich irgendwas davon interessiert, frage bitte, dann kann ich auch ausführlicher antworten :slightly_smiling_face:

1 Like

Strings sind nicht "ordinär" bei C / C++

Bei Basic hast du kein Problem, weil du dort einen Computer mit unendlich viel RAM zur Verfügung hast, wo die ganze Speicherverwaltung vor dir versteckt wird.

Damit man sich bei einem Arduino (mit typischerweise RAM weniger als 2048 Zeichen) damit (mit Glück) auch nicht auseinandersetzen muss, wurden String - Objekte zusätzlich zur Programmiersprache dazuerfunden. Da kannst du mit dem + Operator zaubern, der aus zwei Strings einen dritten erzeugt (falls dafür genügend Speicher vorhanden ist).
Arrays oder Zeiger auf Datenbereiche vom Typ char sind allerdings keine String-Objekte.

sieht nur einfach aus, aber das neue meinstring ist etwas anderes als das alte, und ob der Speicherplatz des alten meinstring jemals wiederverwendet werden kann, ist Glückssache.

Die Lösung ist meistens, einfach auf das + zu verzichten. Noch einfacher ist, erst gar keine String-Objekte zu verwenden. Wer sagt, dass die csv-Zeile erst zusammenkopiert werden muss, um sie hinterher mit einer print-Anweisung zu speichern?

Die subtilen Unterschiede von
const char* text1 = "Hallo";
const char text2[] = "Hallo";
sind evtl. noch gar nicht dein Problem, aber das kann zur Zeit noch keiner wissen ( nicht mal @combie :wink: )

Die Andeutung .csv sagt meiner Kristallkugel, dass du wegen einer SD-Karte sehr knapp mit RAM bist.

Du irrst!
Das ist keine Meinung, sondern Fachwissen und Kompetenz.

Das könntest du dir auch erarbeiten.
Sogar in Sachen Pointer, Strings und Arrays.

Ich lese dir dein Buch nicht vor.

Danke für die nette Antwort :slight_smile:
Ich habe mit einem Uno angefangen. Habe dann auch Nano, Micro, Leonardo benutzt. Und momentan bin ich auch beim ESP32. Wegen WLAN um meine LOGS auf einen Server zu schreiben.
[/quote]

Es ist zwar grundsätzlich keine gute Lösung, ein "schlechtes" Programm durch leistungsfähigere Hardware zu retten, könnte für Dich aber eventuell der einfachere und damit schnellere Weg sein. Ich beschäftige mich in letzter Zeit mit einem ESP32, der auch per Arduino-IDE programmiert werden kann, der aber wegen des größeren Speichers unempfindlicher auf String-Objekte reagiert. Da setze ich csv-Dateien im Dateisystem des ESP32 zusammen und kopiere sie dann auf meinen FTP-Server.

Konstante Texte = Schaltstatus Klartext wie "A= on". Und je nach gelesenem Status des jeweiligen Schalters [n] soll dann im csv-Text der passende Text stehen bzw. auch im Kontrolldisplay angezeigt werden

Das kann man natürlich mit if-Abfragen basteln. Aber da die Schalternummern und Statuswerte eh nur 0 oder 1 sind bietet sich ja ein Array für die 4 möglichen Anzeigen an. .

Da habe ich eigentlich ganz deutlich geschrieben, wo ich das Problem habe.
char oder char* oder const char* - alles in Beispielen gefunden für einfachste Texte. Und die Namen der Variable mit oder ohne "[ ]". Das ist die Verwirrung.

Ich möchte das jetzt nicht mehr wiederholen.

Hast Du mein Testprogramm getestet? Gibt es dazu Fragen?

Naja...
Mir scheint, ihm will ein 2 Dimensionales Array bauen.
Muss sich jetzt entscheiden, ob 2 dimensionales Zeigerarray oder 3 dimensionales char Array
Kann das aber nicht, weil Doku nicht lesen/verstehen wollend.

Sieht man schon hier dran:

Nix wird in C++ so adressiert.

Sagt:

E:\Programme\arduino\portable\sketchbook\sketch_feb17d\sketch_feb17d.ino:8:25: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    8 |   char* switchtext[] = {"A=off","A=on","B=off","B=on"};
      |                         ^~~~~~~

Also keine gute Idee.

Dann doch eher so:

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

  char switchtextA[2][2][6] {{"A=off","A=on"},{"B=off","B=on"}}; 
  const char * const switchtextB[2][2] {{"A=off","A=on"},{"B=off","B=on"}}; 
  
  Serial.println(switchtextA[1][0]); // sagt B=off
  Serial.println(switchtextB[1][0]); // sagt B=off
}

void loop() 
{

}

Sorry - ich hatte noch keine Gelegenheit dazu.

Alle meine Fragen habe ich konkret im ersten Post bereits geschrieben. Aber ich steige jetzt aus. Mir ist dieses Forum bzw. sind ein paar Leute hier zu nervig.

oft muss man gar nichts "zusammenbauen". Nimm die Streaming.h library und streame in dein Ziel. Das geht auch mit einer SD Karte. "Alles" wofür du print / println anwenden kannst, kannst du auch gleich streamen und sparst massig Codezeilen.

String wird "böse" wenn man konkateniert.
Mit .reserve() ist es dann wieder ungefährlich.

Da stellt sich mir jetzt die Frage: WAS genau auf welchem Microcontroller willst du machen?

Wohin kommt das CSV File? SD-Karte, Filesystem am ESP, .
wie kommst zum NTP Server, was ist da implementiert?

Hat er doch geschrieben, ist gut ausgestattet.

So wie ich das sehe , hat er einige Infos die er in einen Zeichenkette zusammenbringen will, mit einen Trennzeichen (üblich :wink: und dann die Zeile auf eine SD-Karte mit Append schreiben.

Das scheint mir das ganze Problem zu sein.

in Basic wäre das : a$ = "Bezeichnung: ;"+ bez$ + ";Wert;" + str(summe) + VBCRLF
In der nächsten Zeile wäre dann :"Schreibe a$ in die Ziel-Datei".

Gruß
Pucki