www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Integer nach ASCII umwandeln


Autor: Pet (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dazu gibt es im K&R ein Beispiel...

Autor: Pet (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dumme Frage:
was ist K&R

Autor: Rahul (Gast)
Datum:

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

Autor: Pet (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich noob:)
lol

Autor: Xenu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Pet (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: D. W. (dave) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könntest auch Subtraktions-Methode nehmen:

Mit größter Zehnerpotenz anfangen, bei 3567 als Wert z.B. 1000:
int minuend = 1000;
char temp = 0;
while (zahl > minuend)
{
   zahl -= minuend;
   temp++;
}
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 ;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Konrad Heisig (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Die Waldfee (Gast)
Datum:

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

Autor: Konrad Heisig (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Pet (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Pet (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.