Zeile 16 ist mir noch klar. 'string' wird als Parameter übergeben und die übergebenen 'delimiters' werden durch Null-Terminatoren ersetzt. Das schöne daran, auch wenn es mehrere Delimiters hintereinander gibt werden diese zu einem Null-Terminator zusammengefasst. Soweit ist mir das alles klar.
Voodoo ist für mich Zeile 20. Hier wird 'NULL' als string Parameter übergeben in dem dann Delimiters gegen Null-Terminatoren ersetzt werden sollen. Woher weiß strtok bzw. das Programm das es weiterhin 'string' zerlegt ausgeben soll? Geht doch gar nicht ohne angegeben Parameter. Voodoo?
Eigentlich ganz einfach. Wenn string übergeben wird, fängt strtok bei dem von vorn an.
Intern merkt sich strtok, wo es als letztes mit '\0' getrennt hat. Wenn NULL übergeben wird, dann macht es danach weiter. (also im bisherigen string nach dem '\0')
wenn sich strtok den vorher übergebenen string merkt dann ist das für mich etwas ungewöhnlich ohne nochmalige/ständige Parameterangabe. Aber wenn das so ist wie es ist okay. Danke Dir.
Es merkt sich eigentlich nicht den string, sondern den Pointer, wo es das '\0' gesetzt hat.
Der alte string in dem Sinne existiert ja nicht mehr, weil er mit '\0' geteilt wurde.
Darf ich mich mal aufregen? (in Wirklichkeit bin ich ganz ruhig)
Du bist genau auf die Scheiße/Verwirrung gestoßen, die passiert, wenn man statische Variablen in Funktionen verwendet.
Man sieht es der Funktion nicht an.
Sie funktioniert nicht im Multitasking/ISR Umgebungen, eben wegen dem Static ist sie nicht wiedereintrittsfähig/reentrant.
Abhilfe schafft strtok_r().
Falls irgendeiner, hier im Forum, noch nicht kapiert hat, dass und warum ich was gegen statische Variablen habe.
strtok() zeigt es hier nochmal deutlich!
Eine gute Funktion, hat bei identischen Parametern immer das gleiche zu tun!
strtok() tut das nicht.
das Problem mit den statischen Variablen muss jedem erstmal bewusst werden, selbst wenn man das Hundertmal liest.
Gut, dann werde ich mein bis jetzt Handgedengeltes durch strtok_r ersetzen. Mal sehen wie die Programmzeilen so schrumpfen. Dient alles meinem Parser.
Danke Euch.
Das ist wohl so....
Und ganz besonders, wenn das Static hier durchaus mehrfach am Tag, quasi jedem Anfänger ohne jede Warnung, vorgebetet wird.
Anfangs habe ich noch versucht dagegen an zu arbeiten.
Das aber mittlerweile wegen totaler Uneinsichtigkeit/Ignoranz des/der Gegenüber, weitestgehend aufgegeben.
Jetzt wird halt quasi jeder damit infiziert....
Müssen dann eben jeder selber mal das Denken aktivieren, darauf kommen und nicht nur dem jeweiligen Vorbeter hinterher rennen.
Ich würde bei der Verwendung von static etwas differenzieren wollen.
Für allgemeingültige Funktionen / Libs sollte man sie vermeiden. Ich gehe bei strtok davon aus, dass das ein Relikt aus den Anfängen von C ist.
Bei Einzweckfunktionen (Du nennst sie so schön Wegwerffunktionen) würde ich es auch nutzen, es aber im Kommentar explizit angeben. Es vereinfacht doch etwas den Aufbau.
Die Alternative wäre den Wert immer wieder per Referenz/Zeiger mit zu übergeben (wie bei strtok_r). Aber irgendwo muss diese(r) ja auch gespeichert werden und das ist in der Regel auch innerhalb einer Funktion oder global.
Oder man geht gleich zu Klassen, damit kann man das Problem der Persistenz in den Instanzen auflösen.
Richtig!
Aus der Steinzeit.
Ich möchte dafür wetten, dass man sich wenige Jahre später schon in den Hintern gebissen hat, dass man das so eingeführt hat. Und jetzt nicht mehr davon runter kommt.
Ja!
Die liegen mir nicht so.....
Mein Fokus liegt eher auf Wiederverwendung.
Ziel: Einmal schreiben, nie wieder drüber nachdenken.
Faulheit, Bequemlichkeit, aber das nur auf kurze Entfernung, ja, das ist wohl das einzige wirkliche/mächtige Argument.
Auf lange Sicht, steht man sich mit dem Umweg sicherlich etwas besser.
Ach ja, in Libs gehört sowas verboten.... eigentlich ....
wenn man eine komplette Zerlege- und Zuweisungsfunktion schreibt, die alle Einzelwerte rauszieht und entsprechend anderen Variablen zuweist, dann kann 'rest' non static bleiben. Diese Funktion fällt dann etwas größer aus, enthält alles was benötigt wird und ruft alle weiteren Funktionen auf die benötigt werden. Ist eben dann Parser spezifisch angepasst. Wobei bei einem Parser immer irgendwas speziell angepasst werden muss.
Eine reine Zeichenersetzfunktion wäre noch sowas hier,
Eine Zeichenersetzfunktion wäre noch sowas hier,
void ZeichenInCharArrayErsetzen (char *zeichenkette, const char search, const char replace)
{
size_t i {0};
while ( zeichenkette[i] != '\0') {
if ( zeichenkette[i] == search ) { // suche nach Zeichen 'search' und
zeichenkette[i] = replace; // ersetze es durch 'replace'
}
i++;
}
}
damit wird nur erstmal ersetzt und es geht nichts verloren wenn man im Gegensatz zu strtok nicht sofort den Rückgabewert verarbeitet. Ich tüftel mal weiter. Das Hauptanliegen ist ja geklärt.
Wobei ja unsere beiden Standardfunktionen setup und loop in jedem Fall für einen einzelnen Verwendungszweck geschrieben werden, als immer Wegwerffunktionen sind.
Zur Wiederverwendung sind dann eher die da drin aufgerufenen Funktionen.
Ich habe gerade nochmal in Deine INTERVALL-Macros geschaut. Da machst Du aber auch intensiv von static Gebrauch oder gibt es mittlerweile eine neue Version ohne static?
Die sind ja für Wiederverwendung gebaut?
Ja!
Darum funktionieren sie auch nicht wenn man "wiederverwendet".
Oder ineinander verschachtelt.
Auch nicht in Klassen.
oder gibt es mittlerweile eine neue Version ohne static?
Die Multitasking Macros, sind auch sehr static lastig.
Dann gibts noch die CooperativTask Dinger... (auch in der combieLib.zip lohnt sich mal anzusehen)
Dort nur noch ein einziges static.
Und das gekapselt in einem Singelton.
Davon dümpelt noch eine Variante ohne static bei mir auf der Platte. Hat sich als notwendig erwiesen, da ich mittlerweile recht viel mit 2Core µC mache.
Erst die Datenflussbetrachtungsweise, hat mich dann ganz von statischen Dingen erlöst.
Davon sind schon 4 Instanzen in meinem Download Ordner
Jedes Mal, wenn Du die im Forum einbindest, lade ich die, um immer die neueste Version zu haben.
Ich denke, gerade im loop, als Spezialfunktion (Wegwerf) können wir uns das static durchaus leisten. Da ist keine Wiederverwendung sinnvoll möglich.
Genau so, wie Du goto an manchen Stellen als sinnvoll einstufst
Als ich mit Arduino anfing, war ich über vieles verwundert. ("Aber das ist doch gar nicht reentrant".)
Bis mir klar war, dass auf einem kleinen Microcontroller ja gar nichts nebenbei läuft, was ich nicht unter Kontrolle habe. Ohne Multithreading u.ä. kann man sich das Leben sehr vereinfachen.
Man sollte sich immer bewußt sein, was man macht. Dann kann man auch strtok undd static benutzen.
Wer mit Voodoo arbeitet, weiß ja auch, was er macht, und nutzt gezielt aus, dass es anderen wie Voodoo vorkommt. Davon geh ich mal bei Voodoo-Zauberern aus.
Ja, genau. Ich sehe diese beiden Funktionen als Sonderfall, die speziell für jeden Zweck neu geschrieben werden.
Etwas Anderes sind allgemeingültige Funktionen, die man darin aufruft und daraus so eine Art Lib-Sammlung machen will. Ansonsten sollte man die Funktionen auch als speziell/Wegwerf bezeichnen.
Ich sag ja nichts, wenn @combie abfällig von Wegwerf-Funktionen redet.
Wenn man nur ein Serial hat, kann man immer zum Parsen strtok verwenden. Wenn man gleichzeitig und verschachtelt zwei Texte zerlegen will, sollte man was anderes nehmen, aber strtok nicht wegwerfen.