über Seriellen Monitor in switch-case springen

Gast #6086269
Lesenswert?

Hi,
hoffe Ihr habt alle frohe Festtage !

Ich versuche gerade über den Seriellen Monitor in eine Switch-CASE zu 
springen.
jedoch funktioniert das nicht ganz. Der Compiler meldet folgendes:
1
sketch_dec26a:18:10: error: expected identifier before 'case'
2

3
     goto case 1;
4

5
          ^
6

7
sketch_dec26a:18:10: error: expected ';' before 'case'
8

9
sketch_dec26a:18:10: error: case label '1' not within a switch statement
10

11
sketch_dec26a:18:16: error: expected ':' before ';' token
12

13
     goto case 1;
14

15
                ^

hier mein Code:
1
byte Case = 1;
2

3
unsigned long Millis;
4

5
void setup() {
6
  Serial.begin(115200);
7
  Millis = millis();
8

9
}
10

11
void loop() {
12

13
  if (Serial.available() > 0) {
14

15
    const char a = Serial.read();
16

17
    if (a == '1') {
18
    goto case 1;
19
    }
20
    else if (a == '2') {}
21
    else if (a == '3') {}
22
    else if (a == '4') {}
23
    else if (a == '5') {}
24
    else if (a == '6') {}
25

26
  }
27
}
28

29
if (millis() - Millis >= 10000) {
30
  switch (Case) {
31

32
    case 1:
33
      Serial.println("Case 1");
34

35
      Case = 2;
36
      Millis = millis();
37

38
      break;
39

40
    case 2:
41
      Serial.println("Case 2");
42

43
      Case = 3;
44
      Millis = millis();
45

46
      break;
47

48
    case 3:
49
      Serial.println("Case 3");
50

51
      Case = 4;
52
      Millis = millis();
53

54
      break;
55

56
    case 4:
57
      Serial.println("Case 4");
58

59
      Case = 5;
60
      Millis = millis();
61

62
      break;
63

64
    case 5:
65
      Serial.println("Case 5");
66

67
      Case = 6;
68
      Millis = millis();
69

70
      break;
71

72
    case 6:
73
      Serial.println("Case 6");
74

75
      Case = 1;
76
      Millis = millis();
77

78
      break;
79
  }
80
}
81
}

Was mache ich falsch?

Mfg
Gast #6086302
Lesenswert?

Hier noch einige Konstrukte die dir bei weiteren "Programmieruebungen"
sicherlich hilfreich sein werden:
1
Conditional Statements
2

3
WHAT IF
4
    Used in simulation languages. Branches before evaluating the test condition.
5

6
OR ELSE
7
    Conditional threat as in: "Add these two numbers OR ELSE"
8

9
WHY NOT
10
    Executes the code that follows in a devil-may-care fashion
11

12
WHO ELSE
13
    Used for polling during I/O operations
14

15
ELSEWHERE
16
    This is where your program really is when you think it's here
17

18
GOING GOING GONE
19
    For writing unstructured programs. Takes a random branch to another part of your program.
20
    Does the work of a hundred GOTOs
21

22
Case Statements
23

24
JUST IN CASE
25
    For handling afterthoughts and fudge factors.
26
    Allows you to multiply by zero to correct for accidently dividing by zero
27

28
BRIEF CASE
29
    To encourage portable software
30

31
OPEN AND SHUT CASE
32
    No proof of correctness is necessary with this one
33

34
IN ANY CASE
35
    This one always works
36

37
HOPELESS CASE
38
    This one never works
39

40
BASKET CASE
41
    A really HOPELESS CASE
42

43
Loop Statements
44

45
DON'T DO WHILE NOT
46
    The loop is not executed if the test condition is not false (or it's Friday afternoon)
47

48
DIDN'T DO
49
    The loop executes once and hides all traces
50

51
WON'T DO
52
    The program stops because it doesn't like the code inside the loop.
53
    Execution can be resumed by typing "MAY I" at the command line
54

55
MIGHT DO
56
    Depends on how the program is feeling.
57
    Executed if the CPU is "up", not executed if the CPU is "down" or if its feelings have been hurt
58

59
DO UNTO OTHERS
60
    Used to write the main loop for operating systems to antagonize all programs in a uniform manner
61

62
DO WAH
63
    Used to write loops for computer generated music (e.g. Rag Timing)

Guten Ausrutsch!
Gast #6086304
Lesenswert?

if (Serial.available() > 0) {

    const char a = Serial.read();
}

if (millis() - Millis >= 10000) {
  switch (a) {
    case 1:
      Serial.println("Case 1");
      a = 2;
      Millis = millis();
      break;
 }

So wird da eher ein Schuh draus. Keine goto's nötig da switch case über 
den Inhalt des Identifier a gesteuert wird.

Man ist gut beraten goto's nicht zu nutzen.
Gast #6086326
Lesenswert?

kenny schrieb:
> Man ist gut beraten goto's nicht zu nutzen.

Zumindest sollte man etwas Disziplin dabei wahren.

Was hier nicht geht, ist das Springen mitten in eine Funktion hinein.

@  Franco O.
Leider kann ich nicht erkennen, WAS gebaut werden soll, nur, dass du 
einen falschen Weg gewählt hast.
Gast #6086328
Lesenswert?

Arduino Fanboy D. schrieb:
> kenny schrieb:
>> Man ist gut beraten goto's nicht zu nutzen.
>
> Zumindest sollte man etwas Disziplin dabei wahren.

Das habe ich aber auch oft gelesen dass man davon die finger lassen 
sollte.

> Was hier nicht geht, ist das Springen mitten in eine Funktion hinein.
>
> @  Franco O.
> Leider kann ich nicht erkennen, WAS gebaut werden soll, nur, dass du
> einen falschen Weg gewählt hast.

Was genau ist der falsche weg?

also Der plan ist dass der die das Switch-Case normal laufen soll mit 
dem Zusatz dass ich einen Bestimmten Case aufrufen kann er dann diesen 
case ausführt und normal über die Millis weiter läuft
Gast #6086352
Lesenswert?

Arduino Fanboy D. schrieb:
> Wenn der Automat das nächste mal dran kommt, macht er mit 1 weiter.

Da da sowieso eine "}"-Klammer zu viel ist, macht er gar nichts weiter 
(der Compiler wird weter rummeckern).
Ich habe die if-Else-If-Orgie so verstanden, dass bei Eingabe einer 
Ziffer über die serielle Schnittstelle ein neuer Automatenzustand 
gewählt werden soll.
Die Stelle wird ja auch nur angesprungen, wenn '1' auf der Schnittstelle 
empfangen wurde.

Ich kann natrlich auch mal wieder komplett daneben liegen...
Gast #6086360
Lesenswert?

Arduino Fanboy D. schrieb:
> Du möchtest eine Ablaufsteuerung bauen?
> Einen auf switch/case basierenden endlichen Automaten?
> Wenn der Automat das nächste mal dran kommt, macht er mit 1 weiter.

nene Das habe ich ja schon. Er starte bei 1 nach jedem ablauf

Franco O. schrieb:
> case 1:
>       Serial.println("Case 1");
>
>       Case = 2; <-- Nach jedem Case setzt er ihn auf den nächsten
>       Millis = millis();

so wird alle 10 Sekunden der nächste Case ausgeführt was auch so sein 
soll

Jetzt möchte ich aber Case 2 aufrufen. So sind wir bei dem Geschreibsel 
gelandet. Meine Idee war per Seriellen Monitor den Case einzugeben und 
dann direkt dort hinzuspringen.
Gast #6086361
Lesenswert?

Arduino Fanboy D. schrieb:
> Kann ja sein!
>
> Case = geleseneZahl - '0';

Vielleicht möchte er aber auch "Something completely different" in den 
anderen Abfragen machen.
Die Abfragen kann man natürlich auch in einer Switch-Case-Abfrage 
verarbeiten.

Man kann auch die Millis-Neuberechnungsgeschichten zusammenfassen und 
vor der zweiten Switch-Case einfügen, sofern nicht vielleicht doch ein 
Fall dabei ist, bei dem die Rechnung nicht durchgeführt werden soll.
Beitrag #6086362 wurde von einem Moderator gelöscht.
Gast #6086399
Lesenswert?

Einfach die Bedingung schaffen, dass er direkt nach Empfang eines 
Characters das "switch" Statement ausführt, also:

if (Serial.available() > 0) {

  const char a = Serial.read();

  if (a == '1') {
    Millis = millis() - 10000;
    Case = 1;
  }
...

if (millis() - Millis >= 10000) {
  switch (Case) {
...
(Firma: egal) #6086607
Lesenswert?

kenny schrieb:
1
> if (Serial.available() > 0) {
2
> 
3
>     const char a = Serial.read();
4
> }
5
> 
6
> if (millis() - Millis >= 10000) {
7
>   switch (a) {
8
>     case 1:
9
>       Serial.println("Case 1");
10
>       a = 2;
11
>       Millis = millis();
12
>       break;
13
>  }

Das ist aber fast schon genauso fehlerhaft wie das von TO

Oliver S. schrieb:
> So ginge es:
1
> //...
2
> 
3
> goto label1;
4
> //....
5
> 
6
> switch (Case) {
7
> 
8
>     case 1:
9
>     label1:
10
>       Serial.println("Case 1");
11
> 
12
>       break;
13
> }

Nö, das ist in den meisten Fällen eher wie mit dem Großkalibergewehr ins 
Knie geschossen.


Kleiner Tipp, mal über den Gültigkeitsbereich von Variablen und über 
wild im Quellcode verstreute "break" nachdenken.
(Firma: egal) #6086653
Lesenswert?

Franco O. schrieb:
> So hats bei mir geklappt. Sollte ich das denn lieber nicht so machen?

Nimm lieber die Variante mit der Hilfsvariable so in der Art wie von 
Dirk.B vorgeschlagen. Sowas ist allemal sauberer als mit goto mitten in 
irgendwelche Konstrukte reinzuspringen und dann zu hoffen das sie 
dennoch sauber verlassen werden.

---
Das mit dem goto|switch|case|label|break habe ich gerade mal mit clang 
rumexperimentiert.
Interessanter weise tut der break genauso als wäre switch|case 
ausgeführt worden und springt an die gleiche Stelle.
Erweckt bei mir jetzt eher den Eindruck dass das c-goto 1:1 in einen 
ASM-Jump umgesetzt wird ohne darauf zu achten das dadurch das 
eigentliche C-Konstrukt etwas ausgehebelt wird.
goto|irgendwas|label|break oder goto|for|switch|case|label|break frist 
der Compiler dagegen nicht ohne heftig zu meckern.
Mich würde jetzt mal interessieren ob diese "als ob" verhalten bei einem 
goto mitten in eine switch irgendwo im Standard definiertes Verhalten 
ist auf das man sich theoretisch verlassen könnte oder eher "Zufall" 
ist. So auf die schnell konnte ich diesbezüglich nichts finden.

PS: ich habe garantiert nicht vor sowas ernsthaft zu verwenden, es 
interessiert mich nur gerade mal wieder was C/C++ so alles an 
"fragwürdigen" Konstrukten zulässt.
Gast #6086658
Lesenswert?

Irgend W. schrieb:
> Mich würde jetzt mal interessieren ob diese "als ob" verhalten bei einem
> goto mitten in eine switch irgendwo im Standard definiertes Verhalten
> ist auf das man sich theoretisch verlassen könnte oder eher "Zufall"
> ist.

Ist kein Zufall.

Schaue dir dazu mal dem Adam Dunkel seine ProtoThreads an.

Eine Variante arbeitet mit Switch/case, welches auch Case in 
untergerodneten Blöcken "anspringen" kann. Auch mitten in for Schleifen 
rein usw.
Die andere Variante nutzt computed goto für den selben Zweck.

Es gibt viele weitere Implementierungen dieses Prinzips.
z.B.
https://forum.arduino.cc/index.php?action=dlattach;topic=415229.0;attach=176389
https://forum.arduino.cc/index.php?action=dlattach;topic=596279.0;attach=293747
Gast #6087035
Lesenswert?

Irgend W. schrieb:
> Nimm lieber die Variante mit der Hilfsvariable so in der Art wie von
> Dirk.B vorgeschlagen. Sowas ist allemal sauberer als mit goto mitten in
> irgendwelche Konstrukte reinzuspringen und dann zu hoffen das sie
> dennoch sauber verlassen werden.

Gut dann nehme ich das Lieber :)

Herzlichen Glückwunsch Dirk du wirst für immer und ewig in meinem Code 
verewigt.

Dankeschön!
Gast #6087378
Lesenswert?

Noch eine Beispiellösung:
Einlesen erfolgt im seriellen Interrupt. Gegebenenfalls
könnte man noch einen Puffer zwischen isr und loop einfügen.
1
char help = 0;
2

3
void setup ()
4
{
5
  Serial.begin(9600);
6
  Serial.println("Geben Sie im seriellen Monitor 0 oder 1 ein.");
7
}
8

9
void loop()
10
{   
11
 // Serial.println("232323"); delay(1000);
12
  
13
  if (help != 0)
14
    {
15
      
16
    switch (help)
17
     { 
18
      
19
      case '0' : Serial.println("Anton");
20
                 break;
21
      case '1' :  Serial.println("Berta");        
22
      }                           
23
    }
24
   help = 0;
25
}
26

27

28

29
void serialEvent()
30
{
31
  if (Serial.available())
32
      {
33
        help = (char)Serial.read();
34
      
35
       if(help >= '0'   && help <= '9')
36
            ;     //es beibt alles beim Alten
37
      else
38
      help = 0;
39
      }  
40
}

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