www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wer kennt sich mit string.h aus?


Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

Ich bin dabei mein MC35T mit dem ATmega16 auszulesen. Ankommende Daten 
zeige ich auf einem LCD- Display an.
Wenn ich dem Befehl zum senden eines Telfonbucheintrags abschicke, 
bekomme ich ein String mit den geforderten Daten. Soweit klappt das 
auch. Jetzt weiß ich, dass sowohl der Name, als auch die Nummer in 
Anführungszeichen <“> stehen. Ich merke mir, während das Array gefüllt 
wird, wo die 4 Anführungszeichen stehen. Wenn die Übertragung fertig 
ist, fülle ich die zwei Strings „name“ und „nummer“. Also habe ich eine 
Funktion geschrieben die sieht so aus:


void get_from_mc35t()
{
  U8 i = 0;
  temp[zaehler] = uart_getchar(); // in temp kommt das aktuelle 
empfangene Zeichen

      // hier wird das vierte Array-Platz gespeichert in dem das erste
      // < " > platziert ist
      if((temp[zaehler] == '"') &&(anf_zeich3 != 0)&&(anf_zeich4 == 0))
        {
          anf_zeich4 = zaehler;
        }

      // hier wird das dritte Array-Platz gespeichert in dem das erste
      // < " > platziert ist
      if((temp[zaehler] == '"') &&(anf_zeich2 != 0)&&(anf_zeich3 == 0))
        {
          anf_zeich3 = zaehler;
        }

      // hier wird das zweite Array-Platz gespeichert in dem das erste
      // < " > platziert ist
      if((temp[zaehler] == '"') &&(anf_zeich1 != 0)&&(anf_zeich2 == 0))
        {
          anf_zeich2 = zaehler;
        }

      // hier wird der erste Array-Platz gespeichert in dem das erste
      // < " > platziert ist
      if((temp[zaehler] == '"') &&(anf_zeich1 == 0))
        {
          anf_zeich1 = zaehler;
        }


      ///// Anfang der Auswertung nach empfangen des OK[CR][LF]
      if((temp[zaehler] == LF) && (temp[zaehler-1]== CR) && 
(temp[zaehler-2]== 'K') && (temp[zaehler-3] == 'O'))
      {
        lcd_clear();



        for(i = 0; i< (anf_zeich2 - anf_zeich1 -1); i++)
          {
            eintrag.nummer[i] = temp[anf_zeich1 +1 +i];
           }
        eintrag.name[i+2] = 0; // Am Ende noch eine Null dran hängen

        // hier wird vom dritten bis zum vierten < " > der Name in das 
Array
        // geschrieben
        for(i = 0; i< (anf_zeich4 - anf_zeich3 -1); i++)
          {
            eintrag.name[i] = temp[anf_zeich3 +1 +i];
           }
        eintrag.nummer[i+2] = 0; // Am Ende noch eine Null dran hängen


        lcd_gotoxy(1,1);
        lcd_text("Name:");
        lcd_gotoxy(1,2);
        lcd_text(eintrag.name);
        lcd_gotoxy(1,3);
        lcd_text("Nummer:");
        lcd_gotoxy(1,4);
        lcd_text(eintrag.nummer);

        i = 0;
        zaehler = 0;
        anf_zeich1 = 0;
        anf_zeich2 = 0;
        anf_zeich3 = 0;
        anf_zeich4 = 0;
      }  ///// Ende der Auswertung nach empfangen des OK[CR][LF]

      else // bezieht sich auf das "if" der Auswertung OK[CR][LF]
      {
        zaehler++;
      }


}// Ende get_from_mc35t()


Ich weiß, der Aufruf:
eintrag.nummer[i+2] = 0;
Sieht komisch aus, aber nur so geht das ganze.
Das ganze funktioniert eigentlich ganz gut. Allerdings nur so lange bis 
ich z.B. einen Namen mit 15 Zeichen gelesen habe, und dann einen mit nur 
10. Dann steht im String noch der Rest vom letzten. (der ganze Rest)

Jetzt ist meine Frage ob es bei den vielen Stingfunktionen nicht eine 
gibt, die mir dabei etwas mehr helfen könnte wie das zählen der 
Anführungszeichen. Ich habe zwar schon im Internet gesucht, allerdings 
gibt es nie Beispiele dazu.

Hat von euch jemand eine Idee????
Oder gibt es eine hilfreiche Internet- Seite??

Danke schon mal für eure Hilfe…
Grüße,
Marcel

Autor: Durchblicker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich finde, die Nullterminierung ist vertauscht für name und nummer. Da 
hast Du nen Dreher drin.

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh je, du hast recht!!!!!
Da habe ich vor lauter Bäumen den Wald nicht mehr gesehen!!!!

Aber leider geht es so immer noch nicht :o(

Autor: Durchblicker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ein anderer Denkanstoss, ganz ohne sring.h

#define WAITNAME    0
#define READNAME    1
#define WAITNUMMER  2
#define READNUMMER  3
#define WAIT_O      4
#define WAIT_K      5
#define WAIT_CR     6
#define WAIT_LF     7

char Name[40];
char Nummer[40];
byte Cnt;
char Char = uart_getchar();
switch (State)
{
case WAITMAME:
    if (Char != '\"')
        break;
    State = READNAME;
    Cnt = 0;
    break;
case READNAME:
    if (Char != '\"')
    {
        Name[Cnt++] = Char;
        break;
    }
    State = WAITNUMMER;
    break;
case WAITNUMMER:
    if (Char != '\"')
        break;
    State = READNAME;
    Cnt = 0;
    break;
case READNUMMER:
    if (Char != '\"')
    {
        Name[Cnt++] = Char;
        break;
    }
    State = WAIT_O;
    break;
case WAIT_O:
    State = Char == 'O' ? WAIT_K : WAIT_NAME;
    break;
case WAIT_K:
    State = Char == 'K' ? WAIT_CR : WAIT_NAME;
    break;
case WAIT_CR:
    State = Char == '\r' ? WAIT_LF : WAIT_NAME;
    break;
case WAIT_LF:
    State = WAIT_NAME;
    if (Char == '\n')
        // Fertig, Datenverarbeitung
    break;
}

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo  Durchblicker,

hmmm, ich bin noch kein all zu gutern Programmierer!!! Da brauche ich 
erst mal ne weile bis ich deinen Code richtig verstehe.

Aber auf jeden Fall mal vielen Dank für deinen Denkanstoss.

Ich gehe mal davon aus das "State" eine globale Variable ist!!



ich könnte für die Anzeige also noch schreiben:

#define WRITE_LCD     8



und dann unten:

case WAIT_LF:
    State = WRITE_LCD;
    if (Char == '\n')
    break;

case WRITE_LCD:
    State = WAIT_NAME;
    if (Char == '\n')
        // Fertig, Datenverarbeitung
        ///// Ausgabe auf dem LCD !!!
    break;



ist das so richtig??

Grüße Marcel

Autor: Durchblicker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau. Ausserdem habe ich die Nullterminierung vergessen, und bei 
READNUMMER hab ich in Name reingespeichert... :

case READNAME:
    if (Char != '\"')
    {
        Name[Cnt++] = Char;
        break;
    }
    Name[Cnt] = 0;
    State = WAITNUMMER;
    break;

case READNUMMER:
    if (Char != '\"')
    {
        Nummer[Cnt++] = Char;
        break;
    }
    Nummer[Cnt] = 0;
    State = WAIT_O;
    break;

Was bei Deinem Code schiefläuft, weiss ich allerdings auch nicht...

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Durchblicker,

so jetzt geht's endlich mit deinem "Denkanstoss" :o))

Es hat die ganze Zeit bei mir nicht funktioniert da ich einen Denfehler 
drin hatte.

1. Mann epfängt nicht automatisch nach dem letzten  "  das  OK\n\r . Das 
heißt die Funktion für  \n  und  \r  mußte hier so geschrieben werden 
wie bei dem ".

2. Man muss gleich beim  \r  auf das LCD geschrieben werden. Man kann 
nicht in  \r  schreiben: Status = WRITE_LCD da  \r  ja das letzte 
empfangene Zeichen ist und so die Funktion nicht mehr aufgerufe wird.

Wie gesagt, jetzt klappt das ganze aber hervorragend.

Viele Dank für deinen klasse Tip!!!!

Schönen Sonntag Abend noch und Grüße,

Marcel

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.