Hallo, ich suche einen möglichst effektiven Code für einen Mikrocontroller. mit dem ein String von links her mit einem vorgegebenen Zeichen (z.B. ' ' oder '0') aufgefüllt und so auf eine definierbare Länge gebracht wird. Z.B. soll ein String mit einer Zahl "12" mit dem Zeichen '0' auf die Länge von vier Zeichen aufgefült werden : "0012" Am besten sollte der aufgefüllte String als Ergebnis der Funktion zurückgegeben werden, der Usprungsstring, die gewünschte Endlänge und der Zeichentyp zum Auffüllen sollen als Parameter an die Funktion übergeben werden. Ich könnte mir natürlich selbst eine Lösung zusammenstricken, suche aber einen möglichst effektiven, schnellen und schon getesteten Code. Vielleicht hat ja jemand schon eine geprüfte Lösung parat ? Prozessor : MSP430 Compiler : MSPGCC Danke !
anfaenger schrieb: > Ich könnte mir natürlich selbst eine Lösung zusammenstricken, suche aber > einen möglichst effektiven, schnellen und schon getesteten Code. Dann schreib die doch mal. > Vielleicht hat ja jemand schon eine geprüfte Lösung parat ? Mit den Standard-str Funktionen ist das gar nicht so schwer selbst zu machen. Mach mal, zeig sie und dann gibts auch Kritik dazu. Ist eine gute Übung.
anfaenger schrieb: > Ich könnte mir natürlich selbst eine Lösung zusammenstricken, suche aber > einen möglichst effektiven, schnellen und schon getesteten Code. Am schnellsten ist es, den Ursprungsstring gleich mit den benötigten führenden Zeichen zu schreiben. Woher stammen denn die Zahlen als String ohne führende Zeichen? Ist vor den Ziffern noch Platz im Speicher?
Die Zahlen als String ohne führende Zeichen stammen von itoa, utoa, ultoa. sprintf z.B. verwende ich aus Platz- und Performancegründen nicht.
anfaenger schrieb: > sprintf z.B. verwende ich aus Platz- und Performancegründen nicht. Sehr gut! :-) Ich würde an deiner Stelle die Funktion utoa() neu schreiben, und zwar so, dass die führenden Nullen gleich dabei sind. Witzigerweise ist ein utoa() mit fester Stellenzahl sogar einfacher und schneller als ohne. Um wie viele Stellen insgesamt geht es? Nachtrag: Hier sind ein paar Infos zum Thema: http://www.mikrocontroller.net/articles/Festkommaarithmetik#ITOA_selbst_gemacht
Aktuell geht es um Zahlen mit zwei oder vier Stellen, damit für Datums- und Zeitangaben ein ordentlicher String zusammengestzt werden kann. Ich hatte allerdings daran gedacht, die Funktion später universeller für Formatierungszwecke einzusetzen. Im Normalfall hat der temporäre String 12 Zeichen, damit z.B. auch ein long-int noch gespeichert werden kann. Der Nickname "anfaenger" ist vielleicht eine kleine Untertreibung, deshalb ist auch der Übungseffekt für mich in dieser Angelegenheit nicht so wichtig.
anfaenger schrieb: > Der Nickname "anfaenger" ist vielleicht eine kleine Untertreibung, > deshalb ist auch der Übungseffekt für mich in dieser Angelegenheit nicht > so wichtig. Worum gehts dann? So eine Funktion ist schneller geschrieben als du an deinem Eröffnungsposting gefeilt hast. Ich werd mitlerweile hellhörig, wenn jemand nach der 'möglichst optimalen' Lösung bei eigentlich einfachen Problemen fragt. Dieses 'optimale' heißt nämlich in Wirklichkeit: Bitte präsentiert mir wenisgtens irgendwas, weil ich es alleine nicht hinkriege. PS: Da so eine Funktion in 99% aller Fälle für Ausgabezwecke gebraucht wird, spielt die Laufzeit kaum eine Rolle. Die eigentliche Ausgabe dauert wesentlich länger als das Formatieren der Ausgabe. Um Laufzeit-Performance brauchst du dir an dieser Stelle kaum Gedanken machen. Ausser natürlich wenn man die Dinge vorsätzlich kompliziert macht. Und Markus hat auch recht: ein utoa welches keine führenden 0-en ausgibt, ist komplizierter als eines ohne.
Bei zwei Stellen dürfte es relativ einfach sein. Angenommen, die Variable zahl liegt immer im Bereich zwischen 0 und 99, dann gehts am einfachsten so: unsigned char zahl; static char ziel[3]= {0,0,0}; ... ziel[0]= zahl/10+'0'; ziel[1]= zahl%10+'0';
Markus W. schrieb: > anfaenger schrieb: >> sprintf z.B. verwende ich aus Platz- und Performancegründen nicht. > > Sehr gut! :-) Nö, nicht gut. Es gibt keinen Grund Vorhandenes nicht zu verwenden, wenn man die Resourcen dazu hat. Ob der Speicher brach liegt oder nicht, macht für den µC keinen Unterschied. Wenn er gesagt hätte, er hätte den Speicher nicht, ist das eine andere Sache. Ist der aber vorhanden, gibt es kaum einen Grund sprintf nicht zu verwenden. Ein sprintf( Buffer, "%02d:%02d %02d - %02d-%02d-%04d, hour, minute, sec, day, month, year ); ist in 20 Sekunden hingeschrieben und braucht weniger Laufzeit als der nachfolgende lcd_puts( Buffer );
Karl Heinz Buchegger schrieb: > Nö, nicht gut. > Es gibt keinen Grund Vorhandenes zu verwenden, wenn man die Resourcen > dazu hat. Ob der Speicher brach liegt oder nicht, macht für den µC > keinen Unterschied. Da hast du natürlich Recht. Allerdings schrieb der Trhead-Ersteller gleich am Anfang, dass er einen möglichst effektiven Code sucht. Ich habs dahingehend interpretiert, dass der Code kompakt sein soll und schnell laufen muss (z.B. weil er in einer ISR genutzt wird). Man kann das natürlich auch so verstehen, dass er Code sucht, der sich in eine einzelne Zeile schreiben lässt, und es nicht auf die Ressourcen ankommt. Eine Frage des Blickwinkels...
Markus W. schrieb: > Karl Heinz Buchegger schrieb: >> Nö, nicht gut. >> Es gibt keinen Grund Vorhandenes zu verwenden, wenn man die Resourcen >> dazu hat. Ob der Speicher brach liegt oder nicht, macht für den µC >> keinen Unterschied. > > Da hast du natürlich Recht. > Allerdings schrieb der Trhead-Ersteller gleich am Anfang, dass er einen > möglichst effektiven Code sucht. Ganz ehrlich: Diese Aussagen nehm ich mitlerweile nicht mehr ernst. Wird nach 'möglichst effektiv' gesucht, lautet die Frage meistens (>99% aller Fälle) in Wirklichkeit: Hilfe, ich kriegs überhaupt nicht hin! Wer hilft mir?
Karl Heinz Buchegger schrieb: > Ganz ehrlich: > Diese Aussagen nehm ich mitlerweile nicht mehr ernst. Wird nach > 'möglichst effektiv' gesucht, lautet die Frage meistens (>99% aller > Fälle) in Wirklichkeit: Hilfe, ich kriegs überhaupt nicht hin! Wer hilft > mir? Deine Meinung in allen Ehren, vor allem weil ich weiss, dass Du Dich oft schon wirklich um DAU´s bemüht hast. Bei mir geht es allerdings wirklich um einen möglichst effektiven Code und ich habe diese Frage gestellt, weil ich das Rad nicht immer wieder selbst erfinden muss und weil das ev. auch von allgemeinerem Interesse sein könnte. Bei Google-Suchen werden z.B. oft Treads von hier angezeigt. Ich könnte mir das schon auch selbst zusammenstricken, aber das bedeutet schon einen gewissen (ev. vermeidbaren Zeitaufwand) und die Lösung wäre ziemlich sicher schlechter als bei einem bereits getesteten und optimierten Code. Und so trivial scheint jetzt eine optimierte allgemeine Lösung (unabhängig von itoa, etc) auch wieder nicht zu sein.
Karl Heinz Buchegger schrieb: > Wenn er gesagt hätte, er hätte den Speicher nicht, ist das eine andere > Sache. Ist der aber vorhanden, gibt es kaum einen Grund sprintf nicht zu > verwenden. Der MSP439F249 hat 64 KB Flash und 2 kB RAM. Ich habe sprintf schon mal ausprobiert und dabei festgestellt, dass er ziemlich viel Speicher verbraucht hat (wieviel wiess ich jetzt nicht mehr genau). Klar wäre es mit sprinft trivial. Aber ich suche nach einer schlankeren Lösung.
Man muss Dich vielleicht nochmal in die richtige Richtung drehen. Hier ist doch utoa genannt worden. Schau Dir mal den Code an. Frage Dich, was hindert utoa daran immer weiter Nullen vorne anzuhängen?
Markus W. schrieb: > Ich habs dahingehend interpretiert, dass der Code kompakt sein soll > und schnell laufen muss (z.B. weil er in einer ISR genutzt wird). Ein wohlformatierte Umwandlung in einen String hat in einer ISR nun wirklich nichts zu suchen.
µC-Bastler schrieb: > Markus W. schrieb: >> Ich habs dahingehend interpretiert, dass der Code kompakt sein soll >> und schnell laufen muss (z.B. weil er in einer ISR genutzt wird). > > Ein wohlformatierte Umwandlung in einen String hat in einer ISR nun > wirklich nichts zu suchen. Richtig. Das Problem ist vermutlich wie in 99% der Fälle hier: Das Programmkonzept.
µC-Bastler schrieb: > Ein wohlformatierte Umwandlung in einen String hat in einer ISR nun > wirklich nichts zu suchen. Die Routine befindet sich auch nicht in einer ISR. Die ISR´s setzen nur Flags und wecken ggf. den Prozessor aus den LPM´s auf, damit die resultierenden Arbeiten dann im Hauptprogramm abgearbeitet werden. Es geht generell um eine möglichst effiziente Programmierung.
anfaenger schrieb: > Es geht generell um eine möglichst effiziente Programmierung. So etwas gibt es nicht. Man optimiert so viel, wie es nötig ist. Siehe die Diskussion zu sprintf oben.
Simon K. schrieb: > anfaenger schrieb: >> Es geht generell um eine möglichst effiziente Programmierung. > > So etwas gibt es nicht. Man optimiert so viel, wie es nötig ist. Siehe > die Diskussion zu sprintf oben. Da hat jeder wohl seine eigene Philosophie. Ich möchte mein Projekt jedenfalls nicht mittendrin wieder grundlgend überarbeiten müssen, weil durch verschwenderische Programmierung der Speicherplatz nicht ausreicht. Ausserdem geht es um eine Ultra-Low-Power Anwendung und da kostet jeder unnötige Rechenschritt auch (einsparbare) Energie
@Markus W. : Danke für den Tipp, ich habe es für mich nochmal etwas modifiziert : // Funktion zur Umwandlung einer vorzeichenlosen 32 Bit Zahl in einen String // (Eine vorzeichenlose 32 Bit Zahl kann maximal 10 Dezimalstellen haben (0..4294967295) ) // siehe auch : http://www.mikrocontroller.net/articles/Festkommaarithmetik#ITOA_selbst_gemacht void uitoa_self(uint32_t zahl, uint8_t str_length, char* string) { // uint32_t zahl : Von unsigned Integer in String umzuwandelnde Zahl // uint8_t str_length : gewünschte Stringlänge (incl. Füllzeichen links) // char* string : Rückgabestring int8_t ni; // Schleifenzähler string[str_length]='\0'; // String Terminator z.B.: Stringlänge 4: [0..3], Terminierung bei 4 for(ni=(str_length-1); ni>=0; ni--) // { string[ni]=(zahl % 10) +'0'; // Modulo 10 liefert die letzte Stelle als Rest, dann den ASCII-Code von '0' addieren (für richtiges Zahlen-ASCII-Zeichen) zahl /= 10; // Zahl durch 10 teilen, verwirft die zuvor ausgewertete letzte Stelle } }
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.