Forum: Compiler & IDEs Zahlen auf LCD ausgeben


von The F. (frotzzi)


Lesenswert?

Hallo zusammen, ich bin ein einsteiger in C und versuche grade auf einem 
LCD_Display zahlen auszugeben.

Auf der FAQ Seite habe ich mir schon "Wie kann ich Zahlen auf LCD/UART 
ausgeben?" durchgelesen aber nicht zu 100% verstanden.
Link 
https://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F

Ich habe mal Spaßes weise den Code einfach kopiert und ausprobiert und 
es funktioniert. Aber was habe ich davon wenn ich es einfach nur 
einfüge. Kann man den Code vereinfachen so das es auch ein Anfänger 
versteht?

Mein Ziel ist es den Code zu verstehen und daraus eine neue Funktion zu 
machen FtoA
1
u = ( (unsigned)-(z+1) ) + 1; //ich weiß das hier unsigned für posetive Zahlen steht aber was hat es mit z+1 zu tun und warum?
1
Buffer[i++] = '0' + u % 10; // hier verstehe ich den "u % 10" Teil nicht, kann man das einfacher schreiben?
1
u /= 10; //Vereinfacht wäre es ja dann "u = u / 10;" oder?
1
 
2
// Ich verstehe zwar was es macht das die Zahlen sich spiegeln sollen
3
// aber ich verstehe nicht wie
4
// bei der for-schleife verstehe ich das i/ 2 nicht warum man es tut.
5
6
      for( j = 0; j < i / 2; ++j ) {
7
      tmp = Buffer[j];
8
      Buffer[j] = Buffer[i-j-1];
9
      Buffer[i-j-1] = tmp;
10
    }
11
    Buffer[i] = '\0';


Original Code
1
void ItoA( int z, char* Buffer )
2
{
3
  int i = 0;
4
  int j;
5
  char tmp;
6
  unsigned u;    // In u bearbeiten wir den Absolutbetrag von z.
7
  
8
    // ist die Zahl negativ?
9
    // gleich mal ein - hinterlassen und die Zahl positiv machen
10
    if( z < 0 ) {
11
      Buffer[0] = '-';
12
      Buffer++;
13
      // -INT_MIN ist idR. größer als INT_MAX und nicht mehr 
14
      // als int darstellbar! Man muss daher bei der Bildung 
15
      // des Absolutbetrages aufpassen.
16
      u = ( (unsigned)-(z+1) ) + 1; 
17
    }
18
    else { 
19
      u = (unsigned)z;
20
    }
21
    // die einzelnen Stellen der Zahl berechnen
22
    do {
23
      Buffer[i++] = '0' + u % 10;
24
      u /= 10;
25
    } while( u > 0 );
26
27
    // den String in sich spiegeln
28
    for( j = 0; j < i / 2; ++j ) {
29
      tmp = Buffer[j];
30
      Buffer[j] = Buffer[i-j-1];
31
      Buffer[i-j-1] = tmp;
32
    }
33
    Buffer[i] = '\0';
34
}

von zyxw (Gast)


Lesenswert?

Es reicht, i/2 Stellen zu spiegeln, d.h. zu vertauschen.

Das beschriebene ist aber ein recht rechenaufwendiges Verfahren.

Suche nach Peters Danneggers Add-Sub-Methode, die braucht keine "teuren" 
%- und /-Operationen.
% ist die Modulo-Funktion, d.h. der Rest der Division. Damit werden die 
einzelnen Ziffern berechnet.

>    u = ( (unsigned)-(z+1) ) + 1;
Die Zeile und deren Original-Kommentar sind ziemlich sinnlos.
Gemeint ist, dass bei z.B. bei int16_t  es zwar -32768, aber nur +32767 
gibt.

Der Autor meint, dass er das mit dem +1 irgendwie umschiffen kann 
(-32768+1=-32767), das geht aber nicht, weil sich in der int_t 32768 
immer noch nicht darstellen lässt.
Er müsste es schon in eine neue unsigned-Variable berechnen.
I.d.R braucht man aber diese Fallunterscheidung gar nicht, der Compiler 
/ Prozessor macht es irgendwie richtig.

von W.S. (Gast)


Lesenswert?

The F. schrieb:
> Auf der FAQ Seite habe ich mir schon "Wie kann ich Zahlen auf LCD/UART
> ausgeben?" durchgelesen aber nicht zu 100% verstanden.

Das ist im Prinzip doch ganz einfach. Laß dich aber nicht von den gern 
und oft benutzten C-typischen Abkürzungen und Sonderzeichen verwirren.

So, jetzt mal in "symbolischer" Sprache:

1. Methode, wenn man mit Rechenkraft nur so um sich schmeißen kann:

if Zahl ist 0 then Ergebnis = "0" und raus.
Ergebnis = "";
while Zahl ist nicht 0 do
begin
  Ziffer = (Zahl modulo 10) + '0';
  Zahl = Zahl durch 10;
  Ergebnis = Ziffer + Ergebnis;
end

Eine Variante davon ist das Verwenden von ldiv_t, womit man modulo und 
durch in einem Ruck hat.



2. Methode, so wie im Schulbuch 1. oder 2. Klasse:
(größte glatte Zahl sei hier mal 10000, weil ein 16 Bit Integer nicht 
die 100000 erreichen kann)
Ergebnis = "";
for Stelle=10000, dann 1000, dann 100 dann 10 to 1 do
begin
  Ziffer = '0';
  while Zahl >= Stelle do
  begin
    Zahl = Zahl - Stelle;
    Ziffer = Ziffer + 1;
  end
  Ergebnis = Ergebnis + Ziffer;
end

Noch ein Tip: In der steinalten Lernbetty (hier im Forum zu saugen) ist 
ein Modul conv.c, wo du solche Konvertierungen mal nachlesen kannst, so 
du magst.

W.S.

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.