Wie Char Array im Programmablauf füllen

Hallo zusammen,

ist es möglich ein Char Array zu deklarieren, wenn ich nur die maximalen Zeichen und maximalen Einträge bei der Deklaration kenne?

Ich möchte nämlich ein leeres Array mit 180 Einträgen a 128 Zeichen deklarieren um es im nächsten Schritt mit Daten aus einer Text Datei zu füllen. Die einzelnen Einträge sind zwischen 0 und 128 Zeichen lang.

Die Text Datei möchte ich dann nämlich in einer Schleife Zeile für Zeile auslesen um den Inhalt später in Variable[0] bis Variable[179] zu haben.

Die Arduino Referenz hilft mir für die Deklaration leider nicht.

Arrays und FOR-Schleifen
Arrays werden oft innerhalb von Schleifen bearbeitet, wobei der Schleifenzähler als Index für jedes Array-Element verwendet wird. Wenn du beispielsweise die Elemente eines Arrays über den seriellen Anschluss ausgeben möchtest, kannst du Folgendes tun:

for (byte i = 0; i < 5; i = i + 1) {
  Serial.println(myPins[i]);
}

https://www.arduino.cc/reference/de/language/variables/data-types/array/

char testarray[180] [128];

1 Like

Vielen Dank, das werde ich mal versuchen.

Das geht aber nicht auf Uno/Nano, weil es 23040 Byte RAM erfordert.

Ich nutze einen ESP32. :blush:

Scheint zu funktionieren, gibt es nun noch eine möglichkeit testarray[0] als String auszugeben und andersrum auch wieder reinzuschreiben.

Die ESPAsyncWebServer Library arbeitet nämlich nur mit Strings. Sowohl für die Templates als auch für die GET params.

Ich möchte nämlich mein testarray[0] bis testarray[180] als Platzhalter für eine Webseite nutzen. Dort habe ich auch ein Formular um später die GET Parameter auszulesen und diese wieder in meine Array zu speichern.

Am besten ohne vorher 180 * 5 Strings zu erzeugen und diese dann zu füllen.

String Teststring0;
Teststring0 = Testarray[0];
// Bloß nicht

ja gibt es.
Frage beantwortet. Punkt.

Warum machst dir keinen Testsketch um das auszuprobieren?

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

  char testarray[42][8];
  strcpy(testarray[0], "foo");

  String teststring0;
  teststring0 = testarray[0];
  Serial.println(teststring0);
}

void loop() {}

abgesehen davon, dass deine letzten Posts darauf hindeuten, dass du dich aktuell komplett verläufst...

Genau das wollte ich nicht.

Und was willst du mir jetzt damit sagen?

String test = testarray[0];
snprintf(testarray[1], 128, "%s", test.c_str()); siehe snprintf.

Konzeptionell halte ich Deinen Ansatz für unglücklich, da der ESP32 ein Dateisystem bereitstellt und man auch direkt mit String arbeiten kann. Beispiele findest Du u. a. bei Fips und eine Anleitung: Einführung zu fipsok.de.

was willst du genau?
Mach einen kompilierbaren Sketch so kurz wie möglich und beschreibe was anders sein soll.

XY Problem.
Du versuchst ein X zu lösen, hast aber ein Y Problem.
Du fragst nach Lösungen zu X, in Wirklichkeit geht es um ganz was anderes.

Sagt wer :question:

In der Lib steht

void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr);

Das ist sicher nicht meine Absicht.

Werde ich mir anschauen.

Arduino Strings soll man doch möglichst vermeiden, da diese u. a. den RAM Fragmentieren.

Die IDE meckert, dass Sie einen String erwartet, aber einen Char erhält.

String processor(const String& var)
{
  if(var == "PLATZHALTER1")
    return testarray[1];
  return String();
}
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    if (request->hasParam("test")) {
      testarray[1] = request->getParam("test")->value(); }
}
      

Richtig, für einen UNO stimmt das.

Viele mir bekannte Beispiele für den ESP32 auch von Espressiv nutzen aber hemmungslos Strings, weshalb ich das dann auch tue. Das ist kein Beweis für die Richtigkeit, aber es scheint auch keine nennenswerten Probleme zu geben.

Wenn die Funktion den Typ String hat, dann muß hinter return auch ein Wert vom Typ String stehen, sonst ist das formal falsch. Versuche mal
return String(testarray[1]);

Gut habe ich gemacht, kompiliert nun auch ohne Fehler. ESP32 crasht allerdings wenn ich die bereitgestellte Webseite aufrufe. Es ist zum Mäusemelken...

/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1442 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x40089995 on core 0

ELF file SHA256: 0000000000000000

Backtrace: 0x400889e8:0x3ffb4f00 0x40088c65:0x3ffb4f20 0x40089995:0x3ffb4f40 0x400d4035:0x3ffb4f80 0x400d40e6:0x3ffb4fa0 0x400d44ea:0x3ffb4fc0 0x400d4558:0x3ffb4ff0 0x4013bf2d:0x3ffb5010 0x4013c9c6:0x3ffb5030 0x401356d3:0x3ffb5050 0x40139f9e:0x3ffb5080 0x401275f3:0x3ffb50a0 0x40089c66:0x3ffb50d0

Dekodiert:

0x40089995: xQueueGenericReceive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c line 2038
0x400889e8: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 715
0x40088c65: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 715
0x40089995: xQueueGenericReceive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c line 2038
0x400d4035: AsyncClient::_allocate_closed_slot() at C:\Users\Daniel\Documents\Arduino\libraries\AsyncTCP\src/AsyncTCP.cpp line 1039
0x400d40e6: AsyncClient::AsyncClient(tcp_pcb*) at C:\Users\Daniel\Documents\Arduino\libraries\AsyncTCP\src/AsyncTCP.cpp line 1039
0x400d44ea: AsyncServer::_accept(tcp_pcb*, signed char) at C:\Users\Daniel\Documents\Arduino\libraries\AsyncTCP\src/AsyncTCP.cpp line 1039
0x400d4558: AsyncServer::_s_accept(void*, tcp_pcb*, signed char) at C:\Users\Daniel\Documents\Arduino\libraries\AsyncTCP\src/AsyncTCP.cpp line 1039
0x4013bf2d: tcp_process at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/core/tcp_in.c line 865 (discriminator 1)
0x4013c9c6: tcp_input at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/core/tcp_in.c line 372
0x401356d3: ip4_input at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/core/ipv4/ip4.c line 750
0x40139f9e: ethernet_input at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/netif/ethernet.c line 184
0x401275f3: tcpip_thread at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/lwip/lwip/src/api/tcpip.c line 483
0x40089c66: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 355 (discriminator 1)

Oder darf ich so nicht deklarieren?

String test[180];
test[1] = 123;

void setup () {
// Send index page to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html, processor);
  });
}

String processor(const String& var)
{
  if(var == "PLATZHALTER1")
    return test[1];
  return String();
}

Bei send_P sehe ich in der Doku: Send large webpage from PROGMEM

Das machst Du aber nicht.

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
  <title>Test</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head><body>
`PLATZHALTER1`
</body>
</html>)rawliteral";

Okay, hat sich erledigt...

index_html.ino war bei mir vorher ein extra Tab, ich habe die Datei jetzt in index_html.h umbenannt und sie inkludiert.

#include "index_html.h"

Nun funktioniert es. Aber wie kann so etwas passieren, ich meine vorher hat dies ja zu keinem Crash geführt und der Compiler hat auch nicht 'index_html' was not declared in this scope ausgespuckt.