printf


printf gibt formatierte Ausgaben auf dem Standardausgabekanal aus. Bei Verwendung eines PC-Betriebssystems ist der Standardausgabekanal die Konsole / Terminal. Bei Verwendung mittels eines Mikrocontrollers muss je nach benutzter Hardware ein Ausgabekanal geschaffen werden, bpsw. ein angeschlossenes Display, eine Ausgabe über die serielle Schnittstelle oder anderes.

Bei Verwendung mit einem Mikrocontroller ist zu überdenken, ein "full featured" printf einzusetzen, da printf sehr speicherintensiv ist, besonders in Verbindung mit der Ausgabe von Gleitkommazahlen. Ein im Leistungsumfang reduzierter, aber in vielen Fällen ausreichender Ersatz für printf ist my_printf.

    Syntax von printf      : int printf(const char *format [, argument, ...]);
    Prototypdeklaration in : stdio.h
printf unterscheidet sich im Gegensatz zu den meisten Funkktionen in C darin, dass für diese Funktion eine nicht definierte (variable) Anzahl von Funktionsparametern (argument) übergeben werden kann. Bei fehlerfreier Ausfuehrung liefert printf die Anzahl der insgesamt ausgegebener Zeichen als Funktionsargument zurück.
    const char *format
enthält den zwingend notwendigen String, der ausgegeben werden soll. Alle eventuell nachfolgende Funktionsparameter sind optional.

Beispiel:
    printf("Hallo Welt");
Innerhalb des Strings *format können Umwandlungszeichen (engl. conversion modifier) für weitere Parameter eingesetzt werden, die eine
Formatierung der Ausgabe ermöglichen. Außerdem kann dieser String
Escape-Sequenzen enthalten, die ebenfalls der formatierten Ausgabe dienen.


Umwandlungszeichen %


Prinzipiell funktionieren die Umwandlungszeichen nach folgendem Schema: Ein Umwandlungszeichen wird mit dem %-Zeichen (Ascii-Code 37) als Einleitungszeichen angegeben.

Direkt anschließend an dieses Einleitungszeichens können weitere Angaben folgen:

  • ein Flagzeichen (erlaubte Zeichen: SPACE,-,+,#,0)
  • die Feldbreite
  • durch einen Punkt getrennt die Anzahl der Nachkommastellen
  • an letzter Stelle das Umwandlungszeichen (und somit den Ausgabetyp)

Ein einfaches Beispiel nur mit Umwandlungszeichen (ohne Flags, ohne Feldbreite und ohne Punkt):
    printf("1. Zahl= %d, 2. Zahl= %d, 3. Zahl= %d",34, 65, 99);
Ausgabe:
    1. Zahl= 34, 2. Zahl= 65, 3. Zahl= 99
Erklärung:

Da im Ausgabestring insgesamt 3 Umwandlungszeichen enthalten sind (3 mal %d), werden diese %d durch die jeweils folgenden Parametern ersetzt. D.h. anstelle des ersten im String enthaltenen %d wird die dem %d zugeordneter Parameter ausgegeben. Im vorliegenden Falle wird also in den Text die Zahl 34 mit dezimaler Ausgabe eingefügt. Anstelle des zweiten Vorkommens von %d wird 65, anstelle des dritten wird 99 ausgegeben.


Verfügbare Umwandlungszeichen sind:


     Zeichen 
    Datentyp und Darstellung

    %d
    Integer als dezimale Zahl ausgeben
    %i
    Integer als dezimale Zahl ausgeben
    %c
    Ausgabe eines char als (Ascii)-Zeichen
    %e
    Ausgabe einer double Gleitkommazahl im wissenschaftlichen Format (bspw.: 3.342409e+3)
    %E
    Ausgabe einer double Gleitkommazahl im wissenschaftlichen Format (bspw.: 3.342409E+3)
    %f
    Ausgabe einer double Gleitkommazahl (bspw.: 33424.092342)
    %o
    oktale Ausgabe eines Integers
    %p
    Ausgabe der Adresse eines Pointers
    %s
    Ausgabe einer Zeichenkette (String)
    %x
    Integer als hexadezimale Zahl ausgeben, alphanumerische Ziffern werden klein geschrieben
    %X
    Integer als hexadezimale Zahl ausgeben, alphanumerische Ziffern werden groß geschrieben
    %u
    Ausgabe eines vorzeichenlosen Integers
    %%
    Ausgabe des Prozentzeichens

Beispiele:
    printf("int : %d \n", 65);
    printf("negative int : %d \n",-65);
    printf("Gleitkomma : %.6f \n", M_PI);
    printf("Asciizeichen 65 : %c \n", 'z');
    printf("Zeichenkette : %s \n", "AbCdEf");
    printf("43 in Oktal : %o\n", 65); printf("43 in Hex : %x\n", 65); printf("Prozentzeichen : %%\n");
Ausgabe:
    int : 65
    negative int : -65
    Gleitkomma : 3.141593
    Asciizeichen 65 : z
    Zeichenkette : AbCdEf
    43 in Oktal : 101
    43 in Hex : 41
    Prozentzeichen : %


Flag / Flagzeichen


Direkt nach dem %-Einleitungszeichen kann ein sogenanntes Flag-Zeichen (Kennzeichnung) angegeben werden. Dieses Zeichen beeinflußt die Ausgabe auf dem Ausgabekanal.

     Zeichen  Bedeutung

    -
    Text wird linksbuendig ausgerichtet
    +
    auch bei einem positiven Zahlenwert wird ein Vorzeichen mit ausgegeben
    SPACE
    Leerzeichen, ein Leerzeichen wird ausgegeben, wenn der Wert positiv ist
    #
    abhängig von Format und Betriebssystem. In Verbindung mit hexadezimaler Ausgabe wird der Ausgabe "0x" vorangestellt.
    0
    eine Auffüllung erfolgt mit Nullen anstelle von Leerzeichen
Beispiel:
    printf("Hex-Zahl: %#x\n", 76);
Ausgabe:
    Hex-Zahl: 0x4c


Feldbreite und Nachkommastellen


Nach den Flags können Angaben zur Gesamtzeichenanzahl der Ausgabe (Feldbreite) und / oder Angabe zur Anzahl der Nachkommastellen gemacht werden.

Wird eine für die Gesamtbreite eine höhere Anzahl Stellen angegeben, als die auszugebende Zahl selbst besitzt, so wird die Ausgabe linksseitig um Leerstellen aufgefüllt, so dass die geforderte Gesamtbreite erfüllt ist.

Ist als Flag die Ziffer "0" angegeben, so wird die Gesamtausgabe mit Nullen anstelle von Leerzeichen aufgefüllt. Soll eine Gleitkommazahl ausgegeben werden (float oder double), so kann die Feldbreite durch ein "." Zeichen auch den Nachkommateil beinhalten. Hierbei gibt die Angabe für die Feldbreite die Gesamtzeichenzahl der Ausgabe an, die Ziffernangabe nach dem Punkt die Anzahl der Stellen des Nachkommateils.

Überschreitet die Anzahl der Zeichen für den Nachkommateil die Angabe für die Gesamtzeichenanzahl, so werden jedoch die Zeichen für den Nachkommateil garantiert ausgegeben, so dass die Gesamtzeichenanzahl der Ausgabe in diesem Fall die der angegebenen
Feldbreite überschreitet.

Der Punkt, der den Vorkommateil vom Nachkommateil trennt zählt hierbei als Zeichen für die Gesamtbreite. Es kann auch nur die Anzahl der Nachkommastellen ohne führende Gesamtanzahl angegeben werden.

Beispiele:
    printf("\n1234567890");
    printf("\n%10d",23);
    printf("\n%010d",65);
    printf("\n%10.4f",M_PI);
    printf("\n%.3f",M_PI);
    printf("\n");
Ausgabe:
    1234567890
            23
    0000000065
        3.1416
    3.142


Escape-Sequenzen / Steuerzeichen



Der Ausgabestring kann sogenannte Steuerzeichen (Escape-Sequenzen) enthalten. Das Ausgabeverhalten hängt vom verwendeten Terminal bzw. der verwendeten Terminalemulation ab (die Windowskonsole verhält sich leider abweichend zur Linuxkonsole).

Ein Steuerzeichen wird durch einen Schrägstrich nach rechts unten (engl. backslash) "angemeldet".


    Zeichen
    Bedeutung

    \n
    (new line) fügt eine neue Zeile unterhalb der aktuellen Zeile ein. Hierbei ist das Ausgabeverhalten von der Terminalemulation abhängig. Die Linuxkonsole generiert bei einem "new line" Kommando auch ein Bewegen des Cursors an den Zeilenanfang (was einem "carriage return" entspricht). Bei der Windowskonsole bleibt der Cursor in der x-Position verharren, an der er sich befindet. Ein "/n" unter Linux bewirkt somit dasselbe wie ein "/n/r" unter Windows.
    \r
    (carriage return) bewirkt ein Setzen des Cursors an den Zeilenanfang
    \t
    setzt den Cursor auf die nächste horizontale Tabulatorposition
    \b
    setzt den Cursor ein Zeichen nach links OHNE das aktuelle Zeichen hierbei zu löschen
    \f
    setzt den Cursor auf die Startposition der nächsten Seite
    \v
    setzt den cursor auf die nächste vertikale Tabulatorposition
    \0
    markiert das Ende einer Textzeile (nachfolgende Zeichen werden nicht mehr interpretiert und auch nicht ausgegeben

Beispiel (unter Verwendung von \n \r t und Flags):

    // Hinweis: \r Escape-Sequenz waere fuer Programmlauf unter Linux nicht notwendig

    printf("\n\rQuadratzahlen\t Wurzel\t\t  Reziprokenwerte");
    printf("\n\r---------------------------------------------------\n\r");
    for (i= 1; i< 17; i++)
    {
      printf("\n\r %2d * %2d= %4d\t sqrt(%2d)= %4.2f\t  1/%2d= %.4f",         \
                    i,    i,  i*i,    i,   sqrt((float)i), i,  1.0/(float)i);
    }

Ausgabe:
 
Quadratzahlen    Wurzel           Reziprokenwerte
---------------------------------------------------

   1 *  1=    1   sqrt( 1)= 1.00   1/ 1= 1.0000
   2 *  2=    4   sqrt( 2)= 1.41   1/ 2= 0.5000
   3 *  3=    9   sqrt( 3)= 1.73   1/ 3= 0.3333
   4 *  4=   16   sqrt( 4)= 2.00   1/ 4= 0.2500
   5 *  5=   25   sqrt( 5)= 2.24   1/ 5= 0.2000
   6 *  6=   36   sqrt( 6)= 2.45   1/ 6= 0.1667
   7 *  7=   49   sqrt( 7)= 2.65   1/ 7= 0.1429
   8 *  8=   64   sqrt( 8)= 2.83   1/ 8= 0.1250
   9 *  9=   81   sqrt( 9)= 3.00   1/ 9= 0.1111
  10 * 10=  100   sqrt(10)= 3.16   1/10= 0.1000
  11 * 11=  121   sqrt(11)= 3.32   1/11= 0.0909
  12 * 12=  144   sqrt(12)= 3.46   1/12= 0.0833
  13 * 13=  169   sqrt(13)= 3.61   1/13= 0.0769
  14 * 14=  196   sqrt(14)= 3.74   1/14= 0.0714
  15 * 15=  225   sqrt(15)= 3.87   1/15= 0.0667
  16 * 16=  256   sqrt(16)= 4.00   1/16= 0.0625 


sprintf



sprintf verhält sich genau wie printf mit dem Unterschied, dass die Ausgabe nicht auf dem Standardausgabekanal, sondern in einen String (d.h. in ein Char-Array) erfolgt.

    Syntax von sprintf     : int sprintf(char *buffer, const char *format [, argument, ...]);

    Prototypdeklaration in : stdio.h
Sämtliche Angaben fuer Umwandlungszeichen, Flags sowie Feldbreitenbezeichner die für printf gelten, sind auch für sprintf gültig.

Beispiel:

  char  txtbuffer[100];
  
  sprintf(txtbuffer, "\n%.3f * sqrt(%.1f) = %.3f\n", M_PI, 2.0, M_PI * sqrt(2.0));
  printf("%s", txtbuffer);
Ausgabe:
    3.142 * sqrt(2.0) = 4.443

my_printf


my_printf ist ein in der Funktionalität reduzierter Ersatz für den jedem C-Compiler beiliegenden printf und ist speziell für die Benutzung in Verbindung mit Mikrocontrollern gedacht. my_printf macht immer dann Sinn, wenn es darum geht Flashspeicher zu sparen und ermöglicht den Einsatz auf Mikrocontrollersystemen ab ca. 2 kByte Flashspeicher.

In der speichersparsamsten Version verfügt my_printf über keine Ausgabemöglichkeit von float oder double, ein jedoch vom Standard abweichendes Umwandlungszeichen %k ermöglicht es, Pseudo-Kommazahlen auszugeben.


my_printf
---------------------------------------------------------


my_printf ist ein in der Funktionalitaet reduzierter Ersatz fuer printf,
speziell zur Benutzung in Verbindung mit Mikrocontrollern. Er macht dann
Sinn, wenn es darum geht (Flash)speicher zu sparen und ermoeglicht den
Einsatz auf Mikrocontrollersystemen ab 2 kByte Flashspeicher.

Ein vom Standard abweichendes Umwandlungszeichen %k ermoeglicht es,
Pseudo-Kommazahlen auszugeben.

my_printf existiert im Verzeichnis ../src in den Quelltextvarianten:
  Die Syntax von printf  :  void my_printf(const char *s,...);
  Prototypdeklaration in :  ../include/my_printf.h

Um my_printf innerhalb eines Programms zur Verfuegung zu haben, muss
entsprechend der gewuenschten Funktionalitaet die benoetigte Datei compiliert
und hinzugelinkt werden. Bei Verwendung der hier benutzten Makefile Vorlagen
wird dies erreicht durch Angaben von:


Die zu den verschiedenen my_printf gehoerende Header-Datei ist fuer alle
Varianten unabhaengig der Funktionalitaet gleich:

  #include "my_printf.h"

my_printf benoetigt zur Ausgabe irgendwo in den zu einem Programmprojekt
gehoerenden Dateien eine Funktion namens:

  void my_putchar(char ch);

my_printf bedient sich dieser Funktion zur Zeichenausgabe. Soll bspw.
ein Programm die Ausgaben auf der seriellen Schnittstelle vornehmen existiert
wahrscheinliche eine Funktion aehnlich

Um nun diese Ausgabefunktion nutzen zu koennen koennte ein einfaches Programm
folgendermassen aussehen:

  #include <avr/io.h>
 
  #include "uart_all.h"
  #include "my_printf.h"
 
  #define printf    my_printf
 
  /* --------------------------------------------------------
     my_putchar
  
     wird von my-printf aufgerufen und hier muss
     eine Zeichenausgabefunktion angegeben sein, auf das
     printf dann schreibt !
     -------------------------------------------------------- */
  void my_putchar(char ch)
  {
    uart_putchar(ch);
  }
 
  int main(void)
  {
    uart_init();
    printf("\n\r Hallo Welt\n\r");
    while(1);
  }

Im gezeigten Beispiel wird die Zeile

dazu genutzt, um im gesamten Programm printf anstelle von my_printf schreiben
zu koennen und somit bereits bestehende Programme mit my_printf (anstelle
von printf aus stdio.h) nutzen zu koennen. Mit dieser Angabe jedoch ist
dann eine eventuell vorhandene originale printf Funktion nicht mehr
verfuegbar.

printf - Derivate
Inhaltsverzeichnis


---------------------------------------------------------
Umwandlungszeichen my_printf
---------------------------------------------------------


  Zeichen  |    Datentyp und Darstellung
  --------------------------------------
           |
    %d     |    Integer als dezimale Zahl ausgeben
           |           int ist 16-Bit Wert auf 8-Bit Systemen
           |           int ist 32-Bit Wert auf 32-Bit Systemen
    %l     |    nur bei printf32.c : 32-Bit Integerwert ausgeben
           |           (verfuegbar fuer AVR, STM8 und MCS-51=
    %k     |    (Pseudo-Kommazahl) Integerwert mit eingesetztem
           |    Kommapunkt ausgeben, auf 32-Bit Systemen oder bei
           |    my_printf32 als 32-Bit Wert, ansonsten als 16-Bit Wert.
           |    Mit dem Wert in globaler Variable printfkomma wird
           |    angegeben, an welcher Position ein Dezimalpunkt ausgegeben
           |    wird.
    %c     |    Ausgabe eines char als (Ascii)-Zeichen
    %f     |    nur bei my_printf_float
           |           Ausgabe einen (float) Gleitkommawertes. Ein Punkt
           |           zur Angabe der Nachkommastellen wird
           |           interpretiert
    %s     |    Zeichenkette (String) ausgeben
    %x     |    Integer als hexadezimale Zahl ausgeben
    %%     |    Ausgabe des Prozentzeichens

Beispiel:
  #define printf    my_printf
 
  int a,a2,b,c;
 
  printf("\n\r ASCII-Zeichen '%c' = dezimal %d = hexadezimal 0x%x\n\r", 'M', 'M', 'M');
 
  a= 42; b= 13;
 
  // Variable a um eine Zehnerstelle nach links,
  // um spaeter eine Nachkommastelle anzeigen zu koennen
  a2= a*100;
  c= a2 / b;
 
  printfkomma= 2;
  printf(" %d / %d = %k", a, b, c);

Ausgabe: