Hallo,
als blutiger Anfänger in Sachen 'C' mit AVR versuche ich den String
einer GPS-Maus zu lesen.
Das klappt eigentlich schon gut, nun will ich ihn in seine Bestandteile
zerlegen.
Ich habe ein paar Beispiele mittels der Suche gefunden, fast alles ist
aber mit Bascom gemacht.
Auch habe ich ein paar wenige Beispiele mit der C-Funktion strtok
gesehen, die gibt es aber beim AVR nicht (heißt wohl strtok_r).
Kann mir bitte jemand ein einfaches, nachvollziehbares Beispiel geben,
mit dem ich einen empfangenen String der GPS-Maus in seine Bestandteile
zerlegen kann,
so dass jeder Teilstring in einem eigenen String gespeichert wird?
Vielen Dank,
Jürgen
Hallo Jürgen,
das kann man so pauschal nicht sagen. Es kommt immer darauf an, was du
mit den einzelnen Teilstrings machen möchtest. Die Zeichen die du
empfängst sind ja ascii Zeichen. Wenn du also was mit ...,1234,...
empängst, kannst du zum beispiel einer Variable nicht einfach den String
zuweisen, sondern musst ihn erst mal konvertieren.
Sag uns doch einfach mal, was du so vor hast mit den Informationen von
der GPS Maus. Willst du sie nur wieder irgendwo anzeigen oder verwerten?
Gruss
Nils
da es ein langer string ist der meist mit ',' getrennt ist kann man
danach suchen
char *temp;
temp = strchr( ****string , ',' );
temp is dann ein zeiger auf das erste komma
wenn man nun das ganze wiederholt aber anstatt dem string den zeiger+1
übergibt
sucht man weiter im string das nächste komma
zB geht das so .. gibt aber noch andere möglichkeiten
Den möchte ich zerlegen, so dass ich nachher neue Strings habe:
Zeit = "191410"
Breitengrad = "4735.5634"
Laengengrad = "00739.3538" usw.
Vielen Dank,
Jürgen
ich wäre für eine elegante strchr lösung ^^
hatte einmal sprint und so genutzt ..
allein das einbinden der lib stört mit seinen >500byte doch etwas
bei 500bate bekommt man locker das mit den normalen stringfunktionen hin
inkl umwandlung mit atoi und CO
Die 10 ist übrigens an mindestens einer Stelle zu knapp....
Man kann das testen lassen, indem man statt
1
%[^,]
besser:
1
%9[^,]
angibt; dann werden maximal 9 Zeichen verwendet (und damit ist
noch Platz für die abschließende 0 im Puffer bei 10 Zeichen).
Reicht das nicht, bricht sscanf() ab und liefert dann nicht 13
zurück, sondern entsprechend weniger.
gast schrieb:
> ich wäre für eine elegante strchr lösung ^^>> hatte einmal sprint und so genutzt ..> allein das einbinden der lib stört mit seinen >500byte doch etwas>> bei 500bate bekommt man locker das mit den normalen stringfunktionen hin> inkl umwandlung mit atoi und CO
Das ist wahr; dann ist aber strtok() einfacher und braucht auch
nicht viel Platz. Letztlich macht sie ja auch nichts anderes,
als nach dem Trennzeichen zu suchen und mit einer terminierenden
0 zu überschreiben.
strtok_r kann man dann auch verwenden; allerdings muß man das if
davor ändern. strtok_r() liefert dann nämlich NULL (was in meinem
Beispiel als Fehler interptetiert wird).
Klaus Wachtler schrieb:
> strtok_r kann man dann auch verwenden; allerdings muß man das if> davor ändern. strtok_r() liefert dann nämlich NULL (was in meinem> Beispiel als Fehler interptetiert wird).
Hallo,
ich grab den Beitrag mal wieder aus.
bin ein ziemlicher Fan von strtok(), obwohl dieser bei NMEA-Strings den
ersten token überspringt und destruktiv arbeitet, ist er sehr schnell.
habe aber das Problem, dass strtok() nicht mit 'leeren Strings' zwischen
zwei Kommas zurechtkommt.
Kann mir jemand helfen und sagen wie man den Code von Klaus Wachtler
umändern muss, dass strtok_r() den Bereich zwischen 2 Kommas (",,")
nicht überspringt?
gruss,
defi
Danke für den link.
Bei der Statemaschine sind aber nur wenige NMEA Variablen integriert, um
alle Variablen aus den verschiedenen NMEA-Sätzen auszulesen dauert es
sehr lange.
Ich denke, dass strtok immer noch die beste Methode wäre, wenn das
Problem mit den 2 Kommas nicht wäre.
Na ja, so einen "strtok Ersatz" hat man aber auch schnell selber
gemacht.
ungetestet:
1
char*part;
2
char*pLoop;
3
charString[]="a,b,,c,d";
4
uint8_tfinished=false;
5
6
7
pLoop=String;
8
9
while(!finished){
10
11
// pLoop zeigt auf den Anfang des nächsten Eintrags
12
// wenn es keinen mehr gibt, dann ist *pLoop == 0
13
14
if(*pLoop){
15
// hier beginnt der Teilstring
16
part=pLoop;
17
18
// weiter bis zum Trennzeichen
19
while(*pLoop&&*pLoop!=',')
20
pLoop++;
21
22
// am Ende angelangt ?
23
if(*pLoop=='\0')
24
finished=true;
25
else
26
// den String dort unterteilen, so dass part einen gültigen
27
// Teilstring ergibt
28
*pLoop='\0';
29
30
// mach was mit part
31
printf("%s\n",part);
32
33
// und die Voraussetzung für den nächsten Schleifendurchlauf
34
// schaffen: pLoop zeigt auf den Anfang des nächsten Teilstrings
35
pLoop++;
36
}
37
}
letzten Endes hast du keine grossen Anforderungen an den strtok Ersatz.
Das ist einfach nur eine while-Schleife, bis das nächste Trennzeichen
auftaucht. Pointer auf Anfang des Teilstrings, while-Schleife bis zum
Trennzeichen, dort eine '\0' rein und man hat den Teilstring. Ein
bischen aufpassen muss man noch, dass es zu keinen Komplikationen kommt,
wenn kein Trennzeichen mehr gefunden wird und das wars dann auch schon.
So, jetzt wärme ich die Geschichte nochmal auf.
Ich hatte vor etlichen Tagen eine PM dazu bekommen wg. Leertoken
und strtok().
Leider kam ich erst nicht dazu und habe inzwischen versehentlich
die Mail gelöscht; sie war wohl von defi, sorry.
Meine Behauptung, daß strtok* mit leeren Token sinnvoll umgehen
würde, war voreilig.
Als Friedensangebot hier eine eigene Variante (viel kompakter
dürfte es nicht gehen; Ring frei!):
Wenn ich das richtig sehe, wird aber ein leeres Token am Ende damit
nicht geliefert ("t1,t2,t3,")?
Dazu müsste man das if entfernen und dessen Rumpf aber stehen lassen.
Dann wird es sogar noch einfacher...
Jürgen schrieb:> Sehr schön. Aber wie übergebe ich nun einen Teilstring an eine int-> Variable?
Gar nicht.
Wozu soll das denn gut sein?
Ein Teilstring ist erst mal ein String. Er enthält eine Zeichenkette, zb
"Hermann Müller".
Eine int Variable ist eine Variable die Zahlen aufnehmen kann, zb 42
Das passt aber nicht zusammen. Ein String ist nicht etwas, was in einer
int Variablen gespeichert werden könnte.
Es kann natürlich sein, dass dein Teilstring die Textrepräsentierung
einer Zahl enthält. Das zb der String anstelle von "Hermann Müller" den
Text "126" enthält. Auch das ist erst mal nur ein Text. Aber es ist ein
Text aus dem man sinnvoll eine Zahl bilden kann, nämlich die Zahl 126
Und genau das macht zb die Funktion atoi. (zu lesen als "A to I", also
ASCII to Integer)
Man übergibt ihr einen Pointer auf den Start eines Strings und die
Funktion versucht da eine Zahl 'herauszuholen', sofern der String mit
einem Zeichen beginnt, das das erste Zeichen einer Zahl sein könnte.
Vielleicht tu ich dir aber auch unrecht und du bist gar nicht der
Jürgen, der den Thread eröffnet hat. Auf der anderen Seite ist es aber
auch ziemlich unwahrscheinlich, dass sich ausgerechnet ein anderer
Jürgen diesen Thread wieder ausgegraben hat.
Der springende Punkt ist aber: Seit Juli letzten Jahres war es dir nicht
möglich ein C-Buch zu kaufen und zumindest das erste Drittel
durchzuarbeiten?
Na dann Prost!
Da dieser Threat sich um die Werte eines Positions-Protokolls einer GPS-
Maus dreht, liegt doch nahe, wozu das gut sein soll.
Trotzdem vielen Dank, Karl-Heinz
Jürgen schrieb:> Da dieser Threat sich um die Werte eines Positions-Protokolls einer GPS-> Maus dreht, liegt doch nahe, wozu das gut sein soll.
Darum geht es nicht.
Es geht darum wozu es gut sein soll "einen String in einer Int Variablen
abzulegen".
Das ist ungefähr so, wie die Fragestellung: Wie mache ich meine 45 Meter
Segleyacht in meiner 3 Meter PKW-Garage fest.
Es geht nicht darum, warum du ausgerechnet deine Yacht in die Garage
haben willst (weil du sie vor Wind und Wetter schützen willst), sondern
es geht darum, dass es keinen sinnvollen Grund gibt ein 45 Meter Objekt
in eine 3 Meter "Schachtel" quetschen zu wollen, die noch nicht mal dazu
gedacht ist etwas anderes als einen PKW aufzunehmen. Jeder, der den
Unterschied zwischen einer Segelyacht und einem PKW kennt, leuchtet
unmittelbar ein, dass die ursprüngliche Fragestellung eine sinnlose ist.
Im Umkehrschluss kann man dann folgern, dass dem Fragesteller daher
nicht klar ist, dass eine Segelyacht (noch dazu eine große) etwas andres
ist als ein Fiat Panda. Entweder das oder die Fragestellung wurde extrem
unglücklich formuliert.
Mit ist schon klar, was du eigentlich fragen wolltest. Daher habe ich
dann auch die Frage beantwortet, die du eigentlich stellen wolltest,
aber in Unkentnis der Situation nicht gestellt hast. Und angesichts der
Zeiträume konnte ich mir dann auch einen kleinen Seitenhieb nicht
verkneifen.
Die Lösung (atoi) ist ja zum Glück da.
Karl heinz Buchegger schrieb:> Es geht darum wozu es gut sein soll "einen String in einer Int Variablen>> abzulegen".
Die Funktion (atoi) tut doch genau das, was ist denn daran unsinnvoll?
Übertragen: ich falte meine Dreimastbark auf handliche Garagengröße,
sodass sie immernoch ein Segelschiff ist, aber in meine Garage passt,
schließlich hab ich keine Pier im Garten.
Mit ganz viel Phantasie könnte ich mir vorstellen, man könne meine Frage
so interpretieren, dass ich versuche, $GPRMC in eine Int-Variable zu
konvertieren.
Da gehört schon viel negatives Denken zu.
Na dann übergib atoi doch mal den String
"124395856743635342648583624274957465" und lass den in 'ner int
Variablen "ablegen"...
Es geht einfach darum das atoi eben nicht den String in einer Int
Variablen ablegt, sonder ihn hernimmt, und versucht eine konvertierung
durchzuführen.
Also nimmst du einen Teilstring und "übergibst" den an atoi, und kriegst
dan (hoffentlich) die gewünschte Zahl.
Jürgen schrieb:> Die Lösung (atoi) ist ja zum Glück da.>>>> Karl heinz Buchegger schrieb:>> Es geht darum wozu es gut sein soll "einen String in einer Int Variablen>>>> abzulegen".>> Die Funktion (atoi) tut doch genau das, was ist denn daran unsinnvoll?
Du verstehst es immer noch nicht, oder?
Wenn man sich an den Buchstaben des geschriebenen Wortes hält, dann ist
die Fragestellung
"Aber wie übergebe ich nun einen Teilstring an eine int-Variable?"
lediglich mit einem simplen "Gar nicht" zu beantworten.
Auch atoi vollbringt keine Wunder und quetscht einen Teilstring in eine
int-Variable.
Was aoti macht ist: Es sieht sich den Teilstring an und versucht ihn als
Textrepräsentierung einer Zahl aufzufassen. atoi liefert dir die Zahl,
deren Textrepräsentierung im String steht (sofern da überhaupt eine Zahl
drinnen steht).
aoti kovertiert die Textrepräsentierung einer Zahl in die Zahl selber.
Und diese Zahl kannst du dann in deiner int-Variablen ablegen, oder was
weiß ich alles damit machen, was man eben mit Zahlen so machen kann.
Das Zauberwort ist: Da ist eine Konvertierung beteiligt!
Das ganze ist ein mehrstufiger Prozess
Konvertierung Abspeichern in
in eine int-Zahl der int-Variablen
Text -----------------------> int ----------------------> int
wird von atoi wird durch die
erledigt Zuweisung erledigt
Es geht im weitesten Sinne darum, dass du dich korrekt ausdrückst, wenn
du nach etwas fragst. Ansonsten bringt dir jemand einen
Schraubenschlüssel, wenn du nach einem Werkzeug aus Stahl frägst, mit
dem man Nägel in die Wand schlagen kann. Denn ein Hammer hat einen Stiel
aus Holz und den hast du mit deiner Frage nach einem Werkzeug aus Stahl
ausgeschlossen. Selbst dann, wenn deine ursprüngliche Überlegung war,
keinen Gummihammer zu bekommen.
Und wenn du denkst, das das ja wohl egal ist ob du dich korrekt
ausdrückst oder nicht, dann wirst du in der Programmierung Schiffbruch
erleiden. Denn ein Computer ist ein Gerät, dass deine Befehle
wortwörtlich befolgt. Für einen Computer gilt "Do what I write" und
nicht "Do what I mean"
Ach von daher weht der Wind.
"Natürlich" weiss ich vorher, welchen Teil des Strings ich einsammeln
und zur int machen möchte (nämlich die Geschwindigkeit), und dass dieser
Teil in eine int reinpasst..