Integer zu String, aber (Speicher-)effizient.

OP #2414361
Lesenswert?

Für ein Programm muss ich einen beliebigen Integerwert in ein C-Array 
umwandeln. Im Moment mache ich das so:
1
char len[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.
#2414406
Lesenswert?

Christian H. schrieb:
>
1
char len[sizeof(int)*8+1];
2
> (void) sprintf(len,"%d",i);

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 ...
Gast #2414409
Lesenswert?

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
Gast #2414432
Lesenswert?

Christian H. schrieb:
> Für ein Programm muss ich einen beliebigen Integerwert in ein C-Array
> umwandeln. Im Moment mache ich das so:
>
>
1
char len[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.
#2414438
Lesenswert?

Ginge das abzählen so ?
1
#define BASE 10
2

3
uint?_t length = 0;
4
uint?_t vgl = 0;
5

6
while ( vgl < value) // 
7
{
8
  length ++;
9
  vgl *= BASE;
10
  vgl += BASE - 1;
11
}
12

13
/*
14

15
Die obige Schleife sollte doch das hier machen:
16

17
if (x>9) length++;
18
if (x>99) length++;
19
if (x>999) length++;
20
if (x>9999) length++;
21
if (x>99999) length++;
22
if (x>999999) length++;
23
if (x>9999999) length++;
24
...
25
*/
#2414516
Lesenswert?

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.
OP #2414577
Lesenswert?

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.
#2414588
Lesenswert?

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
#2414772
Lesenswert?

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)
#2414775
Lesenswert?

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?
#2414904
Lesenswert?

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)
#2414913
Lesenswert?

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.
Gast #2414951
Lesenswert?

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.
Persönliche Seite #2415229
Lesenswert?

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...
Gast #2415523
Lesenswert?

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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren