Forum: Mikrocontroller und Digitale Elektronik Vergleich von Teilstrings


von Marc (Gast)


Angehängte Dateien:

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

von Guru (Gast)


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.

von Marc (Gast)


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ß

von Guru (Gast)


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.

von Guru (Gast)


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.

von Marc (Gast)


Angehängte Dateien:

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...

von Serieller (Gast)


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";

von Guru (Gast)


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.

von Serieller (Gast)


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.

von Marc (Gast)


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

von Serieller (Gast)


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

von Serieller (Gast)


Lesenswert?

Mist, Copy&Paste Error

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

von Marc (Gast)


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])...

von Serieller (Gast)


Lesenswert?

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

von Serieller (Gast)


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.

von Marc (Gast)


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.

von Serieller (Gast)


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.

von Marc (Gast)


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

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
Noch kein Account? Hier anmelden.