Go Down

Topic: byte + string in ein array? (Read 497 times) previous topic - next topic

Whandall

Gemeinsame Namensbestandteile wie AlarmValue und Alarm Name,
sind ein Hinweis auf einen Zusammenhang, der nach einem Objekt schreit,
genauso wie numerierte Variablen nach einem Array rufen.

Wenn ich AlarmValue und AlarmName nacheinander deklariere, stehen sie auch zusammen.
Die Arrays stehen hintereinander und der Name von Element 0 steht so weit von seinem Wert weg,
wie es initialisierte Einträge gibt.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

combie

#16
Jun 19, 2017, 09:23 pm Last Edit: Jun 19, 2017, 09:41 pm by combie
Quote
Wenn ich mich auf #7 beziehe, braucht man Alarm, value und name, ich würde mit AlarmValue und AlarmName auskommen.
Hier mal ein einfaches Beispiel.
(den foreach könnte man mit C++11 Mitteln auch anders schreiben)
Code: [Select]


#define CountArray(array) (sizeof(array)/sizeof(array[0])
#define ForEach(array,var) for(int var=0;var<CountArray(array));var++)

#define Halt for(;;)

struct Person
{
  int gebutsjahr;
  char name[20];
  void print(Print &printer)
  {
    printer.print("Name: ");
    printer.println(name);
    printer.print("Geboren: ");
    printer.println(gebutsjahr);
  }  
};

Person Belegschaft[]
{
  {1970,"Walter"},
  {1744,"Egon"},
  {2001,"Charly"},
};

void setup()
{
  Serial.begin(9600);
  Serial.println("Start");
  Serial.println();
}

void loop()
{
  ForEach(Belegschaft,i)
  {
    if(i) Serial.println("---");
    Belegschaft[i].print(Serial);
  }
  Serial.println();
  Serial.println("Ende");
  Halt;
}
Ob ein Mensch ein Gentleman ist,
erkennt man an seinem Benehmen denjenigen Menschen gegenüber,
von denen er keinen Nutzen hat.
Autor: William Lyon Phelps

Serenifly

Ist zwar Off Topic, aber auf dem Arduino gibt es ein Printable Interface mit einer PrintTo(Print& p) Methode. Damit kann man dann das Objekt direkt an print() übergeben. Damit könntest du also "Serial.print(Belegschaft[index])" schreiben

Aber das Prinzip ist das gleiche. structs sind in C++ sehr, sehr eng mit Klassen verwandt. Sie können also Dinge wie Konstruktoren, Methoden und Vererbung enthalten.

Whandall

structs sind in C++ sehr, sehr eng mit Klassen verwandt.
Meiner Ansicht nach ist struct eine class mit impliziter public: Instruktion.

Code: [Select]
struct ZombieS {
  // Member und Methoden
};

class ZombieC {
public:
  // Member und Methoden
};
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Serenifly


Whandall

Na ja, wir sind ja auch alle sehr, sehr eng mit uns selbst verwandt.  ;)
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

combie

Ist zwar Off Topic, aber auf dem Arduino gibt es ein Printable Interface mit einer PrintTo(Print& p) Methode. Damit kann man dann das Objekt direkt an print() übergeben. Damit könntest du also "Serial.print(Belegschaft[index])" schreiben
Tja, damit habe ich es schon mal versucht...
Ist mir nicht gelungen.

Würde mich über eine Vorführung sehr freuen!
Ob ein Mensch ein Gentleman ist,
erkennt man an seinem Benehmen denjenigen Menschen gegenüber,
von denen er keinen Nutzen hat.
Autor: William Lyon Phelps

Serenifly

#22
Jun 20, 2017, 12:30 am Last Edit: Jul 21, 2017, 01:23 pm by Serenifly
Braucht nun allerdings leider auch einen Konstruktor weil es durch die Vererbung und virtuelle Methode nicht mehr eine einfache Aggregation ist:

Code: [Select]

struct Person : Printable
{
  unsigned int geburtsjahr;
  char name[20];

  Person(unsigned int geburtsjahr, const char* name) : geburtsjahr(geburtsjahr)
  {
    strlcpy(this->name, name, sizeof(this->name));
  }

  size_t printTo(Print &printer) const
  {
    size_t len = printer.print("Name: ");
    len += printer.println(name);
    len += printer.print("Geboren: ");
    len += printer.println(geburtsjahr);
    return len;
  }
};


Code: [Select]

ForEach(Belegschaft, i)
{
  if (i) Serial.println("---");
    Serial.print(Belegschaft[i]);
}


Was dann abläuft ist dass es eine Variante von print() gibt die eine Referenz auf Printable als Parameter hat. Diese ruft dann die definierte printTo() Method auf und übergibt dabei das Print Objekt.

EDIT: Rückgabwert entsprechend #23 ausgebessert

Whandall

#23
Jun 20, 2017, 12:56 am Last Edit: Jun 20, 2017, 12:57 am by Whandall
Code: [Select]
 size_t printTo(Print &printer) const
  {
    printer.print("Name: ");
    printer.println(name);
    printer.print("Geboren: ");
    printer.println(geburtsjahr);
    return 0;
  }

Es sollte schon die richtige Länge zurückgegeben werden, sonst kommen z.B. LCD Ausgaben aus dem Tritt.

Also vielleicht eher
Code: [Select]
size_t printTo(Print &printer) const
  {
    size_t len = printer.print(F("Name: "));
    len += printer.println(name);
    len += printer.print(F("Geboren: "));
    len += printer.println(geburtsjahr);
    return len;
  }


Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Serenifly

#24
Jun 20, 2017, 01:15 am Last Edit: Jun 20, 2017, 01:16 am by Serenifly
In dem Fall wird es nicht ausgewertet. Da kann man auch faul sein :p

Die LCD Libraries verwenden das auch nicht. Die implementieren nur die write() Methode um ein Zeichen zu schreiben und das wars. Die ganze Logik steckt in der Print Klasse.

combie

#25
Jun 20, 2017, 01:18 am Last Edit: Jun 20, 2017, 01:56 am by combie
Quote
Braucht nun allerdings leider auch einen Konstruktor weil es durch die Vererbung und virtuelle Methode nicht mehr eine einfache Aggregation ist:
Danke!
Das war mein Problem.


Nachtrag:
Einen Konstruktor hatte ich bisher eigentlich immer, wenn ich virtuelle Methoden verwendet habe.
Und sowieso eher selten diese Array artige Initialisierung.
Zufall, dass mir das noch nicht häufiger auf die Füße gefallen ist.

So gehts dann:
Code: [Select]


#define CountArray(array) (sizeof(array)/sizeof(array[0])
#define ForEach(array,var) for(int var=0;var<CountArray(array));var++)

#define Halt for(;;)



// ------------------------------


struct Person : Printable
{
  int geburtsjahr;
  char name[20];
 
  Person(unsigned int geburtsjahr, const char* name) : geburtsjahr(geburtsjahr)
  {
    strlcpy(this->name, name, sizeof(this->name));
  }

  size_t printTo(Print& p) const
  {
    size_t len = 0;
    len+=p.print(F("Name: "));
    len+=p.println(name);
    len+=p.print(F("Geboren: "));
    len+=p.println(geburtsjahr);
    return len;
  }
};

Person Belegschaft[]
{
  {1970,"Walter"},
  {1744,"Egon"},
  {2001,"Charly"},
};

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start"));
  Serial.println();
}

void loop()
{
  ForEach(Belegschaft,i)
  {
    if(i) Serial.println(F("---"));
    Serial.print(Belegschaft[i]);
  }
  Serial.println();
  Serial.println(F("Ende"));
  Halt;
}
Ob ein Mensch ein Gentleman ist,
erkennt man an seinem Benehmen denjenigen Menschen gegenüber,
von denen er keinen Nutzen hat.
Autor: William Lyon Phelps

Serenifly

#26
Jun 20, 2017, 01:42 am Last Edit: Jun 20, 2017, 01:51 am by Serenifly
In C++11 ist eine Aggregation so definiert:
Quote
An aggregate is an array or a class with no user-provided constructors, no brace-or-equal-initializers for non-static data members, no private or protected non-static data members, no base classes, and no virtual functions.
Wenn das der Fall ist kann man sie einfach mit { } initialisieren. Deshalb muss man bei einem einfachen struct sonst nichts tun. Selbst wenn man ein Array mit einem String-Literal initialisiert.

Sobald man aber dann eine der oberen Dinge hat, kommt so ein Fehler:
Quote
could not convert [...] from '<brace-enclosed initializer list>' to 'Person

Whandall

In dem Fall wird es nicht ausgewertet. Da kann man auch faul sein :p
Das sehe ich völlig anders.

"da kann man auch faul sein" passt überhaupt nicht zu "ich zeige dir wie es geht",
zumindestens nicht ohne entsprechende Kommentar.

Die LCD Libraries verwenden das auch nicht. Die implementieren nur die write() Methode um ein Zeichen zu schreiben und das wars. Die ganze Logik steckt in der Print Klasse.
Das ist korrekt und führte dazu, dass LCD Libraries nicht mehr funktionierten, nachdem Print den Returnkode von write auch benutzte (keine Ahnung bei welcher Version das passierte).
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

combie

#28
Jun 20, 2017, 09:11 am Last Edit: Jun 20, 2017, 09:12 am by combie
Naja, jetzt haben wir den Thread quasi gekapert...
Aber was solls, ich bin zufrieden, habe was gelernt.
Nochmal einen Punkt gefunden, wo ich mein Wissen vervollständigen kann.
Im Grunde ist das einer der wichtigsten Aspekte, warum ich überhaupt hier bin.


Auch hoffe ich, dass der ein oder andere Mitleser, hier von dieser Diskussion, was mit nehmen kann.

---

Ob eine "fehlerhafte" Rückgabe von size_t weitere Fehler nach sich zieht, kann ich so ad hoc nicht überprüfen. Dafür ist die Welt zu groß. Aber mein Pragmatismus erzwingt förmlich die Berechnung des Size .
Der ursprüngliche Programmierer hatte das so im Sinn.
Da ich auch Code (u.a. hier) publiziere, und nicht möchte, dass mir darin Bugs nachgewiesen werden, bzw. andere damit irgendwann auf die Nase fallen, wird Size eben berechnet.
Die paar Additionen tun nicht wirklich weh.
Es dient der Einhaltung, des Prinzips, der geringsten Verwunderung.

Hier im Thread ergab sich die Verwendung von struct.
Ansonsten, würde ich das eher explizit als Klasse definieren.
So dass auch meine heiß geliebten Sichtbarkeitsbegrenzer, (private usw.) ihr Plätzchen finden.

----

Um beim Wecker zu bleiben, bzw. auf ihn zurück zu kommen, wäre jetzt noch angesagt das Array ins EEPROM zu verlagern. Aber erst mal schauen, wie MaHa76 sich das so vorstellt...




Ob ein Mensch ein Gentleman ist,
erkennt man an seinem Benehmen denjenigen Menschen gegenüber,
von denen er keinen Nutzen hat.
Autor: William Lyon Phelps

Whandall

Ansonsten, würde ich das eher explizit als Klasse definieren.
So dass auch meine heiß geliebten Sichtbarkeitsbegrenzer, (private usw.) ihr Plätzchen finden.
Was hält dich ab?

Wie wir schon ausführten, geht das mit struc genau wie bei class, weil beides das Gleiche ist,
lediglich startet das Eine mit einem impliziten private: das Andere mit einem impliziten public:.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Go Up