Forum: Compiler & IDEs Gibt es in C keinen Sprungbefehl?


von Marco (Gast)


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?

von anonym (Gast)


Lesenswert?

if (zeichenkette){
  //;-)
}

von Marco (Gast)


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

von Karl (Gast)


Lesenswert?

Es gibt schon goto, setjump und longjump in C, aber lass mal lieber die 
Finger davon und mach es mit if.

von Falk B. (falk)


Lesenswert?

@ Marco (Gast)

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

Ja, mit goto. Aber HALT! Das ist der falsche Weg! GOTO verwendet man 
nicht.

MfG
Falk

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Walter (Gast)


Lesenswert?

z.B. so ähnlich:

char *str="abc";
int i=0;

while ( *(str+i) )
  if ( getchar()==*(str+i) )
    i++;
  else
    i = 0;

von C++ (Gast)


Lesenswert?

break wäre hier eine gute möglichkeit....

von Marco (Gast)


Lesenswert?

Ich weiß ja nicht ob ich gestern einfach zu wenig geschlafen habe oder 
woher das Brett vorm Kopf kommt...
Aber mit if, while und case schaffe ich es einfach das zu realisieren 
was ich vorhabe.

von CaH (Gast)


Lesenswert?

Dann ist ja alles gur...  ;)

von CaH (Gast)


Lesenswert?

-r +t

von Marco (Gast)


Lesenswert?

Jetzt kann ich nichteinmal mehr schreiben:

Wollte sagen ich schaffe es einfach nicht, das zu realisieren was ich 
vorhabe...

von Marco (Gast)


Lesenswert?

So, jetzt hab ichs mit einem wilden Konstukt doch noch hinbekommen....

Manchmal nimmt das Hirn auch echt mal ne Auszeit...

von Karl H. (kbuchegg)


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

von Marco (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal mein Konstrukt.

Das Problem ist, das das erste Zeichen, also die 0x02 nicht verloren 
gehen darf wenn Sie mittendrin auftaucht. Denn das könnte ja der Anfang 
der erwarteten Bytefolge sein...

von Marco (Gast)


Lesenswert?

Funktioniert Dummerweise noch nicht so ganz, meine Abfrage...

von Marco (Gast)


Lesenswert?

Ein paar Zähler der Variablen waren falsch. Jetzt gehts!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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
}

von Hans-jürgen H. (hjherbert) Benutzerseite


Lesenswert?

Ich verwende, wenn es den Code einfacher macht "goto" und "label:"

for (...)
    {
    while(...)
       {
       if ( alles falch ) goto Fehlerfall ;
       ...
       }
    }
....


Fehlerfall:
...

von Marco (Gast)


Lesenswert?

Vielen Dank!

Werde Freitag mal Rückmeldung geben.
Voher schaffe ich es leider nicht!

von Uboot- S. (uboot-stocki)


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

von Simon K. (simon) Benutzerseite


Lesenswert?

Der Stackframe existiert nur auf Funktionsebene. Und Labels kann man 
eben auch nur innerhalb einer Funktion anspringen.

Es ist also nicht möglich ein Label in einer anderen Funktion 
anzuspringen.

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.