www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Vergleich von Teilstrings


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

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte gerne ein Teil eines über den UART empfangenen Strings 
vergleichen.
Ändert sich der Teilstring, so soll ein Counter erhöht werden.
sprich ich will den ersten empfangenen String mit compare_string
vgl. wenn beide ungleich sind, soll der Counter erhöht werden.

Allerdings sende ich immer alle von alarm_data empfangenen 
Teilstrings...Wäre dankbar, wenn mir hierbei jemand weiterhelfen könnte.
Grüße

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider schreibst Du nicht, was nun eigentlich das Problem ist.

Du formulierst auch leider etwas ungeschickt. Zum einen ist mit:

>Ändert sich der Teilstring ...
nicht klar, ob Du zwei zeitlich hintereinander eingehende Strings meinst 
oder zwei Teilstrings die zusammen hereingekommen sind. Nach erstem 
Überfliegen Deines Codes meinte ich, dass das letztere zutrifft.

und in
>Allerdings sende ich immer alle von alarm_data empfangenen
>Teilstrings
wird der Variable alarm_data eine Aktivität (das empfangen) 
zugeschrieben, was sinnlos ist, denn eine Variable führt nichts aus und 
Du sprichst davon das "Du" etwas tust anstelle des Rechners.
Diese drei Punkte sind für sich genommen schon irgendwie pragmatisch 
deutbar, eher ungeschickt, bedeuten aber eine Unsicherheit die sich 
durch die Anzahl so akkumuliert, dass der ganze Text als Darstellung 
zweifelhaft wird.

Wie gesagt: Der Hauptpunkt ist, das das Problem nicht genannt ist.


Auffällig ist aber, dass compare_data keine Daten enthält, wenn Du 
strcmp aufrufst, denn die Variable wird auf dem Stack angelegt, so das 
höchstens irgendwelche zufälligen Daten dort stehen, aber nichts 
"bestimmtes".
Evtl. hast Du hier ein static vergessen. Der Code der Daten in 
compare_data umkopiert muss natürlich auch mindestens einmal ausserhalb 
der Funktion vorhanden sein.

Noch ein kleiner Verbesserungstip:
Die Schleifen zum umkopieren könntest Du durch strncmp ersetzen.

Mehr fällt mir nicht auf.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Guru,
sorry, du hast Recht, dass ist wirklich blöd formuliert.
Also im Grunde möchte ich den empfangenen Teilstring(alarm_data) mit dem 
vorherigen, in compare_data abgelegten, String vergleichen.

Unterscheidet sich der neue String vom alten (in compare_data abgelegt), 
so soll der counter erhöht werden und der neue String in compare 
abgelegt werden. Im Grunde immer ein Vgl. mit dem vorherigen String.

Allerdings macht das mein Programm nicht und sendet einfach nur die 
aktuellen Strings alarm_data.

Gruß

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha. Ich hab Dir ja Tips gegeben. Schau sie Dir mal an.

Es gibt zwei Punkte die Du beachten musst:

1. Was macht das Programm wenn zuvor noch garnichts empfangen wurde? 
Z.B. unmittelbar nach einem Reset. Du musst die Variable, die den vorher 
empfangenen String speichert passend initialisieren. Z.B. mit '\0'.
2. Wie sorgst Du dafür, das der vorher empfangene String gespeichert 
bleibt? Hier entweder static oder globale Variable.

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Allerdings macht das mein Programm nicht und sendet einfach nur die
>aktuellen Strings alarm_data.

Das könnte auch problemunangemessen formuliert sein. Nach dem Code ist 
es ja gerade Absicht, das der aktuelle String in alarm_data gesendet 
wird. Ich vermute aber das Problem ist, das der String "jedesmal" 
gesendet wird, als wenn er "jedesmal" unterschiedlich ist.

Das hängt mit dem obigen Tip zusammen, das die Variable ihren Inhalt 
nicht hält wenn die Funktion verlassen wird. Also fehlt static bzw. die 
Deklaration im globalen Namensraum.

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo Guru,

zunächst einmal vielen Dank für deine Tipps.

>Der Code der Daten in
>compare_data umkopiert muss natürlich auch mindestens einmal ausserhalb
>der Funktion vorhanden sein.

Das versteh ich nicht ganz. Weshalb?

stringbuffer ist ja ne globale Variable, von der ich die Daten in 
alarm_data kopiere. wenn ein kompletter String empfangen wurde, wird 
system_data == 1 und ich springe in die Funktion.

 Gut, compare_data habe ich nun mal static gemacht und mit '\0' 
initialisiert. Allerdings klappt es immer noch nicht. Hmmmmm, zum Haare 
raufen...

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  if(system_data == 1)

Wenn system_data in einer ISR (UART RX?) gesetzt wird, muss es bei der 
Definition volatile gekennzeichnet sein.

>    // 10 Zeichen aus globalem Puffer stringbuffer
>    // in lokalen Puffer alarm_data kopieren
>    j = 0;
>    for( i = 32; i< 42; i++)
>    {
>      alarm_data[j] = stringbuffer[i];
>      j++;
>    }
>    alarm_data[j] = '\0'; // <== #1

Zeile #1 zerstört dir das 10. Zeichen im lokalen Puffer!

>  char alarm_data[10];
>  char compare_data[10];
>  ...
>    if( strcmp(alarm_data,compare_data) != 0 )

compare_data[] ist nie initialisiert. Der Stringvergleich damit ist 
witzlos.

Wenn du immer mit dem vorherigen Aufruf der Funktion vergleichen 
willst, benutze eine statische Variable und u.U. einen Defaultwert fürs 
leichtere Debuggen

> static char compare_data[10] = "LEER";

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Allerdings klappt es immer noch nicht. Hmmmmm, zum Haare raufen...

Bitte analysiere einmal selbst das Problem. Schau' Dir genau an was 
geschieht. Nimm den Simulator, baue Debug-Ausgaben ein. Lies die 
Funktionsbeschreibungen, lies ein C-Buch.
Ich habe Dich schon in die richtige Richtung gedreht, aber nun möchte 
ich, dass Du alleine läufst.

Noch ein kleiner abschliessender Tip:
Schau Dir genau an, wie der Vergleich beim ersten und bei den folgenden 
Malen abläuft, was verglichen wird und was das Ergebnis ist.

So. Ich halte mich dann mal raus.

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>    if( strcmp(alarm_data,compare_data) != 0 )

Kann schief gehen, wenn in stringbuffer Nullbytes enthalten sind. Die 
for-Schleife kopiert 10 Bytes ohne Rücksicht auf Nullbytes. Aber die 
strcmp()-Funktion beendet beim ersten Nullbyte in einem der beiden 
Puffer den Vergleich.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habs hin bekommen und es läuft sowit auch ganz gut.
eine Verständnisfrage habe ich allerdings noch und ich würde mich 
freuen, wenn mir diesbezüglich jemand weiterhelfen könnte.

Wenn ich folgendes ausführe, lade ich ja zunächst meine Daten in 
alarm_data (char alarm_data[15])...

j = 0;
for( i = 32; i < 42; i++)
{
        alarm_data[j] = stringbuffer[i];
  j++;
}

  j++;
  alarm_data[j] = '\0';

...und erhöhe mein Puffer dann nochmal um eins, um '\0' reinzuschreiben. 
So klappt das auch mit dem strcmp perfekt.

Nur wenn ich jetzt diese Variante wähle, klappt es nicht. Nach 
durchlaufen der for-Schleife, ist j=10. Es muss so ja auch funktionieren 
indem ich das zusätzliche Zeichen aus dem stringbuffer einfach mit '\0' 
überschreibe. Allerdings klappt es nicht so richtig.

j = 0;
for( i = 32; i <= 42; i++)
{
        alarm_data[j] = stringbuffer[i];
  j++;
}

  alarm_data[j] = '\0';

Welchen Denkfehler mach ich da, ich komm nicht drauf

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>  char alarm_data[10];
> for( i = 32; i <= 42; i++)
> {
>   alarm_data[j] = stringbuffer[i];
>   j++;
> }
> alarm_data[j] = '\0';

i   j
======
32  0
33  1
34  2
35  3
36  4
37  5
38  6
39  7
40  8
41  9
42  10 alarm_data[j ist 10] = '\0'; 1. Bufferoverflow
-- for wird verlassen
alarm_data[j ist 10] = '\0'; 2. Bufferoverflow

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mist, Copy&Paste Error

42  10 alarm_data[j ist 10] = stringbuffer[i ist 42]; 1. Bufferoverflow

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Serieller,
ich hab aber char alarm_data[15]!

>Wenn ich folgendes ausführe, lade ich ja zunächst meine Daten in
>alarm_data (char alarm_data[15])...

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und nach der for-Schleife ist j 11, also
alarm_data[j ist 11] = '\0'; 2. Bufferoverflow

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich hab aber char alarm_data[15]!

Wusste ich nicht. In den bisherigen Fragen tauchte immmer ein Array mit 
Größe 10 auf.

>Wenn ich folgendes ausführe, lade ich ja zunächst meine Daten in
>alarm_data (char alarm_data[15])...

Dieses Codestück habe ich in deinen Fragen noch nie gesehen.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry,
nach deinem Post vom
>Datum: 16.03.2011 14:04
habe ich das abgeändert. Deswegen bin ich jetzt auch so verwirrt, das es 
nicht klappt.

Autor: Serieller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Code oben in Variante 2 kopiert 11 Zeichen aus stringbuffer ab 
Position 32 bis einschliesslich 42 nach alarm_data und schliesst 
alarm_data mit einem Nullbyte ab.

Deine These "Es muss so ja auch funktionieren indem ich das zusätzliche 
Zeichen aus dem stringbuffer einfach mit '\0' überschreibe." ist falsch. 
Das Nullbyte wird in obigem Code angehängt und überschreibt nicht.

Autor: Marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha, ok.
Sprich, bei einem Buffer alarm_data[15]...

>j = 0;
>for( i = 32; i < 42; i++)
>{
>        alarm_data[j] = stringbuffer[i];
>  j++;
>}

> j++
>  alarm_data[j] = '\0';

... müsste ich nicht noch zusätzlich

> j++
>  alarm_data[j] = '\0';

ausführen/schreiben, da das automatisch gemacht wird...VG und vielen 
Dank für deine Antworten

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.