Auf 5 Stellen füllen mit führenden Nullen:
snprintf(s,sizeof(s)-1,"%05X",irmp_data.address);
lcd_puts(s);
Einfacher gehts nicht.
Aber warum auf 5 Stellen? Der maximale Wert, den Du von IRMP bekommst,
ist 4 stellig, nämlich 0xFFFF.
Also:
snprintf(s,sizeof(s)-1,"%04X",irmp_data.address);
lcd_puts(s);
Um anzudeuten, dass es sich um eine Hex-Zahl handelt:
snprintf(s,sizeof(s)-1,"0x%04X",irmp_data.address);
Verbrät allerdings 6 Stellen auf Deinem Display. Achte darauf, das Array
s[] groß genug zu wählen, also mindestens:
char s[7]; // 6 Stellen + '\0'
Oliver Ju. schrieb:> Versuchs mal mit toupper(...)Lokus Pokus schrieb:> Jetzt hab ich schon folgendes Versucht:> lcd_puts(itoa(toupper(irmp_data.address),s,16));
^--- hat er doch!
Nur der Rest war nicht richtig, siehe andere Beiträge...
Frank M. schrieb:> snprintf(s,sizeof(s)-1,"%04X",irmp_data.address);
Ich habe gerade mal ins Manual von snprintf() geschaut:
"The functions snprintf() and vsnprintf() write at most size bytes
(including the terminating null byte ('\0')) to str."
Korrekt wäre demnach:
snprintf (s, sizeof(s), "%04X", irmp_data.address);
Sonst könnte am Ende eine Stelle fehlen, wenn man das Array s[] von der
Größe her genau passend macht.
Lokus Pokus schrieb:> geht das nicht etwas kompakter?
klar, mit Schleife. Die Funktion steht genau einmal in der
lcd-standard-lib und wird dann nie mehr angefasst. Sie geht - weil sie
einfach ist - immer und überall uc-übergreifend mit ARM und AVR-IDEs.
Du kannst es aber auch mit Schleife oder itoa oder snprintf machen. Ist
dann aber - wie die Beiträge zeigen - nicht mehr ganz so einfach.
Lokus Pokus schrieb:> Jetzt hab ich schon folgendes Versucht:> lcd_puts(itoa(toupper(irmp_data.address),s,16));>> Allerdings funkt das nicht.
Wäre eine schöne Übung um deine C Kenntnisse zu verbessern zu erkennen
WARUM das so nicht funkt.
Kleiner Tipp: Was ist der Variablentyp der Eingangsvariable von itoa()
und was ist der Ein und Ausgangstyp von toupper().
Frank M. schrieb:> Sonst könnte am Ende eine Stelle fehlen, wenn man das Array s[] von der> Größe her genau passend macht.
Und was passiert wenn du eine String bis aufs letzte Zeichen voll
quetschst?
Das abschließende Nullbyte fehlt und deine nachfolgende Funktion gibt
solange Zeichen aus irgendwo im Speicher aus Zufall mal eine null kommt.
Genaugenommen müsste noch eine s[sizeof(s)-1]=0; einfügt werden.
Bei meiner Variante langt es aber wenn du das einmalig in der nähe der
Deklaration von s machst (außer wenn "s" diese eh komplett mit Null
initialisiert wird) weil diese null nie überschrieben wird.
Bei deiner Variante müsstest du das nach jedem snprintf machen!
Irgendwer schrieb:
> Frank M. schrieb:>> Sonst könnte am Ende eine Stelle fehlen, wenn man das Array s[] von der>> Größe her genau passend macht.>> Und was passiert wenn du eine String bis aufs letzte Zeichen voll> quetschst?> Das abschließende Nullbyte fehlt und deine nachfolgende Funktion gibt> solange Zeichen aus irgendwo im Speicher aus Zufall mal eine null kommt.
Kann es sein, dass dein snprintf() kaputt ist? Meins macht es so:
1
#include<stdio.h>
2
3
void
4
zweifel(intzahl)
5
{
6
chararray[8];
7
inti;
8
9
snprintf(array,sizeof(array),"%d",zahl);
10
printf("%10d -> ",zahl);
11
for(i=0;i<8;i++){
12
printf(" %d",array[i]);
13
}
14
puts("");
15
return;
16
}
17
18
int
19
main(void)
20
{
21
zweifel(12345);
22
zweifel(123456);
23
zweifel(1234567);
24
zweifel(12345678);
25
zweifel(123456789);
26
zweifel(12345678);
27
zweifel(1234567);
28
zweifel(123456);
29
zweifel(12345);
30
return0;
31
}
1
12345 -> 49 50 51 52 53 0 4 8
2
123456 -> 49 50 51 52 53 54 0 8
3
1234567 -> 49 50 51 52 53 54 55 0
4
12345678 -> 49 50 51 52 53 54 55 0
5
123456789 -> 49 50 51 52 53 54 55 0
6
12345678 -> 49 50 51 52 53 54 55 0
7
1234567 -> 49 50 51 52 53 54 55 0
8
123456 -> 49 50 51 52 53 54 0 0
Den ganzen Stress und ein paar Byte RAM kann man sich sparen, wenn man
sich ein lcd_printf() schreibt, das die Zeichen direkt ausgibt, ohne
Umweg über einen Zwischenpuffer.
Schaulus Tiger schrieb:> wenn man sich ein lcd_printf() schreibt, das die Zeichen direkt ausgibt
Oder ein lcd_putchar(), und dann fprintf() nehmen.
Habe mir letztens einen Mini-VT100-Emulator dafür geschrieben, dann
kann man auch Cursorpositionierung und Löschen gleich noch eingebettet
im Zeichenstrom erledigen.
Irgendwer schrieb:> Und was passiert wenn du eine String bis aufs letzte Zeichen voll> quetschst?> Das abschließende Nullbyte fehlt und deine nachfolgende Funktion gibt> solange Zeichen aus irgendwo im Speicher aus Zufall mal eine null kommt.
Unsinn. Kannst Du nicht lesen? Hier nochmal das Zitat aus dem Manual:
"The functions snprintf() and vsnprintf() write at most size bytes
(including the terminating null byte ('\0')) to str."
Das heisst:
1. Es werden höchstens size Zeichen geschrieben
2. Das letzte Zeichen ist immer '\0'
Ergo: Der String wird immer terminiert.
> Genaugenommen müsste noch eine s[sizeof(s)-1]=0; einfügt werden.
Doppel-Falsch:
a) sizeof(s)-1 ist falsch: Du hast ein Zeichen zu wenig, weil
snprintf() bereits mit '\0' terminiert - und zwar bereits
an der Stelle sizeof(s)-2, wenn Du sizeof(s)-1 als Argument
heruntergibst.
b) Eigene Terminierung ist doppelt gemoppelt.
> Bei deiner Variante müsstest du das nach jedem snprintf machen!
Unsinn.
Du hast snprintf() nicht verstanden. Ich habe meine Korrektur doch genau
mit dem Manual-Auszug begründet. Wie konnte Dir das entgehen?
Wahrscheinlich bist Du einer der Übervorsichtigen: Array vorsichtshalber
128 Bytes groß, obwohl nur 16 Stellen benutzt werden. Da fällt Dir
natürlich eine vorzeitige Terminierung von snprintf() an der Stelle
sizeof(s)-2 gar nicht auf ;-)
P.S.
Du verwechselst das Verhalten offenbar mit strncpy(). Da hättest Du
nämlich Recht, strcnpy() ist tatsächlich ziemlich fies in dieser
Hinsicht. Es knallt den Target-String bis zur Stelle n-1 (inkl.) voll
und terminiert dann tatsächlich nicht, wenn kein Platz mehr ist.
Lokus Pokus schrieb:> die Großschreibung ist da jetzt aber nicht inkludiert.
Klar: %x macht klein, %X macht groß. %04X füllt mit Nullen auf, bis das
Ding insgesamt 4 Stellen hat.
Ist also eine Rundum-Lösung für Dich.
grundschüler schrieb:
Solange du sowas schreibst
> x=(byteX%(65536>>(4*i)))/(4096>>(4*i));
sollte man den Leistungsvergleich erst mal links liegen lassen.
grundschüler schrieb:> x=(byteX%(65536>>(4*i)))/(4096>>(4*i));
Sag mal, weisst Du, was Du da tust?
65536 ist schon kein uint16_t mehr, da ist nämlich bei 65535 Schluss. Du
shiftest also einen Long (falls der Compiler 65636 ohne "L" dahinter
überhaupt versteht) um einen variablen Wert.
Da eine ATmega keinen Barrel-Shifter hat, kommt da eine gaaaaanz lange
Schleife raus.
Das Ganze 2 mal. Das ist krass.
Variante A: 7792 Bytes
Das mach ich mit weniger als einem Zehntel.
> A erfüllt alle Anforderungen, ist einfacher und kürzer...
Von einfacher kann keine Rede sein.
Frank M. schrieb:> falls der Compiler 65636 ohne "L" dahinter überhaupt versteht
Ja, macht er, muss er machen.
Aber das Ding taugt eher als Einstieg in den IOCCC denn als eine
allgemein anpreisbare Implementierung.
Dass ein printf nicht klein ist, ist von vornherein klar. Aber
sofern man die paar Bytes mehr nicht gerade wirklich knausern muss,
weil man den falschen Controller für den Job gewählt hat (oder das
Pflichtenheft auf mysteriöse Weise sich mittlerweile verdoppelt hat ;),
dann hat man mit der printf-Familie auf jeden Fall eine Lösung, bei
der man ohne graue Haare schnell zum Ziel kommt, weil man sich auf
das Wesentliche konzentrieren kann, statt sich mit derartigen
Nebensächlichkeiten abquälen zu müssen.
Jörg Wunsch schrieb:> Ja, macht er, muss er machen.
Ich erinnere mich noch an Zeiten, da musste man für F_CPU bei 8000000
immer ein L dranpappen, damit es richtig übersetzt wurde ;-)
> Aber das Ding taugt eher als Einstieg in den IOCCC denn als eine> allgemein anpreisbare Implementierung.
grundschüler hat etwas ähnliches kryptisches in "Projekte und Code"
gepostet. Ein Source, den weder ein Mensch noch ein Compiler verstehen
kann. Das grenzt schon an Unverschämtheit.
> Dass ein printf nicht klein ist, ist von vornherein klar. Aber> sofern man die paar Bytes mehr nicht gerade wirklich knausern muss,> weil man den falschen Controller für den Job gewählt hat (oder das> Pflichtenheft auf mysteriöse Weise sich mittlerweile verdoppelt hat ;),> dann hat man mit der printf-Familie auf jeden Fall eine Lösung, bei> der man ohne graue Haare schnell zum Ziel kommt, weil man sich auf> das Wesentliche konzentrieren kann, statt sich mit derartigen> Nebensächlichkeiten abquälen zu müssen.
Das sehe ich genauso. Gefragt war eine einfache Lösung. snprintf()
ist eine einfache Lösung.
Wenn man die kürzeste Lösung haben will:
1
#include<stdint.h>
2
3
staticuint8_t
4
itox(uint8_tval)
5
{
6
uint8_trtc;
7
8
val&=0x0F;
9
10
if(val<=9)
11
{
12
rtc=val+'0';
13
}
14
else
15
{
16
rtc=val-10+'A';
17
}
18
return(rtc);
19
}
20
21
staticvoid
22
itoxx(char*xx,unsignedchari)
23
{
24
*xx++=itox(i>>4);
25
*xx++=itox(i&0x0F);
26
}
27
28
staticvoid
29
itoxxxx(char*xx,unsignedinti)
30
{
31
itoxx(xx,i>>8);
32
itoxx(xx+2,i&0x0FF);
33
}
34
35
int
36
main()
37
{
38
charbuf[5];
39
40
uint16_tu=1234;
41
42
itoxxxx(buf,u);
43
buf[4]='\0';
44
}
Verbraucht gerade mal 224 Bytes im Flash, also weitab von der
verkorksten Lösung von grundschüler. Ausserdem bietet es 1, 2 und 4
stellige Ausgabe an :-)
Frank M. schrieb:> Ich erinnere mich noch an Zeiten, da musste man für F_CPU bei 8000000> immer ein L dranpappen, damit es richtig übersetzt wurde ;-)
Nö, machen die Leute nur aus Gewohnheit.
Für <util/delay.h> kann man auch 8E6 schreiben, dann spart man sich
das mühselige Zählen der Nullen. ;-) <util/setbaud.h> braucht es aber
als Ganzzahl.
Jörg Wunsch schrieb:> Frank M. schrieb:>> Ich erinnere mich noch an Zeiten, da musste man für F_CPU bei 8000000>> immer ein L dranpappen, damit es richtig übersetzt wurde ;-)>> Nö, machen die Leute nur aus Gewohnheit.>
War da nicht irgendwas mit dem unsigned. Denn eigentlich lautet es ja
1
#define F_CPU 8000000UL
und das U für unsigned war wichtig. Ich kann aber nicht mehr sagen, bei
welcher Berechnung da dann was schief ging. Könnte irgendwas mit
Bitshifts zb bei Baudratenberechnung zu tun haben. Aber genaueres weiss
ich auch nicht mehr.
Karl Heinz schrieb:> War da nicht irgendwas mit dem unsigned.
Ja, das eher noch. Kann sein, dass sonst ein Zwischenergebnis
mal negativ wird. Hängt aber natürlich davon ab, was man mit F_CPU
noch so anstellt. <util/delay.h> benutzt den Makro sowieso innerhalb
von Gleitkommaberechnungen, da ist das egal.
Karl Heinz schrieb:> War da nicht irgendwas mit dem unsigned. Denn eigentlich lautet es ja>
1
>#defineF_CPU8000000UL
2
>
> und das U für unsigned war wichtig.
Ja, kann tatsächlich so gewesen sein. Ich habs auch nicht mehr so genau
im Kopf. Aber irgendwas war da mal. Ist aber schon ein paar Jährchen
her.
Egal.
> int> main ()> {> char buf[5];>> uint16_t u = 1234;>> itoxxxx (buf, u);> buf[4] = '\0';> }> [/c]>> Verbraucht gerade mal 224 Bytes im Flash, also weitab von der> verkorksten Lösung von grundschüler. Ausserdem bietet es 1, 2 und 4> stellige Ausgabe an :-)
Kannst du mir das bitte erläutern wie ich das jetzt in meinem Beispiel
umsetze?
Ist u jetzt der Wert den ich Umwandeln möchte oder die Anzahl der
Null-Stellen?
Lokus Pokus schrieb:> Ist u jetzt der Wert den ich Umwandeln möchte oder die Anzahl der> Null-Stellen?
Du verzeihst, dass ich schmunzle.
Der Funktionsaufruf lautet
1
itoxxxx(buf,u);
buf ist recht offensichtlich das char Array, in welches die ASCII
Repräsentierung rein soll.
Was also wird u sein, wenn die Funktion einen Wert in eine ASCII
Darstellung umwandelt?
Und warum hat die Funktion, die einen uint16_t in eine ASCII-Hex
Darstellung umwandelt (4 hexadezimale Ziffern) 4 Stück x im Namen,
während eine Funktion itoxx, die einen unsigned char umwandelt (2
hexadezimale Ziffern) nur 2 x im Namen hat?
Konsequenterweise hätte Frank die Funktionen allerdings itoXXXX und
itoXX genannt, denn die ASCII Repräsentierungen werden ja mit
Grossbuchstaben gebildet. Aber ... das sei ihm mal nachgesehen :-)
> *xx++ = itox (i & 0x0F);
das &0x0F kann man weglassen, da es in itox eh gemacht wird.
Es geht auch Anders (aus dem Stegreif):
u16_t x;
hex[]="0123456789ABCDEF";
putch('0');putch('X');putch('0');
putch(hex[ x>>12 ]);
putch(hex[(x>>8)&15]);
putch(hex[(x>>4)&15]);
putch(hex[ x &15]);
oder wenn man doch ein out-String will:
out[]="0x03456\0";
out[6]=hex[ x &15];
out[5]=hex[(x>>=4)&15];
out[4]=hex[(x>>=4)&15];
out[3]=hex[ x>> 4 ];
Lokus Pokus schrieb:> Dann muß ich für die Funktion itoxxxx bereits den umgewandelten HEX Wert> angeben oder wie?> Oder ersetzt es das ursprüngliche itoa?
es ersetzt das ursprüngliche itoa.
Was ist denn so schwer drann einfach mal
1
...
2
chars[20];
3
4
itoxxxx(s,15);
5
lcd_puts(s);
in ein Testprogramm zu schreiben und nachzusehen, ob danach
1
000F
auf dem LCD steht?
D.h. die Zahl, ausgedrückt als Hex-Zahl, mit Grossbuchstaben, und auf 4
Stellen aufgeblasen.
Mehr oder weniger funktioniert das.
Allerdings habe ich noch ein unerwünschtes Verhalten.
Die komplette Schaltung soll mit einer 3V Lithium Zelle betrieben
werden.
Wenn ich die Funktion nun verwende:
1
chars[7];
2
3
dogm_cursor(0,2);
4
dogm_puts("A: ");
5
itoxxxx(s,irmp_data.address);
6
dogm_puts(s);
7
dogm_puts(" C: ");
8
itoxxxx(s,irmp_data.command);
9
dogm_puts(s);
dann verstümmelt es mir die Anzeige nach ein paar Ausgaben. Im
Netzbetrieb passiert das nicht.
Ist diese Funktion nun so Performancelastig das dabei der AVR in die
Knie geht?
Lokus Pokus schrieb:> dann verstümmelt es mir die Anzeige nach ein paar Ausgaben.
Verstümmeln bedeutet?
> Im> Netzbetrieb passiert das nicht.> Ist diese Funktion nun so Performancelastig das dabei der AVR in die> Knie geht?
Dem µC ist das grundsätzlich wurscht was er macht. Deswegen braucht er
da auch nicht mehr Strom.
Schon mal frische Batterien probiert?
Tor Tor Tor schrieb:> Lokus Pokus schrieb:>> lcd_puts(itoa(toupper(irmp_data.address),s,16));>> lcd_puts(toupper(itoa(irmp_data.address,s,16)));
falsch.
Können wir diesen Nebenschauplatz jetzt bitte in Frieden ruhen lassen?
Das 'Problem' ist schon längst gelöst.
(Falls es interessiert. Es ist deswegen falsch, weil toupper keinen
String konvertiert, sondern ein einzelnes Zeichen.)
int snprintf(char* buffer, size_t nsize, const char* fmt, ...);
5
int snwprintf(wchar_t* buffer, size_t nsize, const wchar_t* fmt, ...);
6
7
Beschreibung
8
9
Sendet formatierte Ausgabe an einen buffer, der die in nsize angegebene Maximalgröße hat. Ist die Anzahl der auszugebenden Bytes:
10
11
< nsize, so werden alle Zeichen einschließlich des abschließenden ‘\0’- Zeichens geschrieben.
12
13
== nsize, so werden nsize Zeichen ohne das abschließende ‘\0’-Zeichen geschrieben.
14
15
> nsize, so werden nsize Zeichen ohne das abschließende ‘\0’-Zeichen geschrieben.
16
Wenn nsize 0 ist, bleibt der String leer (und kann NULL sein).
Scheit also durchaus abhängig von der verwendeten Implementation der std
zu sein.
Schaulus Tiger schrieb:> zweifel (int zahl)> {> char array[8];> int i;>> snprintf (array, sizeof(array), "%d", zahl);> printf ("%10d -> ", zahl);> for (i = 0; i < 8; i++) {> printf (" %d", array[i]);> }> puts ("");> return;> }
Deine Ausgabe eines Strings ist ein Witz.
Du begrenzt die Ausgabe Fix durch deine Feste Vorgabe in der For von
Acht und wunderst dich über die Aussage.
Mach mal ein
1
printf(" %s",array);
die weiß nämlich nichts davon das sie nach acht Zeichen aufhören soll.
oder z.B.:
1
i=0;
2
do
3
{
4
if(array[i])
5
printf(" %d",array[i]);
6
elsebreak;
7
++i;
8
}while(1);
Sowie eine andere (String-)Funktion aufgerufen wird weiß diese nichts
mehr davon das dass Array nur acht Zeichen groß ist (außer man übergibt
mit sizeof diese Info) und läuft so lange bis es auf eine Null trifft.
Irgendwer schrieb:> Scheit also durchaus abhängig von der verwendeten Implementation der std> zu sein.
Wir schreiben das Jahr 2015, und seit C99 ist snprintf() genormt:
1
7.19.6.5 The snprintf function
2
Synopsis
3
4
1 #include <stdio.h>
5
int snprintf(char * restrict s, size_t n,
6
const char * restrict format, ...);
7
Description
8
9
2 The snprintf function is equivalent to fprintf, except that the
10
output is written into an array (specified by argument s) rather
11
than to a stream. If n is zero, nothing is written, and s may be a
12
null pointer. Otherwise, output characters beyond the n-1st are
13
discarded rather than being written to the array, and a null
14
character is written at the end of the characters actually written
15
into the array. If copying takes place between objects that overlap,
Lokus Pokus schrieb:> dann verstümmelt es mir die Anzeige nach ein paar Ausgaben.
Du hast vergessen, nach dem Aufruf von itoxxxx() den Buffer zu
terminieren - so wie ich es im Beispiel von itoxxxx() auch verwendet
habe.
Also:
itoxxxx(s, irmp_data.command);
buf[4] = '\0';
Das ist ein Unterschied zu itoa().
Anderenfalls kannst Du auch itoxxxx() (dann konsequenterweise auch
itoxx()) selbst terminieren lassen:
1
staticvoid
2
itoxx(char*xx,unsignedchari)
3
{
4
*xx++=itox(i>>4);
5
*xx++=itox(i&0x0F);
6
*xx='\0';// NEU!
7
}
8
9
staticvoid
10
itoxxxx(char*xx,unsignedinti)
11
{
12
itoxx(xx,i>>8);
13
itoxx(xx+2,i&0x0FF);
14
*(xx+4)='\0';// NEU!
15
}
Dann brauchst Du nur
itoxxxx(s, irmp_data.command);
aufzurufen und Du kannst Dir das:
buf[4] = '\0';
schenken.
P.S.
In main.c des IRMP-Projekts sind genau diese itoxx()-Funktionen
(mit interner Terminierung!) schon seit vielen Monaten vorhanden, um
eine konkrete Anwendung von IRMP zu zeigen. Ich frage mich, wieso Du
nicht sowieso darüber gestolpert bist.
Irgendwer schrieb:> Beschreibung>> Sendet formatierte Ausgabe an einen buffer, der die in nsize angegebene> Maximalgröße hat. Ist die Anzahl der auszugebenden Bytes:>> < nsize, so werden alle Zeichen einschließlich des abschließenden ‘\0’-> Zeichens geschrieben.>> == nsize, so werden nsize Zeichen ohne das abschließende ‘\0’-Zeichen> geschrieben.
Kannst Du dazu bitte eine Quelle nennen? Ich traue deutschen
Übersetzungen von libc-Manuals nicht.
Das da oben beschriebene wäre das gleiche Verhalten, wie strncpy() es
macht. Ich weiß aber, dass diese Implemenation für snprintf() dann
falsch wäre.
> Scheit also durchaus abhängig von der verwendeten Implementation der std> zu sein.
Nein, das ist ein Fehler. Es gibt Standards. Wenn diese nicht
eingehalten werden, ist das einen Bug-Report wert.
Sehr elegante Lösung, gefällt mir um einiges besser als mein eigenes
itoxxxx() und verbraucht zudem nur die Hälfte des Flashs :-)
Ich werde diese Version direkt in meine Libs so übernehmen.
Danke,
Frank
Lokus Pokus schrieb:> super und wie wendet man das nun wieder an?
Ist das wirklich so schwierig zu verstehen? Das erkennt man doch schon
an den Typen und Namen der Argumente. Nimm Dir abends mal ein gutes
C-Buch zur Hand. Grundlagen können nie schaden. Und wenn man das
versteht, was man da anwendet, ist das auch nicht verkehrt.
> "number" ist die Anzahl der Nullen?
Nein.
> Digits der HEX-Wert?
nein.
number (deutsch "Zahl") ist die Zahl, die Du konvertieren willst.
digits (deutsch "Ziffern") ist die Anzahl der Ziffern, auf die die
Ausgabe formatiert wird. Mit der Anzahl von Nullen hat das
wirklich nichts zu tun. Bei 0x1234 gibts z.B. keine Nullen
bei digits = 4. Jedoch gibts für die Zahl 0x12 genau 2 Nullen.
Die Ausgabe ist dann nämlich "0012".
Hier hätte statt eines C-Buchs sogar ein Wörterbuch "deutsch-englisch"
gereicht....
Irgendwer schrieb:
> Interessant das ganze:>> Scheit also durchaus abhängig von der verwendeten Implementation der std> zu sein.>> Schaulus Tiger schrieb:>> zweifel (int zahl)>> {>> char array[8];>> int i;>>>> snprintf (array, sizeof(array), "%d", zahl);>> printf ("%10d -> ", zahl);>> for (i = 0; i < 8; i++) {>> printf (" %d", array[i]);>> }>> puts ("");>> return;>> }>> Deine Ausgabe eines Strings ist ein Witz.> Du begrenzt die Ausgabe Fix durch deine Feste Vorgabe in der For von> Acht und wunderst dich über die Aussage.>> Mach mal ein
1
printf(" %s",array);
> die weiß nämlich nichts davon das sie nach acht Zeichen aufhören soll.
Doch, das merkt sie am '\0' Byte, das von einem korrekten snprintf eben
immer eingefügt wird, siehe die witzige Ausgabe:
Schaulus Tiger schrieb:
Frank M. schrieb:> buf[digits] = "0123456789ABCDEF"[number & 15];
hm, das hätte ich jetzt auf Anhieb auch nicht verstanden...
Ist das ein statisches Array?
fdghj schrieb:>> buf[digits] = "0123456789ABCDEF"[number & 15];>> hm, das hätte ich jetzt auf Anhieb auch nicht verstanden...> Ist das ein statisches Array?
Ich hätts so geschrieben:
Lokus Pokus schrieb:> Ich möchte gerne einen HEX-Wert auf einem LCD in Großbuchstaben> ausgeben.>> Jetzt hab ich schon folgendes Versucht:> lcd_puts(itoa(toupper(irmp_data.address),s,16));>> Allerdings funkt das nicht.>> Geht das so überhaupt?
Manchmal ist mir zum Heulen ob des geistigen Zustandes unserer Schreiber
hier. Sowas sollte doch eine dee allerleichtesten Fingerübungen für
jeden Programmier-Anfänger sein - und doch ist es bereits den Leuten
hier zu hoch.
Also, ich zitiere mal aus der Lernbetty (hier im Forum bereits
sedimentiert..):
const char HexChars[17] = {"0123456789ABCDEF"};
/* ein Hex-Zeichen ausgeben */
void Nibble_Out (int aHex)
{ V24_CharOut (HexChars[aHex & 0x0F]); }
/* ein Byte als Hexa ausgeben */
void HexB_Out (byte aHex)
{ Nibble_Out (aHex >> 4);
Nibble_Out (aHex);
}
/* ein Word als Hexa ausgeben */
void HexW_Out (word aHex)
{ HexB_Out (aHex >> 8);
HexB_Out (aHex);
}
/* ein DWORD als Hexa ausgeben */
void HexL_Out (long aHex)
{ HexW_Out (aHex >> 16);
HexW_Out (aHex);
}
/* ein QWORD als Hexa ausgeben */
void HexQ_Out (int64* aHex)
{ HexL_Out (*aHex >> 32);
HexL_Out (*aHex);
}
Aber bitte keine Anfragen, was denn die mysteriöse Funktion
"V24_CharOut(char blabla)" denn wohl machen wird.
Noch ein Tip: Wer es lieber in Kleinbuchstaben mag, darf das Array
"const char HexChars" umschreiben - sofern das keine geistige
Überlastung nach sich zieht.
W.S.
Frank M. schrieb:> asdfasd schrieb:>> char *>> itoh(char *buf, int digits, unsigned number)>> {>> for (buf[digits] = 0; digits--; number >>= 4)>> buf[digits] = "0123456789ABCDEF"[number & 15];>> return buf;>> }>> Sehr elegante Lösung, gefällt mir um einiges besser als mein eigenes> itoxxxx() und verbraucht zudem nur die Hälfte des Flashs :-)>> Ich werde diese Version direkt in meine Libs so übernehmen.>> Danke,>> Frank
Könnte beim AVR allerdings dauerhaft RAM für den String benötigen. Je
nachdem, wie gut der Compiler optimiert. Hast Du das getestet?
Im Zweifel würde ich eher beim if bleiben:
> for (buf[digits] = 0; digits--; number >>= 4) {> if((buf[digits] = '0'+(number & 0x0F))>'9'){buf[digits]+=7;}> }> [/c]> Eine while-Schleife wäre sowieso eleganter.
Diese Variante benötigt 2 Bytes mehr im Flash
> Die Magic 7 stört da noch.
Dann schreib halt 'A'-10-'0' (65-10-48=7).
> Diese Variante benötigt 2 Bytes mehr im Flash
Als welche?
Da Compiler das Konstrukt ?: manchmal unglücklich übersetzen, probier
mal:
for (buf[digits] = 0; digits--; number >>= 4) {
unsigned char val = '0'+(number & 0x0F);
if(val > 9){val += 'A'-10-'0';}
buf[digits] = val;
mit while schaut das dann so aus:
1
buf[digits]=0;//terminating \0
2
do{
3
unsignedcharval='0'+(number&0x0F);
4
if(val>9){val+='A'-10-'0';}
5
buf[digits]=val;
6
number>>=4;
7
while(--digits>0);//digits würde ich signed machen, damit 0 nicht 256 Durchläufe macht
8
}
Wieviel Flash braucht das?
Jetzt wäre ein Vergleich der Listings interessant.
Da es alle meine Compiler umständlich machen, habe ich es gleich als
Inline-Asm programmiert, da sind es wirklich nur ein paar Befehle.
Dein Code addiert bei Ziffern über 9 zuerst '0' und dann nochmal 7.
Meine Version addiert nur einmal den richtigen Wert. Vermutlich ist das
genau die zusätzliche Instruktion, die 2 Byte mehr Flash braucht.
Was daran eleganter sein soll, erschließt sich mir nicht so recht, aber
das ist wohl Geschmackssache.