Go Down

Topic: Bitte um Hilfe zu "strstr-pointer" (Read 186 times) previous topic - next topic

hk007

Jan 15, 2015, 08:48 pm Last Edit: Jan 15, 2015, 08:50 pm by hk007
Hi,

schlagt mich nicht, aber ich hänge wieder an den c-strings.

Folgendes Problem:
Ich lese über die serielle einen Buffer ein. Da steht u.a.ein Datum drin. Sieht immer so aus:
'...Datum:01.01.2015...'
Dann durchsuche ich den Buffer nach der Zeichenkette 'Datum'.
Code: [Select]
           char * result = (strstr (rcvbuf, "Datum"));
           if (result) {
             Debug.println (result);
           } 


Jetzt würde ich gerne aus dem Buffer den Tag/Monat/Jahr extrahieren.
Hab mir das so gedacht:
Code: [Select]
Tag = (int(rcvbuf[x+7]-48)*10) + (int(rcvbuf[x+8]-48)*1)

Aber ich komm ums Verrecken nicht drauf, wie ich aus dem Pointer "result" die Stelle im rcvbuf (also das 'x') rausbekomme?

Wahrscheinlich ists wieder super einfach, aber das ist einfach nicht mein Spezialgebiet...  >:(
Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Serenifly

Wieso rechnest du das was per Hand? Das geht mit atoi():
http://www.cplusplus.com/reference/cstdlib/atoi/

C hat da einen ganzen Haufen Konvertierungs-Funktionen in beide Richtungen

hk007

#2
Jan 15, 2015, 09:04 pm Last Edit: Jan 15, 2015, 09:04 pm by hk007
Wieso rechnest du das was per Hand? Das geht mit atoi():
Weil ich ein lausiger C-Programmierer bin. OK, dann nehm ich atoi um einen String in eine Integer zu wandeln.

Aber mein Hauptproblem ist eigentlich, wie kann ich den Teilstring, der 7 Zeichen nach meinem Suchstring kommt aus dem Buffer extrahieren?
Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Serenifly

Das ist schon völlig ok so. Du holst dir mit strstr() einen Zeiger. Danach kannst du den Zeiger + Offet an atoi() übergeben. Also statt "rcvbuf[x+7]" machst du "rcbuf + 7"

Ich mache in einem Programm auch sowas ähnliches:
Code: [Select]

switch(serialBuffer[0])
{
  case 'C':
    byte day = atoi(serialBuffer + 1);
    byte month = atoi(serialBuffer + 4);
    int year = atoi(serialBuffer + 7);
    byte hour = atoi(serialBuffer + 12);
    byte minute = atoi(serialBuffer + 15);
    setClock(day, month, year, hour, minute);
  break;
}

Der gesendete String sieht so aus:
C15/01/2015 21:14

Dann mach ich nur ein switch auf das erste Zeichen. Und den Tag bekomme ich mit serialBuffer + 1. Die restlichen Indizes muss man dann nur entsprechend der Position im String setzen

Man kann aber genauso mit einer if-else Kette aus strncmp() oder strstr() arbeiten wenn die Unterscheidung an Hand längerer Strings macht. Aber da nur ein Zeichen zu verwenden ist einfacher




hk007

#4
Jan 15, 2015, 09:37 pm Last Edit: Jan 15, 2015, 09:41 pm by hk007
Hmm...
komm noch nicht ganz hinter deine Idee.
Nur ein Zeichen geht in meinem Fall nicht.
-> Also strstr()

Aber ich darf doch nicht meinen recbuf verwenden. Ich weiss ja nicht, wo in dem Buffer das Datum steckt.
Daher suche ich mit strstr() nach dem string 'Datum'
An atoi müsste ich doch dann den zurückbekommenen Pointer übergeben, damit ich immer mit dem selben Offset arbeiten kann.
Code: [Select]
char * result = (strstr (rcvbuf, "Datum"));
int tag = atoi(result +7);
Debug.println (tag);  


Also hätte ich es mal so probiert. Aber da bekomme ich nichts angezeigt.
Verstehe auch nicht ganz, woher die atoi.Funktion weiss, dass sie zwei Zeichen nehmen soll um daraus eine Integer zu konvertieren.

Nebenfrage:
Kann man den Pointer von strstr() nicht so umwandeln, dass er eine Zahl zurückgibt, die angibt, an welcher Stelle im String der Suchstring beginnt?
Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Serenifly

#5
Jan 15, 2015, 09:49 pm Last Edit: Jan 15, 2015, 09:52 pm by Serenifly
Ich sende halt keinen String mit mehreren Kommandos, sondern schließe jedes Kommando mit einem LF ab. Dann wird jedes für sich behandelt auch wenn man mehrere direkt hintereinander sendet.

Was falsch ist, ist das + 7. Es muss + 6 sein. 0 ist das 'D'. Dann 6 weiter und man ist bei der Zahl. Das geht in Visual C++:
Code: [Select]

char str[] = "blah blah Datum:31.01.2015";
char* date = strstr(str, "Datum");
int day = atoi(date + 6);



atoi() hört auf wenn es auf ein Zeichen trifft das keine Zahl ist. Steht so in der Doku:
Quote
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
Quote
Kann man den Pointer von strstr() nicht so umwandeln, dass er eine Zahl zurückgibt, die angibt, an welcher Stelle im String der Suchstring beginnt?
Inzwischen hast du vielleicht gemerkt dass man mit Zeigern rechnen kann. Du musst also nur den gefundenen Zeiger Minus die String Variable machen (welche ein Zeiger auf das erste Zeichen im String ist), bzw. in diesem Fall die Puffer Variable.

hk007

Hi,
alles verstanden. Auch das mit dem Rechnen  :)
Code: [Select]
char * result = (strstr (rcvbuf, "Datum"));
int tag = atoi(result +6);
Debug.println (tag);                                         --> Ausgabe "15" (also den Tag als INT)
Debug.println (result-rcvbuf);                               --> Ausgabe "20" (an dieser Stelle steht das Wort Datum)
Debug.print (rcvbuf[(result-rcvbuf)+6]);                     --> Ausgabe "15" (den Tag als 2 Zeichen)
Debug.println (rcvbuf[(result-rcvbuf)+7]);



Danke dir mal wieder  :)
Arduino 1.0.5 | Arduino UNO & MEGA | Arduino 1.54r2 mit DUE

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy