Hi Forum, ich habe eine Frage zur Arduino Programmierung. Kann man irgenwie mit einer Funktion während dem Programmverlauf die Anzahl der Cases einer switch-case-Verzweigung herausfinden ? Mfg Nuri
Nuri O. schrieb: > Hi Forum, > > ich habe eine Frage zur Arduino Programmierung. > > Kann man irgenwie mit einer Funktion während dem Programmverlauf die > Anzahl der Cases einer switch-case-Verzweigung herausfinden ? > > Mfg > Nuri Wozu. Die ist doch konstant, so wie du das reinprogrammiert hast. Muß man also nicht erst herausfinden.
Man kann bei uin64_t alle 18,446,744,073,709,551,615 cases durchprobieren, ob sie nicht "default:" ausführen. Kann aber etwas dauern.
Naja, in GCC geht es mit einem Trick wenn man ein Makro für "case" verwendet:
1 | #include <stdio.h> |
2 | |
3 | #define CASE(X) { (void) __COUNTER__; } case X
|
4 | |
5 | int func (int i) |
6 | {
|
7 | switch (i) |
8 | {
|
9 | CASE(1): return i + 1; |
10 | CASE(3): return i - 2; |
11 | default: break; |
12 | }
|
13 | printf ("%d cases\n", __COUNTER__); |
14 | return i; |
15 | }
|
16 | |
17 | int main (void) |
18 | {
|
19 | func (2); |
20 | return 0; |
21 | }
|
Dann laufen lassen:
1 | $ gcc case.c -o case.x -Wall && ./case.x |
2 | 2 cases |
Bei mehr als einem switch pro Translation Unit wird das dann etwas aufwendiger, weil m.E. kann mann __COUNTER__ nicht zurücksetzen. Und der Wert steht nur nach dem switch zur Verfügung.
:
Bearbeitet durch User
...und im Code oben kann die Abfrage von __COUNTER__ auch in einer anderen Funktion geschehen, die das switch nich beinhaltet. Due Abfrage muss lediglich nach dem letzten CASE platziert sein, weil __COUNTER__ vom GCC Präprozessor aufgelöst wird.
Nuri O. schrieb: > Kann man irgenwie mit einer Funktion während dem Programmverlauf die > Anzahl der Cases einer switch-case-Verzweigung herausfinden ? Bei solchen Lösungsansätzen würde mich das zugrundeliegende Problem interessieren. Oder andersrum: was bringt es, wenn man weiß, wieviele if- oder case-Abfragen ein Programm an einer bestimmten Stelle hinter sich hat?
Nuri O. schrieb: > Kann man irgenwie mit einer Funktion während dem Programmverlauf die > Anzahl der Cases einer switch-case-Verzweigung herausfinden ? Wozu sollte das gut sein?
Lothar M. schrieb: > Bei solchen Lösungsansätzen würde mich das zugrundeliegende Problem > interessieren. War tatsächlich nur aus neugier. Ich bin kein anfänger, aber auch kein Profi und ich versuche immer alles so zu programmieren, dass ich bei Änderungen so wenig andere Codeteile anpassen muss. Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. Dafür muss ich ja wissen wie viele ich habe. Hatte mich dann gefragt, ob man das statt händisch auch irgendwie auslesen kann. Villeicht lernt man ja was neues :) Johann L. schrieb: > Und der Wert steht nur nach dem switch zur Verfügung. Ah schade, aber die probier ich mal aus, danke Mfg
Nuri O. schrieb: > Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. > Dafür muss ich ja wissen wie viele ich habe. Hatte mich dann gefragt, ob > man das statt händisch auch irgendwie auslesen kann. Villeicht lernt man > ja was neues :) Dann ist switch/case sicherlich das falsche Sprachmittel. Denn eine durchnummerierte case "Aufzählung" ist ein Sonderfall, welcher genau so, oder gar noch effektiver, mit eine Sprungleiste, oder einem FunktionPointerArray abgehandelt werden kann. Und die Größe eines Arrays, oder einer Liste, lässt sich jederzeit herausfinden. > Hatte mich dann gefragt, Vermutlich eine falsche Frage, weil dein C++, welches du verwendest, das nicht hergibt.
Ich gebe meinen Cases mittels define einen namen und danach ein #define CASES_MAX
Arduino F. schrieb: > mit eine Sprungleiste, oder einem > FunktionPointerArray Wie würde das aussehen ? Müsste ich dann für jeden Case eine Funktion schreiben und diese dann in einem Array zusammen fassen ? Flip B. schrieb: > danach ein #define > CASES_MAX Das CASES_MAX aber dann nur für dich ? Also dort trägst du dann auch händisch die Anzahl ein ?
Flip B. schrieb: > Ich gebe meinen Cases mittels define einen namen und danach ein #define > CASES_MAX Das hat aber nichts mit einem dynamisch während des Programmlaufs ermittelten Wert zu tun.
Nuri O. schrieb: > Wie würde das aussehen ?
1 | using FuncPtr = void(*)(); |
2 | |
3 | |
4 | void huchFunc() |
5 | {
|
6 | Serial.println("huch"); |
7 | }
|
8 | |
9 | FuncPtr functions[] |
10 | {
|
11 | [](){Serial.println("tue dies");}, |
12 | [](){Serial.println("tue das");}, |
13 | huchFunc, |
14 | [](){Serial.println("tue jenes");}, |
15 | [](){Serial.println("tue was anderes");}, |
16 | };
|
17 | |
18 | template<size_t N> void randomFuc(FuncPtr (&func)[N]) |
19 | {
|
20 | func[random(N)](); |
21 | }
|
22 | |
23 | void setup() |
24 | {
|
25 | Serial.begin(9600); |
26 | }
|
27 | |
28 | void loop() |
29 | {
|
30 | randomFuc(functions); |
31 | delay(1000); // nur damit es nicht zu schnell durchhuscht |
32 | }
|
Falls dir davon irgendwas "spanisch" vorkommt, ein gutes modernes C++ Grundlagenbuch hilft da weiter.
:
Bearbeitet durch User
Jens G. schrieb: > Das hat aber nichts mit einem dynamisch während des Programmlaufs > ermittelten Wert zu tun. Das spielt doch gar keine Rolex, da ein switch/case Konstrukt sowieso nicht zur Laufzeit verändert werden kann.
Nuri O. schrieb: > Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. Nein, der Compuer führt zu deiner Zahl passende case-Statements aus. Meist eins, aber mit Fall-Through gehen auch mehr für eine Zahl. > Dafür muss ich ja wissen wie viele ich habe. Die Aussage ergibt keinen Sinn. "wie viele" von was? Und warum musst du das "*wissen*". Du arbeitest mit einem mentalen Modell was keinen Sinn ergibt, aber du willst uns auch nicht verraten was das wirklich soll. Du hast die case-Statements geschrieben. Die sind fest in deinem Code. Die kannst du abzählen. 1, 2, 3, ... ganz viele. Arduino F. schrieb: > Dann ist switch/case sicherlich das falsche Sprachmittel. > Denn eine durchnummerierte case "Aufzählung" ist ein Sonderfall, welcher > genau so, oder gar noch effektiver, mit eine Sprungleiste, oder einem > FunktionPointerArray abgehandelt werden kann. Nein. Jeder halbwegs brauchbare C-Compiler erkennt das und legt für sequenzielle case-Statements Sprungtabellen an. Wenn es sein muss abschnittsweise und mit zusätzlichen eingestreuten Tests für nicht-sequenzielle Werte. > Und die Größe eines Arrays, oder einer Liste, lässt sich jederzeit > herausfinden. Und warum will man das tun? Man schreibt z.B. sechs case-Statements, dann hast man sechs Statements. Das werden zur Laufzeit nicht mehr oder weniger. Das sind genau die, die du hin geschrieben hast.
Hannes J. schrieb: > Nein. Jeder halbwegs brauchbare C-Compiler erkennt das und legt für > sequenzielle case-Statements Sprungtabellen an. Wenn es sein muss > abschnittsweise und mit zusätzlichen eingestreuten Tests für > nicht-sequenzielle Werte. Case Kaskaden werden nicht garantiert zu Sprungtabellen. Stark abhängig von den Optimierungseinstellungen. Sie degenerieren auch mal zu einer Vergleichs/Entscheidungskette, vergleichbar mit einer if/else Kaskade. Und das kann total ekelig werden. Kleinste Änderungen im Code ändern dann massiv die Größe des generierten Codes und vor allen Dingen die Laufzeit.
:
Bearbeitet durch User
Nuri O. schrieb: > Arduino F. schrieb: >> mit eine Sprungleiste, oder einem >> FunktionPointerArray > > Wie würde das aussehen ? Ich würd erst mal versuchen, dein Problem klar zu formulieren anstatt dich von irgendwelchen Hacks anfixen zu lassen die du bestimmt nicht brauchst.
:
Bearbeitet durch User
Hannes J. schrieb: >> Und die Größe eines Arrays, oder einer Liste, lässt sich jederzeit >> herausfinden. > > Und warum will man das tun? Zur Erleichterung? Zur Vermeidung von Fehlern? > Man schreibt z.B. sechs case-Statements, dann hast man sechs Statements. > Das werden zur Laufzeit nicht mehr oder weniger. Nein, aber zur Programmierzeit können es mehr oder weniger werden. Und dann ist es geschickt, wenn man nicht jedes mal daran denken muss, noch irgendwo eine magic number anpassen zu müssen. Der Computer ist eigentlich ziemlich gut im Zählen, also warum soll man das dann für ihn erledigen?
:
Bearbeitet durch User
Rolf M. schrieb: > Nein, aber zur Programmierzeit können es mehr oder weniger werden. Und > dann ist es geschickt, wenn man nicht jedes mal daran denken muss, noch > irgendwo eine magic number anpassen zu müssen. Wozu soll diese Magic-Number dienen? Das konnte keiner von euch Helden bisher beantworten. Wer die Kontrolle über seine Case-Statements verloren hat, der hat die Kontrolle über sein Leben verloren. Da hilft auch eine Magic-Number nichts.
Rolf M. schrieb: > Nein, aber zur Programmierzeit können es mehr oder weniger werden. Und > dann ist es geschickt, wenn man nicht jedes mal daran denken muss, noch > irgendwo eine magic number anpassen zu müssen. Magic Numbers ist aber absoluter Beginner Style. Typisch nimmt man enum für die Label-Liste. Z.B.: Beitrag "DS18B20 mit Interrupt, AVR-GCC"
Nuri O. schrieb: > Kann man irgenwie mit einer Funktion während dem Programmverlauf die > Anzahl der Cases einer switch-case-Verzweigung herausfinden ? Wenn dein Programm auf den Sourcecode zugreifen kann, sollte das mit einem stark vereinfachten C++-Parser kein Problem sein. Was natürlich wie alle anderen Antworten mit Lösungsvorschlägen nichts daran ändert, daß die einzig sinnvolle Antwort nein lautet. Oliver
Hannes J. schrieb: > Rolf M. schrieb: >> Nein, aber zur Programmierzeit können es mehr oder weniger werden. Und >> dann ist es geschickt, wenn man nicht jedes mal daran denken muss, noch >> irgendwo eine magic number anpassen zu müssen. > > Wozu soll diese Magic-Number dienen? Das konnte keiner von euch Helden > bisher beantworten. Das hat der TO doch schon geschrieben. Du Held hast es wohl nur überlesen. Sie soll dazu dienen, dem Zufallsgenerator den Zahlenbereich vorzugeben: Nuri O. schrieb: > Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. > Dafür muss ich ja wissen wie viele ich habe. Hannes J. schrieb: > Wer die Kontrolle über seine Case-Statements verloren hat, der hat die > Kontrolle über sein Leben verloren. Da hilft auch eine Magic-Number > nichts. Nun, ohne die Magic Number muss man die Anzahl halt programmatisch ermitteln, aber das lehnst du ja auch ab. Mehr Möglichkeiten gibt es nicht.
:
Bearbeitet durch User
Wenn dem so ist (z.B. Zufallsgenerator mit N Ergebnissen, etwa "elektronischer" Würfel) dann ist switch-case vermutlich das falsche Mittel: * N ändert sich nie → switch / case ist kein Problem * N ändert sich zur Compilezeit, d.h. es gibt X Generierungsvarianten für "Würfel" mit unterschiedlich vielen Seiten / Würfelmöglichkleiten. Abhängig vom Problem und davon, wie groß X ist, kann man: 1) X Generierungsvarianten vorhalten, wenn sich die X's schlecht generalisieren lassen. 2) Lassen sich die X's gut generalisieren, kann man direkt algorithmisch rangehen, oder auto-Generierung der Codestelle in Betracht ziehen. * N ändert sich zur Laufzeit → Ähnlich wie im vorherigen Fall: Bei X möglichen Varianten kann man for jedes mögliche X Code vorhalten (per if-else oder switch-case oder virtuelle Methoden etc); das trifft zu wenn X überschaubar ist. Bei Zillionen von Möglichkeiten für X geht's dann wieder algorithmisch.
:
Bearbeitet durch User
Rolf M. schrieb: > Hannes J. schrieb: >> Wozu soll diese Magic-Number dienen? Das konnte keiner von euch Helden >> bisher beantworten. > > Das hat der TO doch schon geschrieben. Du Held hast es wohl nur > überlesen. Sie soll dazu dienen, dem Zufallsgenerator den Zahlenbereich > vorzugeben: > > Nuri O. schrieb: >> Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. >> Dafür muss ich ja wissen wie viele ich habe. Das würde aber voraussetzen, dass die verschiedenen Fälle von 0 bis N fortlaufend numeriert sind – was nun absolut nicht selbstverständlich ist. Ich würde switch/case z.B. für Verzweigungen in Abhängigkeit von Protokollnummern etc. einsetzen, und da hat man normalerweise nur ein paar interessante Werte und viele Lücken dazwischen.
Ralf D. schrieb: >> Nuri O. schrieb: >>> Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. >>> Dafür muss ich ja wissen wie viele ich habe. > > Das würde aber voraussetzen, dass die verschiedenen Fälle von 0 bis N > fortlaufend numeriert sind – was nun absolut nicht selbstverständlich > ist. Warum sollte man sie anders nummerieren, wenn der Zweck ist, sie per Zufallsgenerator auszuwählen? > Ich würde switch/case z.B. für Verzweigungen in Abhängigkeit von > Protokollnummern etc. einsetzen, und da hat man normalerweise nur ein > paar interessante Werte und viele Lücken dazwischen. Dann braucht man aber auch die Anzahl nicht.
Arduino F. schrieb: > Jens G. schrieb: >> Das hat aber nichts mit einem dynamisch während des Programmlaufs >> ermittelten Wert zu tun. > > Das spielt doch gar keine Rolex, da ein switch/case Konstrukt sowieso > nicht zur Laufzeit verändert werden kann. Egal, ob das eine Rolle spielt - er will die vorhandenen Cases dynamisch zur Laufzeit ermitteln ... ist halt ein Holzweg ...
:
Bearbeitet durch User
Nuri O. schrieb: > Ich erzeuge eine Random zahl und führe dann den entsprechenden Case aus. > Dafür muss ich ja wissen wie viele ich habe. Hatte mich dann gefragt, ob > man das statt händisch auch irgendwie auslesen kann. Villeicht lernt man > ja was neues :) Du willst die Anzahl der erzeugten "Random Zahlen" wissen? Was glaubst du warum es "Random" heisst? Weil beim nächsten Durchlauf wieder genau die selben Zahlen erzeugt werden?
Jens G. schrieb: > Egal Ich danke dir herzlich, für deine Bestätigung meiner Aussagen!
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.