Forum: Mikrocontroller und Digitale Elektronik Anzahl der Cases rausfinden


von Nuri O. (nurios)


Lesenswert?

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

von Jens G. (jensig)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

...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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

von Harry L. (mysth)


Lesenswert?

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?

von Nuri O. (nurios)


Lesenswert?

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Flip B. (frickelfreak)


Lesenswert?

Ich gebe meinen Cases mittels define einen namen und danach ein #define 
CASES_MAX

von Nuri O. (nurios)


Lesenswert?

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 ?

von N. M. (mani)


Lesenswert?

So?
1
enum CaseType
2
{
3
Case0,
4
Case1,
5
CaseN,
6
CaseCount
7
};

von Jens G. (jensig)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
von Rolf M. (rmagnus)


Lesenswert?

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
von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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"

von Oliver S. (oliverso)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
von Ralf D. (doeblitz)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Jens G. (jensig)


Lesenswert?

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
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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
Noch kein Account? Hier anmelden.