C Frage zu Array Initialisierung mit Festtext

OP #7607204
Lesenswert?

geht das noch einfacher?

const char mjanuar[] = "Januar\n"; const char mfebruar[] = "Februar\n"; const char mmaerz[] = "Maerz\n"; const char mapril[] = "April\n";

const char * Text1[4]={mjanuar,mfebruar,mmaerz,mapril};

Ich möchte in Abhängigkeit einer Integer Variablen den Text mit einem Printf ausgeben...

(Firma: Gast) #7607208
Lesenswert?

Thorsten S. schrieb:

geht das noch einfacher?

Nicht wirklich.

Wo ist dein Problem?

Ist zwar Arduino C++, aber vielleicht kannste dir ja was abschauen.

1
#include <Streaming.h> // die Lib findest du selber ;-)
2

3
const char * Text2[]={"Januar","Februar","Maerz","April"};
4

5

6
void ausgabe(unsigned index, const char ** strField, Print &p)
7
{
8
  char buffer[20];
9
  sprintf(buffer,"Monat %s", strField[index]);
10
  p << buffer << endl;
11
}
12
void setup() 
13
{
14
  Serial.begin(9600);
15
  Serial << "Start: " << __FILE__ << endl;
16

17
  ausgabe(0,Text2,Serial);
18
  ausgabe(1,Text2,Serial);
19
  ausgabe(2,Text2,Serial);
20
}
21

22
void loop() 
23
{
24

25
}
OP #7607438
Lesenswert?

Arduino F. schrieb:

Wo ist dein Problem?

Mir fehlte etwas die Notation dafür.

Ich hatte es irgendwie so versucht:

const char Text[3]={{"Januar\n"},{"Februar\n"},{"Maerz\n"}};

Dann so:

const char Text[]={{"Januar\n"},{"Februar\n"},{"Maerz\n"}};

Dann so meine ich...

const char * Text[3]={"Januar\n","Februar\n","Maerz\n"};

Danke. Ich war mir nicht sicher, wie das am besten gehen kann, was möglich ist, auch da die Zeichenketten unterschiedliche Längen haben... Irgendwann dachte ich, es ist besser es mit einem Array von Pointern auf Zeichenketten zu versuchen, das o.g. Beispiel funktioniert ja auch, nur war meine Hoffnung das sich das noch vereinfachen lässt für die Initialisierung, und das ist ja der Fall - perfekt!

Gruß

OP #7607460
Lesenswert?

Am Rande noch,

ich habe auch noch den Fall:

typedef struct { uint8_t a :5, b :3;

}sub_t;

typedef struct { uint8_t x; uint8_t y; sub_t z[20]; }main_t;

main_t test; //Init?

bekomme ich das komplett auf allen Ebenen bei der Deklaration mit Nullen gefüllt, ähnlich wie hier:

uint8_t test1[2]={0,0};

und, wenn - dann wie? Ansonsten bleibt ja nur eine Schleife bei der Initialsierung, oder?

Oder ich mache ein Feld das genauso groß ist wie main_t, füttere das mit Nullen und mache einen Typecast, aber auch sehr unschön, zumal das sicher unter gewissen Umständen auch gut schief gehen kann...

Danke

(Firma: Gast) #7607469
Lesenswert?

Thorsten S. schrieb:

auch da die Zeichenketten unterschiedliche Längen haben...

Thorsten S. schrieb:

Ich hatte es irgendwie so versucht:

Versuchen, ist eigentlich die falsche Strategie. Ein C Grundlagenbuch auswendig zu lernen, ist deutlich erfolgversprechender.

Ich durfte das vor Jahrzehnten mal tun, und die Früchte dessen kann ich auch Heute noch ernten. Selbst wenn ich mittlerweile fast ausschließlich auf dem C++ Schiffchen fahre.

#7607473
Lesenswert?

Thorsten S. schrieb:

bekomme ich das komplett auf allen Ebenen bei der Deklaration mit Nullen gefüllt, ähnlich wie hier:

uint8_t test1[2]={0,0};

und, wenn - dann wie? Ansonsten bleibt ja nur eine Schleife bei der Initialsierung, oder?

Sollte mit einem memset(&test, 0, sizeof(test)) machbar sein.

Allerdings würde ich dir perspektivisch empfehlen, die C++-Notationen zu nutzen, anstatt das gute alte Herumgepointere. Arduino mag zwar eingeschränkt sein, was die Container betrifft auf den kleinen Controllern, aber sowas hier sollte auch als C++-Strukturdefinition gehen, glaube ich, zumindest ab C++20:

1
struct sub_t
2
{
3
   uint8_t a : 5 = 0;
4
   uint8_t b : 3 = 0;
5
};

Kann sein, dass du dafür -std=c++20 mitgeben musst.

#7607496
Lesenswert?

Der avr-gcc ist da recht unflexibel. Das direkte Anlegen eines Arrays von Strings geht nur im RAM. Im Flash muß man dazu ein zweidimensionales Array anlegen, d.h. alle Strings mit der maximal benötigten Länge. Das ist typisch aber kein Problem, da Flash ja reichlich vorhanden ist.

Hier mal ein Beispiel aus meinem Kommandoparser:

1
#define CMD_SIZE        16
2

3
typedef char cmd_str_t[CMD_SIZE];
4

5
typedef void (*func)(void);
6

7
typedef struct
8
{
9
  cmd_str_t cmd;
10
  cmd_str_t cmd_short;
11
  func func;
12
} command_t;
13

14
extern command_t const cmd_table[] PROGMEM;
15

16
command_t const cmd_table[] PROGMEM =
17
{
18
  {MODULE_CMD_INFO,          "i",   cmd_info},
19
  {MODULE_CMD_SERIALNO,      "sn",  cmd_serno},
20
  {MODULE_CMD_RESET,         "re",  cmd_reset},
21
  {MODULE_CMD_EECLEAR,       "epc", cmd_eeclear},
22
  {"", "", 0},
23
};

Die Zugriffe müssen auch abweichend vom Datasegment mit den Spezialfunktionen erfolgen (pgm_read_byte, pgm_read_word, strcmp_P usw.).

Der Keil C51 kann das deutlich besser. Da ist es kein Unterschied, ob RAM oder Flash. Das entsprechende Schlüsselwort "code", "xdata" usw. reicht für alles, was nicht im default Datasegment liegt.

#7607590
Lesenswert?

Thorsten S. schrieb:

Dann so meine ich...

const char * Text[3]={"Januar\n","Februar\n","Maerz\n"};

Das sollte gegangen sein.

Eine Zeichenkette ("Hallo") ist eigentlich nur ein const Pointer. Bei Dir also eine Liste von 3 Pointern. Lediglich bei

char myString[]="Hallo";

wird das Array myString mit den Buchstaben von "Hallo" plus abschließender 0 initialisiert. Das ist eine Sonderbehandlung, eine Vereinfachung zu

char myString[]={'H','a','l','l','o',0};

Darum geht auch {"Hallo"} nicht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren