Datum:
Hallo, ich habe ein Problem, bei dem ich nicht weiterkomme. Ich habe die Suche schon benutzt, genauso wie Google. Aber ich denke es ist zu speziell. Es geht um folgendes: Ein ATmega32 soll Schrittmotoren für eine CNC-Fräse steuern. Die Steuerungsbefehle in Form von G-Code bekommt der Controller von einem angeschlossenen Computer. Jetzt möchte ich mein Programm für den Controller etwas umbauen um mehr Performance rauszuholen. Im Programm des Controllers kommt dieser irgendwann an die Stelle, an der er den G-Code verarbeitet. Für folgende Beispiele wird folgender G-Code angenommen: G01 X12.125 Y20.7123 Bisher sah es so aus:
int value = (int)strtol(valStart, &valEnd, 10); |
wobei valStart ein Pointer ist, der auf den ersten Char nach zugehörigem Befehl zeigt. Zu Beginn also auf '0' (gehört zu "G01"). Die Funktion wertet die Zeichenkette bis zum Vorkommen des ersten ungültigen Zeichens aus. In dem Beispiel das Leerzeichen vor X. Die Variable "value" enthält danach also den Wert "1". Und so weiter. Für Befehle wie X, Y, Z etc. wird natürlich die äquivalente Funktion
float value = (float)strtod(valStart, &valEnd); |
ausgeführt. In beiden Fällen, schreibt die Funktion in valEnd die Stelle des Endes der ausgewerteten Zahl der G-Code Zeichenkette hinein. Ist äußerst praktisch, weil man mit der Überprüfung
if(valEnd - valStart) {
...
} |
sicherstellen kann, dass eine gültige Zahl erkannt wurde. Jetzt kommt mein eigentliches Anliegen: Ich möchte die Funktionen strtol und strtod ersetzen durch eine eigene Funktion um Kommazahlen ganz zu vermeiden. Diese soll dann bei X12.125 z.B. 1940 zurückgeben (die Anzahl der Schritte). Die Auswertung und so weiter klappt alles. Jedoch bekomme ich es nicht hin, dass die Funktion die Endstelle in valEnd schreibt. Bei mir sieht der Funktionsrumpf so aus (ähnlich wie strtol):
int decode(const char * str, char ** endptr); |
Und in der Funktion wird am Ende, nachdem alles verarbeitet wurde folgender Code ausgeführt:
**endptr = *str; |
Aufgerufen wird meine Funktion mit:
valEnd = valStart;
int value = decode(valStart, &valEnd); |
Doch das Problem ist, dass valStart und valEnd immer gleich sind. Die Funktion arbeitet korrekt und gibt das richtige Ergebnis zurück. Jedoch kann ich die Überprüfung:
if(valEnd - valStart) {
...
} |
nicht vornehmen, weil die Aussage jedesmal 0 ergibt. Ich habe die Sache mit Pointer und Pointer auf Pointer etc. nicht ganz drauf, deswegen seht es mir nach, wenn der Fehler offensichtlich ist und ich nicht drauf komme. Ich hoffe ihr könnt mir helfen. Vielen Dank im voraus und einen schönen Sonntag.
Datum:
Mit dem **endptr = *str; weist du ein char zu. Du willst doch aber die Adresse von diesem Zeichen haben. Also str selber. Darum [c}*endptr = str;[/c]
Datum:
DirkB schrieb: > Mit dem **endptr = *str; weist du ein char zu. > Du willst doch aber die Adresse von diesem Zeichen haben. Also str > selber. > Darum >
*endptr = str; |
Ok, verstehe...ich benutze ja auch *str um die Chars auszuwerten. Hätte mir auffallen können. Wenn ich deinen Vorschlag anwende, bekomme ich folgende Fehlermeldung: error C2440: '=': 'const char *' kann nicht in 'char *' konvertiert werden Lasse ich im Funktionsrumpf das const weg, so dass er wie folgt aussieht:
int decode(char * str, char ** endptr); |
So klappt es! Jetzt ist mir nicht klar, warum in der strtol Funktion der Pointer als const char übergeben wird. Hat dazu jemand eine Idee? Habe den Funktionsrumpf nämlich einfach so übernommen. Vielen Dank schonmal. So kann ich jedenfalls erst einmal weiter tüfteln.
Datum:
Tarek T. schrieb: > Wenn ich deinen Vorschlag anwende, bekomme ich folgende Fehlermeldung: > > error C2440: '=': 'const char *' kann nicht in 'char *' konvertiert > werden > > Lasse ich im Funktionsrumpf das const weg, so dass er wie folgt > aussieht: > >
int decode(char * str, char ** endptr); |
> du hättest eher den endptr zu einem const char ** endptr machen sollen. > So klappt es! Jetzt ist mir nicht klar, warum in der strtol Funktion der > Pointer als const char übergeben wird. Hat dazu jemand eine Idee? Natürlich. Damit du die Funktion auch mit einem String-Literal benutzen kannst. int value = (int)strtol("G08", &valEnd, 10); denn dieser String IST konstant und die Funktion darf ihn nicht verändern. Das const macht genau diese Zusage. "Ich werde die Character selber nicht verändern".
Datum:
Karl Heinz Buchegger schrieb: > Natürlich. > Damit du die Funktion auch mit einem String-Literal benutzen kannst. > > int value = (int)strtol("G08", &valEnd, 10); > > denn dieser String IST konstant und die Funktion darf ihn nicht > verändern. Das const macht genau diese Zusage. "Ich werde die Character > selber nicht verändern". Ok, verstehe. Das macht bei strtol evtl. noch Sinn, da es dort vorkommen kann. In meinem Fall jedoch, wird als Argument nie eine konstante Zeichenfolge übergeben. Deshalb kann ich die const Definition im Funktionsrumpf getrost weglassen. Danke für die Erklärung.
Datum:
Tarek T. schrieb: > Ok, verstehe. Das macht bei strtol evtl. noch Sinn, da es dort vorkommen > kann. In meinem Fall jedoch, wird als Argument nie eine konstante > Zeichenfolge übergeben. Deshalb kann ich die const Definition im > Funktionsrumpf getrost weglassen. Kannst du. Allerdings stellst du dir die falsche Frage. Bei const geht es (in einer Funktionsdefinition) immer darum, welche Zusage eine Funktion an den Aufrufer machen kann. Verändert deine Funktion den String? Höchst wahrscheinlich wird sie das nicht tun. Sie sucht ja nur etwas aus dem String heraus, das ist ja keine Veränderung. Daher kann diese Funktion die Zusage machen: Was immer du mir gibst, ich werde es nicht verändern. An dieser Stelle ist das const also keine Forderung an den Aufrufer (du MUSST mir einen double geben), sondern eine Zusage! Und wenn Funktionen diese Zusage machen können, dann sollten sie das auch tun. Denn wenn du dann tatsächlich mal innerhalb der Funktion irrtümlich versuchst den String selbst zu ändern, dann klopft dir der Compiler auf die Finger. Dieses const kostet dir nichts. Du musst es nur richtig machen. Aber für die Funktion und dessen Arbeit hat es bei dir keinerlei Auswirkungen, ausser dass du dir eine zusätzliche 'Sicherheitsebene gegen eigene Fehler' einziehst, die vom Compiler überwacht wird.