Gibt es in C keinen Sprungbefehl?

Gast #759732
Lesenswert?

Hallo

Kann man in C nicht eine Sprungmarke setzten und dorthin springen?

Mein Problem ist folgendes. Ich lese über UART Werte ein. Jetzt möchte 
ich bis auf eine bestimmte Zeichenkette alle Werte verwerfen.

Ich brauche also folgende Abfrage:

Ist Zeichen 0x02? Wenn ja, ist nächstes Zeichen 0x69? Wenn nein, ist es 
0x02? Wenn ja, springe zur Abfrage ob zweites Zeichen 0x69 ist... usw..


Wie macht man sowas?
Gast #759762
Lesenswert?

Eine if Abfrage reicht hier nicht, denn:

Wenn das erste Zeichen 02 ist, das zweite Zeichen eine 69, dann aber 
fälschlicherweise eine 02 kommt, könnte diese ja das erste erwartete 
Zeichen sein. Ich müsste dann also an die Stelle springen an der das 
zweite Zeichen abgefgar wird...
Moderator Persönliche Seite #759767
Lesenswert?

Zwar gibt es ein goto, aber das sollte man sich für absolute
Ausnahmefälle aufheben (*), ansonsten entsteht ganz schnell der
berüchtigte sogenannte Spaghetti-Code: er ist wie ein Teller
Spaghetti, ziehst du an einem Ende dran, kommt nach und nach
alles hinterher...

Das, was du willst, macht man normalerweise mit einer
Kombination aus Schleife (for oder while) und case-Anweisung.

(*) Für eine Fehlerbehandlung beispielsweise, damit lassen sich
u. U. tief verschachtelte (und damit auch nicht mehr übersichtliche)
if-else-Strukturen vermeiden.
#759854
Lesenswert?

Marco wrote:
> So, jetzt hab ichs mit einem wilden Konstukt doch noch hinbekommen....

Zeig mal das wilde Konstrukt.
Vielleicht kann man es noch etwas zähmen.

Mir ist nämlich aus deiner Beschreibung noch nicht wirklich
klar, was du eigentlich willst, bzw. wo das Problem dabei liegt.
Aber ich wage mal eine Interpretation und biete folgende Lösung
dafür an:
1
// Das ist die Sequenz an Bytes die so, in dieser Reihenfolge
2
// empfangen werden muss, damit eine Aktion ausgelöst werden
3
// kann
4
unsigned char Sequence[] = { 0x02, 0x69 };
5
unsigned char SequenceNr = 0;
6

7
void CheckSequence( unsigned char ReceivedByte )
8
{
9
  // Stimmt dieses Byte mit dem nächsten zu erkennenden Byte
10
  // überein?
11
  if( ReceivedByte == Sequence[SequenceNr] )
12

13
    // Wenn ja: registrieren, dass wieder ein Byte der Seuquenz
14
    // gepasst hat
15

16
    SequenceNr++;
17

18
    // War das das letzte zu erkennende Byte der
19
    // vorgegebenen Sequenz? Wenn ja: Hurra: Aktion auslösen
20
    // und wieder in den Grundzustand gehen
21
    if( SequenceNr == sizeof( Sequence ) {
22
      Aktion();
23
      SequenceNr = 0;
24
    }
25
  }
26

27
  else {
28
    // Das empfangene Byte hat nicht gepasst. Daher zurück
29
    // an den Start und erneut auf den Beginn der Sequenz
30
    // warten
31
    SequenceNr = 0;
32
  }
33
}

Du stopfst Byte für Byte, so wie du sie vom UART empfängst, in diese
Funktion hinein. Wenn die empfangene Bytesequenz der Vorgabe im
Array entspricht, wird die Funktion Aktion() aufgerufen.
Sobald in der Übertragungssequenz irgendwo ein Fehler auftaucht,
muss die komplette Sequenz, von vorne beginnend, erneut auftauchen
Moderator Persönliche Seite #759984
Lesenswert?

Hier ein Vorschlag in Form eines zustandsgesteuerten Automaten (state
machine).  Alles natürlich ohne Gewehr oder Pistole...
1
#include <avr/io.h>
2

3
static
4
uint8_t getchar(void)
5
{
6
    while (!(UCSR1A & (1 << RXC1)));  //warten bis RXC1=1, also data received
7
    return UDR1;
8
}
9

10
uint8_t poll_rx_sign[2];
11
uint8_t bd_addr[6];
12

13
void
14
receive(void)
15
{
16
    enum {
17
        IDLE, START, S69, S0C, S07, S00, DATA, CSUM, DONE
18
    } state = IDLE;
19

20
    while (state != DONE)
21
    {
22
        uint8_t c;
23
        int i = 0;
24

25
        c = getchar();
26

27
        switch (state)
28
        {
29
        case IDLE:
30
            if (c == 0x02)
31
                state = START;
32
            break;
33

34
        case START:
35
            if (c == 0x69)
36
                state = S69;
37
            break;
38

39
        case S69:
40
            if (c == 0x0c)
41
                state = S0C;
42
            else if (c == 0x02)
43
                state = START;
44
            break;
45

46
        case S0C:
47
            if (c == 0x07)
48
                state = S07;
49
            else if (c == 0x02)
50
                state = START;
51
            break;
52

53
        case S07:
54
            if (c == 0x00)
55
                state = S00;
56
            else if (c == 0x02)
57
                state = START;
58
            break;
59

60
        case S00:
61
            if (c == 0x7C) {
62
                i = 0;
63
                state = DATA;
64
            } else if (c == 0x02)
65
                state = START;
66
            break;
67

68
        case DATA:
69
            bd_addr[i++] = c;
70
            if (i >= 6) {
71
                i = 0;
72
                state = CSUM;
73
            }
74
            break;
75

76
        case CSUM:
77
            poll_rx_sign[i++] = c;
78
            if (i >= 2)
79
                state = DONE;
80
            break;
81

82
        case DONE:
83
            break;
84
        }
85
    }
86
}
#760425
Lesenswert?

Hans-jürgen Herbert wrote:
> Ich verwende, wenn es den Code einfacher macht "goto" und "label:"
>
> for (...)
>     {
>     while(...)
>        {
>        if ( alles falch ) goto Fehlerfall ;
>        ...
>        }
>     }
> ....
>
>
> Fehlerfall:
> ...

Eine Frage: wird denn bei solch einem Konstrukt der Stack aufgeräumt? 
D.h. wird das Programm im Falle "alles Falsch" exakt so weiterlaufen wie 
wenn die for-Schleife "normal" beendet wird ???

Gruß

Andreas

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