Forum: Mikrocontroller und Digitale Elektronik Integer nach ASCII umwandeln


von Pet (Gast)


Lesenswert?

Ich versuche gerade von BASCOM auf C umzusteigen.
Habe eine kleines Unterprogramm geschrieben, welches eine Integerzahl
über den UART ausgibt:


void print_char (char c)
{
     while (!(UCSRA & (1<<UDRE))){}
         UDR = c;
}

void print_int (int wert)
{
  int temp;
  int i;


  for (i=0; wert!=0; i++)
  {
    temp = wert % 10;
    temp += 48;
    print_char(temp);
    wert /= 10;
  };
}

Das Funktioniert auch, allerdings werden die Stellen falsch herum (also
mit der kleinste Stelle zuerst ausgegebne).
Ich könnte zwar die einzelnen Stellen in ein ARRAY schreiben und dann,
falsch herum ausgeben.

Gibt es vielleicht eine eleganter Methode dafür?

von Rahul (Gast)


Lesenswert?

Dazu gibt es im K&R ein Beispiel...

von Pet (Gast)


Lesenswert?

Dumme Frage:
was ist K&R

von Rahul (Gast)


Lesenswert?

Kernighan & Ritchie
Die haben ein Buch namens "The C-Programming language" geschrieben.
Es ist quasi die C-Bibel...

von Pet (Gast)


Lesenswert?

Ich noob:)
lol

von Xenu (Gast)


Lesenswert?

>Gibt es vielleicht eine eleganter Methode dafür?

Die meisten Compiler (z.B. avr-gcc) haben eine Funktion "itoa" mit in
Ihrer C-Bibliothek, die solltest Du Dir mal anschauen...

von Pet (Gast)


Lesenswert?

Ist schon klar, aber die Funktionen sind meistens sehr groß.
Selber machen ist doch viel schöner.
Dann kann ich ja gleich bei BASCOM bleiben.

von D. W. (dave) Benutzerseite


Lesenswert?

Könntest auch Subtraktions-Methode nehmen:

Mit größter Zehnerpotenz anfangen, bei 3567 als Wert z.B. 1000:
1
int minuend = 1000;
2
char temp = 0;
3
while (zahl > minuend)
4
{
5
   zahl -= minuend;
6
   temp++;
7
}
8
temp += 48;

Das packste entweder in ne Schleife und jeden Schleifendurchgang
minuend / 10 oder du machst es halt 4-5x mit konstanten Minuenden.. ich
hoffe, das Ding heißt auch Minuend ;)

von Karl H. (kbuchegg)


Lesenswert?

Entweder Du nimmst ein Array fuer die
Zwischenspeicherung oder du machst eine
rekursive Funktion:

void print_int_help (int wert)
{
  if( wert == 0 )
    return;

  int temp = wert % 10;
  print_int_help( wert / 10 );
  print_char( temp + '0' );
}

void print_int( int wert )
{
  if( wert == 0 )
    print_char( '0' );
  else
    print_int_help( wert );
}

Rekursive Funktionen werden in µC Programmierung nicht sehr
gerne gesehen, da sie alles am Stack abwickeln und der ist
meist eher knapp.

von Konrad Heisig (Gast)


Lesenswert?

Besser als "itoa" gefällt mir für solche Zwecke die Funktion
"sprintf", die genauso wie printf arbeitet, allerdings ihr Ergebnis
in eine anzugebenden (und ausreichend großen) String schreibt. Damit
kann man nicht nur die Zahl wandeln, sondern auch gleich noch was zu
deren Bedeutung schreiben (muss man aber nicht ;).

Gruß
Konrad

von Die Waldfee (Gast)


Lesenswert?

Das ist aber völlig konträr zu Pets vorhaben, den Code so klein als
möglich zu machen. "printf" ist ein Speicherfresser.

von Konrad Heisig (Gast)


Lesenswert?

Das is schon klar, nur liest das hier vielleicht auch noch jemand
anderes, der genau sowas gesucht hat - währe aufgrund des Thread-Titels
ja immerhin denkbar ;)

von Pet (Gast)


Lesenswert?

Danke für eure Antworten.
Ich habe es jetzt doch so wie ich es am Anfang geschrieben habe
realisiert.
Speicher jetzt jede Stell im Array ab und gib es dann wieder Rückwerts
aus.
Ist am einfachsten, auch wenn es vielleicht eleganter geht.

von Pet (Gast)


Lesenswert?

Hier noch der Code

void print_char (unsigned char c)
{
     while (!(UCSRA & (1<<UDRE)));
         UDR = c;
}

void print_uint (unsigned int wert)
{
  unsigned char ziffer[5], anz=0,x;
  do
  {
    ziffer[anz++] = wert % 10 + 48;
  }
  while (wert /= 10);
  for (x=anz; x!=0; x--) print_char(ziffer[x-1]);
  print_char (13); //Carriage return
  print_char (10); //line feed
}

von Karl H. (kbuchegg)


Lesenswert?

Das einzige was ich Dir ans Herz legen moechte, ist:

Gewoehn Dir schnell wieder ab, Zeichen durch ihren ASCII
Code auszudruecken:

  wert % 10 + 48

ist (bei ASCII) absolut equivalent zu:

  wert % 10 + '0';

nur dass man im zweiten Fall besser sieht, was da passiert.
Du willst das Ergebnis der modulo Division so bearbeiten
dass ein integer von 0 das Zeichen '0' ergibt, 1 zum Zeichen
'1' wird. usw.

Im Originalcode ist das nicht so offensichtlich. Spaetestens
nach 2 Wochen raetselst Du herum: Warum 48, warum 48, warum 48?
Bis es Dir dann wieder wie Schuppen aus den Haaren faellt: Der
ASCII Code von '0' ist 48.

Selbiges fuer 13 und 10
13 ist '\r'   Carriage return
10 ist '\n'   line feed

Schreibst Du:

   print_char( '\r' );
   print_char( '\n' );

dann kannst Du Dir auch die Kommentare sparen. Jeder der C kann,
sieht im Code, und nicht im Kommentar, dass hier Carriage Return
und Line Feed ausgegeben wird. Code sollte immer selbstkommentierend
sein.

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.