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?
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...
Es gibt schon goto, setjump und longjump in C, aber lass mal lieber die Finger davon und mach es mit if.
@ 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
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.
z.B. so ähnlich: char *str="abc"; int i=0; while ( *(str+i) ) if ( getchar()==*(str+i) ) i++; else i = 0;
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.
Jetzt kann ich nichteinmal mehr schreiben: Wollte sagen ich schaffe es einfach nicht, das zu realisieren was ich vorhabe...
So, jetzt hab ichs mit einem wilden Konstukt doch noch hinbekommen.... Manchmal nimmt das Hirn auch echt mal ne Auszeit...
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
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...
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 | }
|
Ich verwende, wenn es den Code einfacher macht "goto" und "label:" for (...) { while(...) { if ( alles falch ) goto Fehlerfall ; ... } } .... Fehlerfall: ...
Vielen Dank! Werde Freitag mal Rückmeldung geben. Voher schaffe ich es leider nicht!
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.