Forum: Mikrocontroller und Digitale Elektronik String links mit Zeichen auffüllen;


von anfaenger (Gast)


Lesenswert?

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 !

von Karl H. (kbuchegg)


Lesenswert?

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.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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?

von anfaenger (Gast)


Lesenswert?

Die Zahlen als String ohne führende Zeichen stammen von itoa, utoa, 
ultoa.

sprintf z.B. verwende ich aus Platz- und Performancegründen nicht.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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

von anfaenger (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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';

von Karl H. (kbuchegg)


Lesenswert?

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 );

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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...

von Karl H. (kbuchegg)


Lesenswert?

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?

von anfanger (Gast)


Lesenswert?

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.

von anfaenger (Gast)


Lesenswert?

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.

von Noname (Gast)


Lesenswert?

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?

von µC-Bastler (Gast)


Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

µ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.

von anfaenger (Gast)


Lesenswert?

µ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.

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von anfaenger (Gast)


Lesenswert?

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

von anfaenger (Gast)


Lesenswert?

@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
Noch kein Account? Hier anmelden.