Hallo,
ich versuche beim Atmega über sprintf die Ausgabe einer Zahl zu
formatieren.
Folgendes klappt:
sprintf(puffer,"%3u\t",daten);
Die Zahl die in "daten" steht, wird immer 3 stellig ausgegeben.
Ich möchte aber nun statt der %3u eine Zahl über ein #define übergeben.
Also in einer .h Datei:
#define ANZAHL 3 // Anzahl der Zeichen die ausgegeben werden sollen
und dann in meiner .c Datei
sprintf(puffer,"%ANZAHLu\t",daten);
Das funktioniert leider nicht. Was mache ich falsch?
Gruß antong
Der Präprozessor interessiert sich nicht für Stringkonstanten, ergo er
ersetzt dort enthaltene Makros nicht.
nicht schön aber selten:
#define ANZAHL "6"
sprintf(puffer,"%"ANZAHL"u\t",daten);
(Funktioniert weil mehrere nebeneinanderliegende Strings wie ein
einzelnder behandelt werden)
alternativ gibt es iirc auch eine Möglichkeit sprintf die Länge als 2.
Parameter zu übergeben, hab aber die Syntax dazu nicht im Kopf.
@ Anton G. (antong)
>Das funktioniert leider nicht. Was mache ich falsch?
Normale Define funktionieren nicht in Strings. Da gibt es aber eine
Lösung, die mir aber im Moment nicht einfällt, stand in einem C-Buch.
http://stackoverflow.com/questions/1079020/can-you-expand-defines-into-string-literals
Das ist aber nur ein HACK, es gibt einen offiellen Weg, ich glaube
irgendwas mit ##
asyxdcvgh schrieb:> alternativ gibt es iirc auch eine Möglichkeit sprintf die Länge als 2.> Parameter zu übergeben, hab aber die Syntax dazu nicht im Kopf.
Da war was, ja.
Früher hat man das eben so gemacht, dass man sich zuerst den
Formatstring zusammengebaut hat
sprintf( FormatString, "%%%du\t", ANZAHL );
und dann eben diesen anstelle eines fixen Strings benutzt hat
sprintf( puffer, FormatString, daten);
Aber wie das mit der Direktangabe im Formatstring geht, weiß ich auch
nicht auswendig.
Ah. weiß wieder. Der * macht das
sprintf(puffer, "%*u\t", ANZAHL, daten);
Karl Heinz Buchegger schrieb:> Ah. weiß wieder. Der * macht das>> sprintf(puffer, "%*u\t", ANZAHL, daten);
Ah genau, das hatte ich im Hinterkopf, war mir aber nicht sicher...
Hallo,
vielen Dank erst mal für die ganzen Antworten.
Leider funktioniert das aber bei mir immer noch nicht ganz.
Folgendes funktioniert:
1
...
2
uint8_tpuffer[20];
3
uint8_tvalue=123;
4
...
5
sprintf(puffer,"Zählerstand: %3u",value);
6
USART1_String_senden(puffer);
7
...
Dieses funktioniert aber nicht:
1
#define ANZAHL 3
2
...
3
uint8_tpuffer[20];
4
uint8_tvalue=123;
5
...
6
sprintf(puffer,"Zählerstand: %*u",ANZAHL,value);
7
USART1_String_senden(puffer);
8
...
Auch wenn ich statt ANZAHL direkt eine Zahl einsetze, erscheint nichts
über die UART. Die Zahl 123 fehlt einfach.
@asyxdcvgh(Gast)
Deine Lösung funktioniert auch.Sieht allerdings wirklich ein wenig
komisch aus.
1
...
2
#define ANZAHL "6"
3
...
4
sprintf(puffer,"Zählerstand: %"ANZAHL"u",value);
5
...
Ich habe auch schon im Internet nach der "%*u" Methode gesucht. Ist aber
schwierig zu finden, da man nach dem Sternchen schlecht suchen kann.
Falls noch jemand eine Idee hat warum das nicht funktioniert, dann würde
ich mich freuen. Ansonsten würde ich die Alternative von
asyxdcvgh(Gast)erst einmal nehmen.
Vielen Dank euch allen.
Gruß Antong
Karl Heinz Buchegger schrieb:> Ah. weiß wieder. Der * macht das>> sprintf(puffer, "%*u\t", ANZAHL, daten);
Stimmt, ist aber eher umständlich, weil dann die Konstante einzeln an
die Funktion übergeben wird - außer der Compiler optimiert das raus. Und
es geht nur, wenn der Compiler das auch unterstützt.
Der einfachste Ansatz ist aber der hier:
Klaus Wachtler schrieb:> Markus W. schrieb:>> sprintf(puffer, "%" #ANZAHL "u\t", daten);>> das mit dem # geht aber nur innerhalb eines Makros.
Hoppla, ich glaub du hast Recht. :-)
Dann eben so:
Hallo,
so ich habe nun einiges getestet von den Antworten oben.
Die Variante von Markus W. funktioniert bei mir leider nicht. Da
bemängelt er die # in der C Datei.
>
1
#define ANZAHL_S #ANZAHL
2
sprintf(puffer,"%"ANZAHL_S"u\t",daten);
3
>
Zwei Varianten funktionieren bei mir.
Die erste Variante von asyxdcvgh (Gast)
>
1
>...
2
>#defineANZAHL"6"
3
>...
4
>sprintf(puffer,"Zählerstand: %"ANZAHL"u",value);
5
>...
6
>
Hat aber den Nachteil, dass ich die ANZAHL später auch noch mal als Zahl
benötige und hier nur einen String in der ANZAHL habe.
Das einzige was bei mir wirklich funktioniert, ist die Variante von Vlad
Tepesch.
>
1
>#defineSTRINGIFY_SUB(str)#str
2
>#defineSTRINGIFY(str)STRINGIFY_SUB(str)
3
>
4
>#defineANZAHL6
5
>
6
>sprintf(puffer,"%"STRINGIFY(ANZAHL)"u\t",daten);
7
>
8
>
Hier kann ich die ANZAHL später auch noch als ganz normal Zahl nutzen.
Ich tue mich immer sehr schwer mit solchen Makros. Wenn ich das Richtig
verstehe, funktioniert das so(bitte korrigiert mich):
Der Preprozessor ersetzt den Text
'STRINGIFY(ANZAHL)' zuerst in 'STRINGIFY_SUB(ANZAHL)' und dann noch mal
'STRINGIFY_SUB(ANZAHL)' in "6". Die # macht ja praktisch einen String
daraus.
Warum muss das so kompliziert. Warum geht nicht einfach:
1
#define STRINGIFY(str) #str
2
3
#define ANZAHL 6
4
5
sprintf(puffer,"%"STRINGIFY(ANZAHL)"u\t",daten);
Diese gekürzte Version funktioniert nicht. Verstehen tue ich das
allerdings nicht, da im Endeffekt doch das gleiche dabei rauskommen
müsste, oder nicht?
@Prachz Kerl
Ist schon klar, dass die Funktion Rechenzeit und Speicher frisst. Soll
im Moment aber erst mal trotzdem so gemacht werden.
Viele Grüße
antong
Anton G. schrieb:> Diese gekürzte Version funktioniert nicht. Verstehen tue ich das> allerdings nicht, da im Endeffekt doch das gleiche dabei rauskommen> müsste, oder nicht?
Das "String-machen" muss einfach etwas verzögert werden, damit vorher
das ANZAHL durch 6 ersetzt wird:
STRINGIFY(ANZAHL) -> STRINGIFY_SUB(6) -> "6"
Deine gekürzte Variante wäre:
STRINGIFY(ANZAHL) -> "ANZAHL"
Und da wird dann ANZAHL nicht mehr durch 6 ersetzt, weil ja innerhalb
von Strings nichts ersetzt wird.
Danke Stefan Ernst.
Also muss ich mein Verständnis oben korrigieren nach
'STRINGIFY(ANZAHL)' zuerst in 'STRINGIFY_SUB(6)' und dann noch mal
'STRINGIFY_SUB(6)' in "6".
Dann ist das auch gar nicht mehr so unlogisch.
Danke an Allen. Habt mir sehr geholfen.
Gruß antong