mikrocontroller.net

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


Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: anonym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (zeichenkette){
  //;-)
}

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl (Gast)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
z.B. so ähnlich:

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

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

Autor: C++ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
break wäre hier eine gute möglichkeit....

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: CaH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann ist ja alles gur...  ;)

Autor: CaH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-r +t

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt kann ich nichteinmal mehr schreiben:

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

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, jetzt hab ichs mit einem wilden Konstukt doch noch hinbekommen....

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:
// Das ist die Sequenz an Bytes die so, in dieser Reihenfolge
// empfangen werden muss, damit eine Aktion ausgelöst werden
// kann
unsigned char Sequence[] = { 0x02, 0x69 };
unsigned char SequenceNr = 0;

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

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

    SequenceNr++;

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

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

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

Autor: Marco (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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...

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert Dummerweise noch nicht so ganz, meine Abfrage...

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein paar Zähler der Variablen waren falsch. Jetzt gehts!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

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

static
uint8_t getchar(void)
{
    while (!(UCSR1A & (1 << RXC1)));  //warten bis RXC1=1, also data received
    return UDR1;
}

uint8_t poll_rx_sign[2];
uint8_t bd_addr[6];

void
receive(void)
{
    enum {
        IDLE, START, S69, S0C, S07, S00, DATA, CSUM, DONE
    } state = IDLE;

    while (state != DONE)
    {
        uint8_t c;
        int i = 0;

        c = getchar();

        switch (state)
        {
        case IDLE:
            if (c == 0x02)
                state = START;
            break;

        case START:
            if (c == 0x69)
                state = S69;
            break;

        case S69:
            if (c == 0x0c)
                state = S0C;
            else if (c == 0x02)
                state = START;
            break;

        case S0C:
            if (c == 0x07)
                state = S07;
            else if (c == 0x02)
                state = START;
            break;

        case S07:
            if (c == 0x00)
                state = S00;
            else if (c == 0x02)
                state = START;
            break;

        case S00:
            if (c == 0x7C) {
                i = 0;
                state = DATA;
            } else if (c == 0x02)
                state = START;
            break;

        case DATA:
            bd_addr[i++] = c;
            if (i >= 6) {
                i = 0;
                state = CSUM;
            }
            break;

        case CSUM:
            poll_rx_sign[i++] = c;
            if (i >= 2)
                state = DONE;
            break;

        case DONE:
            break;
        }
    }
}

Autor: Hans-jürgen Herbert (hjherbert) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verwende, wenn es den Code einfacher macht "goto" und "label:"

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


Fehlerfall:
...

Autor: Marco (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank!

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

Autor: Uboot- Stocki (uboot-stocki)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.