Forum: Mikrocontroller und Digitale Elektronik sprintf() ein Rätsel


von Martin (Gast)


Lesenswert?

Hallo allezusammen,

ich habe unglaubliche Problem bei der stdio-Funktion sprintf().

Folgender Code treibt mich in den Wahnsinn.

 static signed char near HlpArr[9];
  byte ii;

  sprintf((&HlpArr[0]), "%8.2f", X);

  for(ii=0;ii<sizeof(HlpArr);ii++)
  {
    if(HlpArr[ii]=='.')
    {
      HlpArr[ii]=',';
      break;
    }
  }

Ich will damit z.B so ein Ergebnis erreichen -1574,34


Für wieviel Zeichen habe ich insgesamt Platz reserviert? 8, oder?
Die Terminierung /0 passt auch in HlpArr.

Was mach ich falsch?

von g a s t (Gast)


Lesenswert?

8 Zeichen vorm Komma
1 Zeichen = Komma
2 Zeichen dahinter
1 Zeichen = \0

macht 12 Zeichen, reserviert sind nur 9.

von Martin (Gast)


Lesenswert?

Aha,

ich habe so gedacht

1 Zeichen Minus
4 Zeichen Ziffern
1 Zeichen Komma
2 Zeichen Nachkommastellen

Ich hatte so eine Vorahnung.

Dann wird hier nicht richtig erklärt
http://home.htw-berlin.de/~junghans/cref/FUNCTIONS/format.html

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

1
static signed char near HlpArr[9];
2
  byte ii;
3
4
  sprintf((&HlpArr[0]), "%8.2f", X);
Geht das so überhaupt?
Du schreibst damit Das "Ergebnis" an die Adresse vom ersten 
Array-Element.

char HlpArr[groesse]
sprintf(HlpArr, "...", ...);

von g a s t (Gast)


Lesenswert?

Ne, Moment, vielleicht ist das doch so. Ich guck mal nach.

von g a s t (Gast)


Lesenswert?

Nils S. schrieb:
>
1
> sprintf((&HlpArr[0]), "%8.2f", X);
2
> sprintf(HlpArr, "...", ...);

Das ist doch das Gleiche?

von DirkB (Gast)


Lesenswert?

8.2 heißt 8 zeichen insgesamt davon ist ein . und 2 Nachkomma.
Das Vorzeichen kommt noch optional davon ab.

von Chris (Gast)


Lesenswert?

Nils S. schrieb:
> &HlpArr[0]
ist das gleich wie HlpArr. Stimmt also.

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Ok, das wusste ich nicht.

von g a s t (Gast)


Lesenswert?

g a s t schrieb:
> 8 Zeichen vorm Komma
> 1 Zeichen = Komma
> 2 Zeichen dahinter
> 1 Zeichen = \0
>
> macht 12 Zeichen, reserviert sind nur 9.

ist falsch, sorry.

K&R sagt

> A number specifying a minimum field width. The converted argument will be
> printed in a field at leat this wide, and wider if necessry. If the
> converted argument has fewer characters than the field width it will be
> padded on the left (or right, if left adjustement has been requested) to
> make up the field width.

Irren ist menschlich...

von Martin (Gast)


Lesenswert?

@DirkB
"8.2 heißt 8 zeichen insgesamt davon ist ein . und 2 Nachkomma.
Das Vorzeichen kommt noch optional davon ab."


Um mein Ergebnis(-1574,34) zu bekommen muss ich so
formatieren

sprintf((&HlpArr[0]), "%5.2f", X);

oder

von Rene S. (Firma: BfEHS) (rschube)


Lesenswert?

>> static signed char near HlpArr[9];
>> ...
>> sprintf((&HlpArr[0]), "%8.2f", X);
>> ...
>>
--------------------------------------

char HlpArr[12];
...
sprintf( HlpArr, "%8.2f", X);
...

Ich hab das mal so gemacht, geht.

HlpArr[ 0] '1'
HlpArr[ 1] '2'
HlpArr[ 2] '3'
HlpArr[ 3] '4'
HlpArr[ 4] '5'
HlpArr[ 5] '6'
HlpArr[ 6] '7'
HlpArr[ 7] '8'
HlpArr[ 8] '.'
HlpArr[ 9] '1'
HlpArr[10] '2'
HlpArr[11] '\0'

von DirkB (Gast)


Lesenswert?

Nein.
Dein erster Ansatz ist schon richtig. Die Zahl vor dem . gibt die 
Feldlänge an. Und das sind bei dir 8 Zeichen.

Martin schrieb:
> 1 Zeichen Minus
> 4 Zeichen Ziffern
> 1 Zeichen Komma
> 2 Zeichen Nachkommastellen

Ist alles richtig.

von Martin (Gast)


Lesenswert?

@Gast
Kein Problem. Irren ist menschlich.

Ich lasse die Finger vom Code und der bleibt so wie er ist

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Martin schrieb:
> Um mein Ergebnis(-1574,34) zu bekommen muss ich so
> formatieren
>
> sprintf((&HlpArr[0]), "%5.2f", X);

Du musst aber sicher sein, dass er nicht über -9999.99 rausgeht, wenn du 
das Array mit 8+'\0', also 9, chars definierst. Auf dem PC gibt das 
segfaults, wie das "Spinnen" dann beim Controller aussieht, weiss ich 
nicht.

Immer erstmal vom worst-case ausgehen und wenns klappt bytes sparen 
anfangen.

von DirkB (Gast)


Lesenswert?

sprintf hat als Rückgabewert die Anzahal der ausgegebenen Zeichen.
Die sollten kleiner als 9 sein.

Aber was funktioniert denn nicht?

Hast du auch die Fließkommabibliothek ausgewählt?
(ich meine nicht math.h)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Um unnötige Diskussionen vorwegzunehmen:

Im folgenden irre ich selbst, und zwar massiv.

Damit sich alle drüber freuen können, lasse ich den Irrtum hier stehen.

Abschließende Bemerkung hier:
Beitrag "Re: sprintf() ein Rätsel"

##############

DirkB schrieb:
> 8.2 heißt 8 zeichen insgesamt davon ist ein . und 2 Nachkomma.
> Das Vorzeichen kommt noch optional davon ab.

Das ist eindeutig falsch.

8.2 bedeutet mindestens 8 Zeichen vor dem Dezimalpunkt (mit führenden 
Leerzeichen aufgefüllt), Dezimalpunkt und zwei Nachkommastellen.

g a s t schrieb:
> ist falsch, sorry.

Auch Du liegst daneben.

> K&R sagt
>
>> A number specifying a minimum field width. The converted argument will be
>> printed in a field at leat this wide, and wider if necessry. If the
>> converted argument has fewer characters than the field width it will be
>> padded on the left (or right, if left adjustement has been requested) to
>> make up the field width.

Die Feldbreite, die hier beschrieben wird, bezieht sich nur auf die 
Anzahl der Stellen vor dem Dezimalpunkt.

Also:

double x = 1.234;

printf("#%3.2f#", x);

ergibt
#  1.23#

printf("#%2.3f#", x);

ergibt
# 1.234#

printf("#%8.2f#", x);

ergibt
#       1.23#

von DirkB (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> printf("#%8.2f#", x);
>
> ergibt
> #       1.23#

Nein, denn die 8 ist die minimale Feldlänge. Und da alles da rein pastt, 
wird die nicht überschritten.

printf("<%8.2f>", x);

ergibt
<    1.23>
:12345678

von Martin (Gast)


Lesenswert?

Martin schrieb:
> Dann wird hier nicht richtig erklärt
> http://home.htw-berlin.de/~junghans/cref/FUNCTIONS...

Dann nimm doch einfach vertrauenswürdige Quellen zur Hand.

Ein gutes Lehrbuch. Oder gar den Standard.

von Stefan E. (sternst)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Die Feldbreite, die hier beschrieben wird, bezieht sich nur auf die
> Anzahl der Stellen vor dem Dezimalpunkt.

Nein. Es ist definitiv die Gesamtbreite.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Asche auf mein Haupt. Ja, ich gestehe es: Irrtum.

(Notiz an selbst: Warum?!)
1
double x = 123.456;
2
3
int i;
4
int j;
5
6
printf("01234567890123456789\n");
7
for (i = 0; i < 10; i++)
8
  for (j = 0; j < 4; j++)
9
    printf("#%*.*f#  %2d %2d\n", i, j, x, i, j);

ergibt
1
01234567890123456789
2
#123#   0  0
3
#123.5#   0  1
4
#123.46#   0  2
5
#123.456#   0  3
6
#123#   1  0
7
#123.5#   1  1
8
#123.46#   1  2
9
#123.456#   1  3
10
#123#   2  0
11
#123.5#   2  1
12
#123.46#   2  2
13
#123.456#   2  3
14
#123#   3  0
15
#123.5#   3  1
16
#123.46#   3  2
17
#123.456#   3  3
18
# 123#   4  0
19
#123.5#   4  1
20
#123.46#   4  2
21
#123.456#   4  3
22
#  123#   5  0
23
#123.5#   5  1
24
#123.46#   5  2
25
#123.456#   5  3
26
#   123#   6  0
27
# 123.5#   6  1
28
#123.46#   6  2
29
#123.456#   6  3
30
#    123#   7  0
31
#  123.5#   7  1
32
# 123.46#   7  2
33
#123.456#   7  3
34
#     123#   8  0
35
#   123.5#   8  1
36
#  123.46#   8  2
37
# 123.456#   8  3
38
#      123#   9  0
39
#    123.5#   9  1
40
#   123.46#   9  2
41
#  123.456#   9  3

Erklärungsversuch: Es ist Freitag. Nach eins. Da arbeitet doch eh' 
keiner mehr, schon gar kein Hirn.

von DirkB (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Erklärungsversuch: Es ist Freitag. Nach eins. Da arbeitet doch eh'
> keiner mehr, schon gar kein Hirn.

Die Ausrede habe ich heute auch schon benutzt :-)

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.