Integer nach ASCII umwandeln

Gast #275771
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?
Persönliche Seite #275778
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 ;)
#275779
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.
Gast #275780
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
Gast #275783
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.
Gast #275784
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
}
#275785
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren