mikrocontroller.net

Forum: Compiler & IDEs Stringvergleich mit C


Autor: Steffen Brüssel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche seit einiger Zeit einen über UART empfangenen String im
ATMega mit einem Vorhandenen zuvergleichen.
Bei einzelnen Chars funktioniert das ganz wunderbar.
Ich hab mich jetzt total vergallopiert.
Für den Vergelcih von Strings habe ich mich für die Methode strstr
entschieden. Man hat mir allerdings gesagt, dass hier der String
unbedingt mit \n bzw 0x00 abgeschlossen sein muss.

Code:
if(b=='1'){
      if (strstr((char*)data, "1\n")){
       PORTB = 0x00;

      }
      else if (strstr((char*)data, "0\n")){
       PORTB = 0xff;

      }
      else if (strstr((char*)data, "Steffen")){
       USART_transmit_string("Hallo Steffen");//(char*)data

      }
      else if (strstr((char*)data, "Jana")){
       USART_transmit_string("Hallo Jana");//(char*)data
             }

----------------
Ich sende vom Terminal Programm aus auch einen String der dieses
Zeichen enthält. Es wird auch im ATMega erkannt. Aber ichhabe scheinbar
den String Vergeleich selbst falsch aufgezogen.
Noch zur ERgänzung:
volatile unsigned char *data[12];

Wie ihr seht, hab ich shcon ein wenig Probiert und einmal mit und
einmal ohne das \n bzw 0x00 (das sit doch das gleiche, nicht?)
Verglichen. allerdings passiert gar nix :(

Ich höffe Ihr könnt mir hierbei helfen.

Danke

Steffen

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest Dich noch einmal eingehend mit Pointern und Arrays
auseinandersetzen.
Vielleicht hilft Dir folgendes Beispiel (getestet mit MinGW auf
Win2000):

--8<--

#include <string.h>

char data[12];
char *pdata;

int
main(void)
{
   sprintf(data, "foo\n");

   while(1)
   {
      if(pdata = strstr(data, "foo"))
      {
   printf("data contains foo! [@%p]\n", pdata);
   sprintf(data, "bar\n");
      }
      else if(pdata = strstr(data, "bar"))
      {
   printf("data contains bar! [@%p]\n", pdata);
   sprintf(data, "foo\n");
      }
   }

   /* NEVEREACHED */
   return 0;
}

--8<--

Kompilieren mit "gcc -O3 -ggdb -o foobar.exe foobar.c"

Ich würde sagen, es empfiehlt sich immer, bei solchen
Verständnisproblemen erst einmal dieses eine Teilproblem auf dem PC
auszuprobieren, da sich hier viel einfacher Änderungen einbauen lassen.
Dazu braucht man lediglich den hardwareunabhängigen Teil zu
extrahieren.
Ich mache das jedenfalls immer so, wenn mir eine Funktion Probleme
macht oder ich selber Verständnisprobleme habe (worauf es in 99% der
Fälle hinausläuft).

Autor: Steffen Brüssel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Danke dir. Ich probiers.

Du wirsts nicht glauben ich konnte schonmal mit Arrays und Pointern
umgehen. Aber ich hab jetzt über 2 Jahre kein C++ oder java angefasst.
:/ Daher meine Schwierigkeiten.

Thx

Steffen

Autor: Steffen Brüssel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versteh in deinem Beispiel einiges nicht.
Wozu der Pointer pdata? Und wo zeigt er hin?
Warum machst du ne Zuweisung in ner If Anweisung?
Wenns der Compiler nimmt würde doch in pdata true oder false stehen,
oder? Normalerweise Meckerst der Compiler doch wenn in ner If-Anweisung
ne Zuweisung gemacht wird.
Eines meiner Probleme ist, dass ich keierlei Hilfe zu strstr gefunden
hab. Wo steht denn sowas? Ich weis eigendlich nichtmal was es macht. Es
wurde halt schon in anderen Programmen (hab ich in Foren gefunden) so
eingesetzt.

Gruß

Steffen

Autor: Steffen Brüssel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
vergiss was ich gesagt hab. ich weis jetzt wozu der Pointer und wo er
hinzeigt. Auch weis ich jetzt was strstr macht und bin mir sicher das
es das nicht ist was ich eigendlich will.

Ich will nicht einen Teil eines strings sondern 2 komplette Strings
vergleichen.

Peinlich: hab jetzt erst die String geschichte in der WinAVR Hilfe
gefunden.. :(

Gruß

Steffen

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hehe :)
Kein Problem, aber falls Du mal einen groben überblick brauchst, dann
nimm Dir einfach irgend ein "man", gibt etliche davon im Internet.

pdata zeigt auf das erste Vorkommen des Teilstrings "foo" oder
"bar" in data[].

Ich denke, strcmp/strncmp ist das, was Du suchst.

Autor: Steffen Brüssel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So,

das Vergleichen klappt jetzt. Allerdings musste ich mir ein
'Ende'-Zeichen vereinbaren.
Ichhab da jetzt # genommen. Schön wär's, wenn man anders erkennen
könnte wann denn schluss mit dem Empfang ist...
Vielleicht auch übern timeout... hmm...

Gruß

Steffen

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum nimmst Du nicht "Enter", also \r\n...?

Autor: Steffen Brüssel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habs schon mit '\n' probiert, aber scheinbar kommt das von
meiner c# anwendungen auf dem pc nicht als ein zeichen. sondern als
zwei. Ich werds aber mal mit 'Enter' probieren.
Bin aber grad bei nem andernen 'wichtigerem' Problem. :(

thx & Gruß

Steffen

Autor: OsiriS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Servus!

Hab genau das gleich Problem mit dem Atmega128!
Empfange auch über USART0 und schreibe die Bytes in ein array
  unsigned char Rec_Buf[255];
am Ende hänge ich dann noch ein \0 als Endemarkierung.
strncmp geht wohl irgendwie, aber die If-abfrage scheitert dann...:
Sorry, mache das gerade aus dem Kopf, hab den Code grad nicht vor
mir..
/*als globale*/
unsigned char Rec_Buf[255];
unsigned char Cmd_Help[]= "Help";
.
.
/* in main */
unsigned char Cmd[255];
unsigned char *ptr_Buf;
usnigned char *ptr_Cmd;

ptr_Buf= Rec_Buf;
prt_Cmd= Cmd;
while (*ptr_Buf) {
  *ptr_Cmd++ = *ptr_Buf++; /*damit ich nur den Befehl habe*/
}
/* also bis dahin ist alles OK, wenn ich jetzt Cmd ausgebe, kommt auch
der Befehl wieder, denn ich eingegeben habe.
Aber jetzt wirds interessant:*/

if (!strcmp(Cmd, Cmd_Help)) {
 ...puts (...);
}
/* und das geht nicht mehr.
wenn ich mir das Ergebnis von strcmp ausgebe mit puts(.. +0x30)
dann sehe ich auch, dass ascii 0 zurückkommt.
Also scheint der Vergleich ja zu passen.
Aber irgendwie gehts dann doch nicht, auch mit strncmp hab ichs schon
probiert..
Kann mir da jemand einen Tipp geben?
Der Codeschnippsel ist jetzt vielleicht nicht so der Bringer, aber ich
mach da wohl prinzipiell was falsch.
Will halt einen Befehl über Hyperterminal eingeben und
dann im Controller auswerten und darauf reagieren; wobei der Befehl
nicht immer gleich lang sein muss.

Danke mal im Vorraus*/

Grüsse OsiriS

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass das mal in einem Debugger laufen und sieh Dir genau den Inhalt
Deiner Variablen an.
strcmp vergleicht zwei nullterminierte Strings miteinander.

Dir könnte der Gebrauch von strncmp helfen (da kann die maximale
Vergleichslänge angegeben werden).

"wenn ich mir das Ergebnis von strcmp ausgebe mit puts(.. +0x30)
dann sehe ich auch, dass ascii 0 zurückkommt.
Also scheint der Vergleich ja zu passen.
Aber irgendwie gehts dann doch nicht, auch mit strncmp hab ichs schon
probiert.."
Das klingt sehr, sehr wirr. Wie gesagt - nutze einen Debugger, sieh Dir
den Inhalt Deiner Variablen an, dann sollte Dir einiges klar werden.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ich werde niemals verstehen, warum man solche elementaren
Dinge immer gleich auf der Zielplattform Testet!

Ob der "Bytestream" aus einer UART kommt oder irgendwo anders her
spielt für die Funktion str[n]cmp überhaupt_ _keine Rolle!

Mach Doch mal ein C-Programm auf einem PC, welches einfach nur die zu
erwartenden Strings vergleicht...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@OldBug,

"Ich glaube ich werde niemals verstehen, warum man solche elementaren
Dinge immer gleich auf der Zielplattform Testet!"


da geb ich Dir aber sowas von recht.

Jeder kennt die Plattformunabhängigkeit von C, aber gerade C-Anfänger
wollen sie einfach nicht nutzen.
Selbst die speziellen Speicherbereiche des Keil C51 kriegt man mit ein
paar Defines wunderschön auskommentiert.

Und wenn man ein altes DOS-Borland-C nimmt, ist da sogar eine prima
deutsche Hilfe zu jeder Funktion und den Operatoren mit dabei.


Peter

Autor: Michael (ein anderer) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@OsiriS:

Ich würde wetten, Du hast Probleme mit \0 markierungen. Denn wenn Du
einfach die Zeichen nacheinander über die serielle in einen Buffer
einliest, woher soll die String beendende Null kommen?

Autor: OsiriS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Michael (ein anderer)
@Rufus T. Firefly

Danke fuer eure konstrukiven Beiträge!
Hab den Fehler schon gefunden
Hattet gar nicht so unrecht...den Nullstring hab ich zwar
angehängt am Ende, allerdings auch das /r, das ich als "Empfangende"
verwende, das ging dann halt mit in den Vergleich ein....

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.