Für ein Programm muss ich einen beliebigen Integerwert in ein C-Array
umwandeln. Im Moment mache ich das so:
1
charlen[sizeof(int)*8+1];
2
(void)sprintf(len,"%d",i);
Doch ich soll keine "willkürlichen" Grenzen verwenden, sodass ich die
Größe des Arrays an den Integerwert anpassen muss - wie könnte ich das
angehen? Um die Anzahl der Stellen zu berechnen, bräuchte ich eine
Schleife, aber dieser Code befindet sich selbst in einer Schleife, daher
würde ich wenn es geht auf eine Schleife verzichten.
Dass ich (sizeof(int)*8+1)-Char Werte reserviere obwohl unter Umständen
nur viel weniger gebraucht werden. Die Zahl, die umgewandelt wird, ist
wohl meist doch kleiner als 10.
warum sizeof(int)*8+1? selbst wenn du die berechnung sehr einfach halten
willst wäre da eine 3 statt einer 8 angebrachter (und +2 statt +1 ->
vorzeichen).
Dort dynamisch speicher reservieren (wieviel du brauchst sagt dir der
10er-logarithmus, aber voelliger overkill da) ist imo uebertrieben ...
Also wenn ich dich richtig verstehe willst du die Anzahl an Stellen
einer Zahl bestimmen....
Also bei 458 -> 3
oder 12 -> 2, 145789 -> 6
Dann geht das ganz einfach mit Hilfe des Logarithmus
int(log(x)) + 1
lg
Andi schrieb:> Dann geht das ganz einfach mit Hilfe des Logarithmus
Einfach ja, effizient nein.
und oben müssen 12Bytes allociert werden (weiß nicht wie ich auf 9 kam).
Christian H. schrieb:> Für ein Programm muss ich einen beliebigen Integerwert in ein C-Array> umwandeln. Im Moment mache ich das so:>>
1
charlen[sizeof(int)*8+1];
2
>(void)sprintf(len,"%d",i);
>> Doch ich soll keine "willkürlichen" Grenzen verwenden, sodass ich die> Größe des Arrays an den Integerwert anpassen muss - wie könnte ich das
Musst Du das wirklich, die String-Darstellung eines int hat auf jeder
Plattform eine definierte Maximallänge?
Das Forum heisst "PC-Programmierung", wenn ich das ernst nehme ist der
Unterschied zwischen 3 Bytes, 10 Bytes oder 15 Bytes total irrelevant.
Es sei denn Du haettest Millionen davon, in dem Fall musst Du das
vermutlich eh ganz anders machen - eigene Speicherverwaltung ganz anders
als malloc() und Co. wäre angesagt, mit minimiertem Overhead und ohne
den vom Standard erzwungenen "Verschnitt" durch Alignmentanforderungen.
> angehen? Um die Anzahl der Stellen zu berechnen, bräuchte ich eine> Schleife, aber dieser Code befindet sich selbst in einer Schleife, daher> würde ich wenn es geht auf eine Schleife verzichten.
Schleife, einige ifs, Logarithmus, alles zu viel Aufwand wenn Du nur ein
paar irrelevante Bytes einsparen willst.
Thomas W. schrieb:> Ginge das abzählen so ?
Na ja.
Probiers aus.
(negative Zahlen brauchen eine Stelle mehr und an den Bereichsgrenzen
musst du aufpassen)
Aber wie schon gesagt: Wozu?
Die paar Bytes, die in
char len[20];
(void) sprintf(len,"%d",i);
kurzzeitig für nichts überzählig reserviert werden, sind völlig
irrelevant. Es lohnt den Aufwand nicht, sich da etwas anderes einfallen
zu lassen, vor allen Dingen, wenn dieser Aufwand selber wieder eine
Menge Resourcen kostet. Man treibt da den Teufel mit dem Belzebub aus.
Den Unmengen von Integern wird man sinnvollerweise sowieso nicht in
Textform speichern, sondern so wie sie sind .. als int oder long oder
was man dann auch immer hat. Textrepräsentierungen braucht man
normalerweise nur an I/O Schnittstellen und wenn man da kurzzeitig (in
einer Funktion) mal 10 Bytes zuviel allokiert hat, dann ist das kein
Thema um das man sich Sorgen machen muss. Wenn diese temporären 10 Bytes
den Unterschied zwischen läuft und läuft nicht ausmachen, dann hat man
an anderen Stellen schon viel größere Probleme.
Thomas W. schrieb:> @KH:> Ja die 0, Vorzeichen und überläufe funktionieren nicht.> Alles "dazwischen" geht.>> Wie zählt man besser ab ?
Ist doch alles schon angesprochen worden.
Entweder Logarithmus oder durch 10 dividieren bis man bei 0 ist und
mitzählen.
Ist schon verrückt was der TO auf einem PC!? für Verrenkungen machen
will um 5 oder 10 Bytes zu sparen.
Irgendwie habe ich das Gefüht das eigentliche Problem liegt anderswo.
Danke für die vielen Antworten. Also die Angabe lautet wie folgt:
1
Willkürliche Grenzen sind soweit als möglich zu vermeiden.
2
Ist es notwendig, Grenzen einzuführen, so ist die Überschreitung dieser Grenzen zu behandeln.
3
Alle diese Grenzen sind als symbolische Konstante (Makrodefinitionen!) zu vereinbaren.
Gehe ich hier zu weit? Würde es eine effizientere Approximation des
Log10-geben - vl eine grobe Annäherung durch Taylor Polynom? Selbst wenn
das Resultat ein wenig über dem des logs sein sollte, wäre das doch
egal.
da ich mit Pascal arbeite, kann ich (mal wieder) nur den Kopf schütteln
;-)
C und Strings sind schon was tolles ;-)
gib es in C wirklich keine "IntToString" (optimierte) Funktion die das
FixFertig zurück liefert?
also wenn man sich schon über sowas "rudimentäres" jedes mal den kopf
zerbrechen muss, und (vor allem) jeder Programmiere dass nach seinem gut
dünken "löst"...
naja egal:
ich würde:
a) auf die Paar byte sch.. (vorallem wenn es um einen PC geht, und nicht
um einen µC)
b) einmal (pro thread) Speicher GLOBAL reservieren (in der maximal
möglichen länge (also 12 Byte)
dort hinein das sprintf(...)
das Ergebnis dann dynamisch reservieren
bzw. wenn man die 12 "vermeiden will" kann man sich beim EINMALIGEN
globalen reservieren ja mehr mühe geben, und z.b. je nachdem ob der
integer 16, 32 oder 64 bit hat, dort einmalig die maximale länger
ermitteln
Robert L. schrieb:> gib es in C wirklich keine "IntToString" (optimierte) Funktion die das> FixFertig zurück liefert?
natürlich gibt es das. Wird ja auch benutzt.
Aber ich muss als Aufrufer die Speicherfläche zur Verfügung stellen und
da muss ich sie entsprechend dimensionieren.
In C gibt es keine dynamisch wachsende/schrumpfende Strings. Hat den
Nachteil, dass man sich um solche Sachen selber kümmern muss. Hat den
Vorteil, dass man keine versteckten dynamischen Allokierungen hat, die
ihrerseits wieder zu Problemen führen können (Speicherfragmentierung /
Out of Memory). Wenn ich dynamisch wachsende Strings brauche, muss ich
mir die selber machen.
> also wenn man sich schon über sowas "rudimentäres" jedes mal den kopf> zerbrechen muss, und (vor allem) jeder Programmiere dass nach seinem gut> dünken "löst"...
Darüber zerbricht man sich auch nicht den Kopf, man wählt ...
> a) auf die Paar byte sch.. (vorallem wenn es um einen PC geht, und nicht> um einen µC)
Christian H. schrieb:> Danke für die vielen Antworten. Also die Angabe lautet wie folgt:>>
1
Willkürliche Grenzen sind soweit als möglich zu vermeiden.
2
> Ist es notwendig, Grenzen einzuführen, so ist die Überschreitung dieser
3
> Grenzen zu behandeln.
4
> Alle diese Grenzen sind als symbolische Konstante (Makrodefinitionen!)
5
> zu vereinbaren.
>> Gehe ich hier zu weit?
Kommt drauf an.
Ist dieses "zum String umwandeln" ein wesentlicher Bestandteil deiner
Aufgabe oder ist das ein Nebenschauplatz, weil du eben irgendwo
Rechenergebnisse ausgeben musst um zu zeigen, dass deine
Hyper-Duper-Routenberechnung auch tatsächlich funktioniert.
Wie lautet denn die komplette Aufgabenstellung?
Das ist eben nur eine Nebenbedinung. Es werden Zeichen verarbeitet.
Paralell wird mitgezählt und die Anzahl soll immer wieder ausgegeben
werden. Diese ist in einem Integer und daher muss ich den in einen
String umwandeln.
Christian H. schrieb:> Das ist eben nur eine Nebenbedinung. Es werden Zeichen verarbeitet.> Paralell wird mitgezählt und die Anzahl soll immer wieder ausgegeben> werden. Diese ist in einem Integer und daher muss ich den in einen> String umwandeln.
Und warum musst du das dann intern in einen String umwandeln.
Wenn du einen Integer ausgeben musst, musst du doch nicht extra
umwandeln
printf( "%d", Anzahl );
und schon steht die Anzahl auf der Konsole.
(Oder ist da eine GUI involviert. Dann freilich müsste man vorher
umwandeln, wenn man keine entsprechende Funktion hat. Aber auch dann
würde ich diesen Teil nicht als eigentlichen Bestandteil der Aufgabe
ansehen. Ist aber IMHO)
Christian H. schrieb:> Das ist eben nur eine Nebenbedinung. Es werden Zeichen verarbeitet.> Paralell wird mitgezählt und die Anzahl soll immer wieder ausgegeben> werden. Diese ist in einem Integer und daher muss ich den in einen> String umwandeln.
Ja und dann mach das in einer lokalen Variablen, die Größe ist der
dekadische Logarithmus abgerundet + 2 (keine negative Anzahl) Das Ganze
definierst du als Konstante, da rechnet es der Compiler einmal aus.
Das ist ja keine willkürliche sondern eine gerechtferigte Grenze.
Wenn du die maximale Länge ermittelst, die der erzeugte String haben
kann und das als fixe Größe nimmst, ist das doch keine willkürliche
Grenze.
Wenn man z.B. festlegt, daß ein Dateiname maximal 8 Zeichen lang sein
darf, gefolgt von einem Punkt und bis zu drei weiteren Zeichen, dann
wäre das eine willkürliche Grenze.
Also ich fürchte du hast die Aufgabe an der Stelle missverstanden:
> Willkürliche Grenzen sind soweit als möglich zu vermeiden.
Also nicht einfach 1000 als Grenze festlegen, weil man denkt passt
schon, oder Beschränkungen einführen wo keine nötig sind.
> Ist es notwendig, Grenzen einzuführen,> so ist die Überschreitung dieser Grenzen zu behandeln.
Zielt wohl auf Fehlerbehandlung/Pufferüberläufe ab.
> Alle diese Grenzen sind als symbolische Konstante> (Makrodefinitionen!) zu vereinbaren.
Keine Magic Numbers.
Wenn maximal 20 Zeichen bei der Umwandlung rauskommen könnne: Ist doch
schön, kurze Begründung warum, eine Macrokonstante anlegen und fertig...
Christian H. schrieb:> Danke für eure Mühen! Ich habe es jetzt wie folgt gelöst:>> int n;>>>> n = fprintf(...);>>>> // so kann ich den Integer in einen String umwandeln und bekomme die Anzahl der
Stellen zurück!
Wie "fprintf()"? Gibst du es etwa irgendwo aus, nur um rauszubekommen,
wie lang der String wird? Das ist sicher nicht die Idee der Aufgabe
gewesen!