Hi, ich hab mal wieder eine Frage: ich hab eine Funktion, die in einem String einen Platzahlter gegen einen anderen String ersetzen soll. Aufgrund der Probleme hab ich die nun mal abgespeckt und suche nur noch nach dem string. void StringReplace(char* string, const char* find, char* replace) { char* pos; pos = strstr(string, find); if (pos) { strcpy(string, pos); } } Die Platzhalter (parameter find) lege ich als konst. Strings im progmem an, wie in den FAQs beschrieben: PGM_P placeholders[] PROGMEM = {placeholder_weight, placeholder_weight_test}; void GetPlaceHolder(char* buffer, int index) { PGM_P p; memcpy_P(&p, &placeholders[index], sizeof(PGM_P)); strcpy_P(buffer, p); } Der Aufruf von StringReplace erfolgt dann so in einer Funktion: ... char buffer[20]; char buffer1[20]; GetPlaceHolder(&buffer[0], 0); GetPlaceHolder(&buffer1[0], 1); StringReplace(&(display.content_text[0]), &buffer[0], &buffer1[0]); ... De gesuchte String wird aber nicht gefunden, obwohl enthlaten. Ändere ich die Funktion hingegen so ab: void StringReplace(char* string, const char* find, char* replace) { char buf[5]; char* pos; buf[0] = '#'; buf[1] = 'w'; buf[2] = 'm'; buf[3] = '#'; buf[4] = 0; pos = strstr(string, &buf[0]); if (pos) { strcpy(string, pos); } } Wird der Suchstring gefunden. Auch der Aufruf von StringReplace mit PSTR("#wm#") oder "#wm#" bringt nicht das gewünschte Ergebnis. Was mache ich hier falsch? Danke schonmal, Christian
Sag doch mal bitte: - Was übergibst Du deiner Funktion? - Was kommt dabei raus? - Was soll rauskommen? Feadi
PGM_P p; memcpy_P(&p, &placeholders[index], sizeof(PGM_P)); ??? Du glaubst dass du ins Flash schreiben kannst? Ne, memcpy_P liest aus dem Flash und kopiert ins RAM.
Hi, Wieso schreibe ich ins flash? Das ist das Originalbeispiel aus den FAQs, das zeigt, wie man aus dem Flash ins Memory schreibt. Wie kommst Du darauf, das hier irgendwas ins Flash kopiert wird oder werden soll? Man sieht in dem ersten Beitrag ganz klar, welche strings aus dem Flash kommen. Das sind genau find und replace. Geschrieben wird ausschließlich in die Variable string, wobei das Schreiben, wie ich bereits beschrieben habe, nicht das Problem ist sondern vorher der string search. Die Funktion StringReplace erklärt sich von selbst. Man übergibt einen string (null terminiert), sowie zwei weitere strings (find, replace). In der abgespeckten Version oben soll die funktion in string nach find suchen (strstr) und wenn gefunden, dann wird hier zur Vereinfachung in string erstmal einfach der Teilstring kopiert, der gefunden wurde. Was ich an die Funktion übergebe ist oben ausführlich beschrieben, ebenso was ich erwarte, das passieren soll. Ebenso ist beschrieben, dass es mit dem Beispiel aus den FAQs nicht funktioniert, mit dem setzen der einzelnen chars aber schon. Die zentrale Frage ist und bleibt (uunabhängig von allen funktionen oben): Wieso funktioniert strstr nicht, wenn ich dort eine String aus dem Flashram gemäß der Anleitung aus den FAQs übergebe, wohl aber, wenn ich diesen String einzeln per characters zusammenbaue? Ich weiss, dass ich nicht ins flash schreiben kann und beabsichtige auch nicht, dies zu tun. Ich will lediglich in einem String mit einem Platzhalter diesen Platzhalter durch einen anderen String ersetzen. Sowohl Platzhalter als auch ersetzter String sind im Flashram abgelegt. Vielleicht hat ja jemand ein Beispiel dafür? Danke, Christian
Codeauschnitt von oben void GetPlaceHolder(char* buffer, int index) { PGM_P p; memcpy_P(&p, &placeholders[index], sizeof(PGM_P)); ... (Katrierter) Prototyp von memcpy: memcpy(ziel, quelle, länge); Darum
Warum so kompliziert (und zudem falsch)? mach doch einfach void GetPlaceHolder(char* buffer, int index) { memcpy_P(buffer, placeholders[index], strlen_P(placeholders[index])); ... Wobei das warscheinlich auch nicht so funtionieren wird wie Du Dir das vorstellst, denn aller Vorraussicht nach wird die Länge des Platzhalters zu 99,9% immer verschieden von der Länge des Ersatzstrings sein.
Nöö, vollkommen falsch: Aus der original Doku der AVR GCC lib: memcpy_P: This is a special version of the memcpy function that copies data from program memory to RAM. Da PROGMEM gleichbedeutend mit FLASH (siehe auch GCC Tutorial) bedeutet dies, die Funktion kopiert vom(!) Flash ins(!) RAM, genau, wie ich das beabsichtige und nicht etwa wird irgendwas ins Flash kopiert. Der Mechanismus ist so wie von mir verwendet auf mehreren AVR Seiten dokumentiert (siehe zB GCC Tutorial). Ziel des Ganzen ist es einfach, die im Flash definierten Daten in den Hauptspeicher zu kopieren um diesen dort ganz normal wie alle Daten im RAM zu verwenden. Davon ab: Wenn ich die vorgeschlagene Variante verwende, muss ich nach dem Aufruf das Gerät ausschalten, da es gnadenlos abstürzt (passiert beim Aufruf von memcpy_P)
Die Sache mit memcpy_P duerfte darauf beruhen, dass Wernder nicht durchschaut hat, worauf Du mit GetPlaceHolder hinaus willst. Hab selbst 3 mal hinschauen mussen um zu erkennen was da vor sich geht. > Die zentrale Frage ist und bleibt (uunabhängig von allen > funktionen oben): Wieso funktioniert strstr nicht, wenn ich > dort eine String aus dem Flashram gemäß der Anleitung aus den > FAQs übergebe, Das tust Du ja gar nicht. Du kopierst ja den String aus dem Flash zunaechst ins SRAM und arbeitest von dort weiter. Lass Dir doch den String im SRAM mal ausgeben damit Du siehst ob der dort nochr ichtig ist, oder ob der schon falsch ist. > Wird der Suchstring gefunden. Auch der Aufruf von StringReplace > mit PSTR("#wm#") oder "#wm#" bringt nicht das gewünschte Ergebnis. Hmm. Zumindest letzteres sollte funktionieren. Aendere doch mal die Funktion ob, so dass sie die die Strings iregendwo ausgibt, damit Du checken kannst, was denn da in die Funktion heineingeht: void StringReplace(char* string, const char* find, char* replace) { printf( "string: %s\n", string ); printf( "find: %s\n", find ); char* pos; pos = strstr(string, find); if (pos) { strcpy(string, pos); } } Ich weiss jetzt nicht welche Moeglichkeiten zum debuggen Du hast. Gegenenfalls musst Du halt fuer den printf was anderes finden. Aber mit einem Aufruf von int main() { char buffer[20] = "t#wm#"; StringReplace( buffer, "#wm#", 0 ); } Sollte da in StringReplace was vernuenftiges ausgegeben werden.
Hallo Karl, >> Das tust Du ja gar nicht. Du kopierst ja den String aus >> dem Flash zunaechst ins SRAM und arbeitest von dort weiter. Du hast natürlich recht. Ich habe mich mißverständlich ausgedrückt. Natürlich hole ich mir die Strings ins RAM, da strstr ja nicht auf den FlashRam zugreift. Vermutlich wäre die richtige Lösung ein strstr_P, aber das gibt es leider nicht. Die Kontrollausgabe habe ich bereits gemacht, in dem ich die Strings in "find" und "replace" einfach per strcpy in die variable "string" kopiert habe (nach dem If). Diese wird nach StringReplace auf einem Display ausgegeben. Der Witz an der Sache: "Find" wird auch mit GetPlaceHolder geholt korrekt ausgegeben. Den Mechanismus in GetPlaceHolder verwende ich an etlichen anderen Stellen bereits und der funktioniert überall problemlos. Mein Problem ist, das ich einfach nicht sehe, wo das Problem ist. Vielleicht habe ich einfach einen Knick im Hirn, aber ich seh's nicht. Debuggen kann ich leider gar nicht, da es sich um eine sehr komplexe Hardware handelt. Aber natürlich kann ich Strings und Zahlen ausgeben und Keyboardeingaben machen. Ich probiere mal Deine Vorschläge aus, vielleicht bringt mich das weiter. Danke für das konstruktive Feedback! :-) Christian
Es geht nun! Es lag weder an der Funktion StringReplace noch an GetPlaceHolder. Beide funktionieren einwandfrei (bereits im ersten Beitrag war das so). Das Problem war ein Makro PMSTR, was ich gebaut habe um nicht jedesmal "const string xyz[] PROGMEM = "string";" schreiben zu müssen. Das Makro enthielt ein #string für den Stringparameter. Nur hatte ich den saublöden Fehler gemacht "PMSTR(placeholder1, "#wm#")" zu schreiben. Da #string aber auch die Quotes mit in den String packt, sah das Ergebnis so aus "const string xyz[] PROGMEM = "\"string\"";", es waren also die Quotes mit im String, grmpf#$%&§... Unglücklicherweise ist dann noch dazugekommen, das es in meinem Font aus Platzgründen keine Quotes gibt und somit diese nicht ausgegeben wurden. Doppelt blöd also....
Und hier noch die Implementierungen, falls jemand Interesse daran hat: // Deklaration von Strings im FLASH const string ph_1[] PROGMEM = "test1"; const string ph_2[] PROGMEM = "test2"; // Alle strings in dieses Array gepackt PGM_P placeholders[] PROGMEM = { ph_1, ph_2 }; // Hier werden die flash strings in einen Buffer im Ram kopiert void GetPlaceholder(char* buffer, int index) { PGM_P p; memcpy_P(&p, &placeholders[index], sizeof(PGM_P)); strcpy_P(buffer, p); } // Und diese Funktion ersetzt den Teilstring "find" in "string" durch den string in "replace". Ist sicher nicht 100%ig, aber für meine Zwecke reichts. find und replace können unterschiedliche Längen haben. void StringReplace(char* string, char* find, char* replace) { char temp[256]; char* pos; int lfind,lreplace; pos = strstr(string, find); if (pos) { lfind = strlen(find); lreplace = strlen(replace); if (lreplace <= lfind) { strcpy(pos + lreplace, pos+lfind); strncpy(pos, replace, lreplace); } else { strcpy(&temp[0], pos); strncpy(pos, replace, lreplace); strcpy(pos+lreplace, &temp[lfind]); } } }
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.