snprintf
functie.
© Harry Broeders.
Deze pagina is bestemd voor studenten van de Haagse Hogeschool - Academie voor Technology, Innovation & Society Delft.
De functie snprintf
kan gebruikt om data geformateerd naar een
C-string te sturen. Het prototype van deze functie is gegeven in
<stdio.h>
:
int
snprintf (char*
s, size_t n, constchar*
fmt, ...);
Deze functie formateert de na fmt
meegegeven parameters op de
manier zoals in de format string fmt
is opgegeven. Het resultaat
wordt weggeschreven op de plaats die door de
char*
s
wordt aangewezen en er worden maximaal n
karakters
weggeschreven (het laatste weggeschreven karakter is altijd het
'\0'
karakter). De functie geeft het aantal geformateerde karakters
(ook inclusief '\0'
) terug. Als de retrunwaarde groter is dan
n
dan was er dus niet voldoende ruimte.
Deze functie kan dus gebruikt worden om data te formateren en naar een
char
array te sturen op dezelfde manier als de bekende
printf
functie gebruikt kan worden om data te formateren en
naar het beeldscherm te sturen. Bij het programmeren van microcontrollers
is er meestal geen "normaal" beeldscherm (stdout
) aanwezig.
De functie snprintf
kan dan gebruikt worden om data te formateren
in een C-string. Deze string kan dan vervolgens op een eenvoudig LCD display
weergegeven worden of via een seriële verbinding naar een PC of andere
mirocontroller verstuurd worden.
De avr-libc library bevat diverse varianten van de printf
functie
waaronder snprintf
. Onderaan pagina 188 en op pagina 189 en
190 in
avr-libc-user-manual.pdf
staat beschreven hoe de
format string fmt
gebruikt kan worden. Microsoft Visual
Studio 2010 bevat de functie snprintf niet (en voldoet dus niet aan de C99
standaard!), zie
http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010.
In Microsoft Visual Studio 2010 kun je wel gebruik maken van de functie sprintf
maar bij deze functie ligt altijd het gevaar van een buffer overrun op de
loer. Zie: De gevaren van buffer
overrun!
int
.
Hieronder is een AVR gcc programma gegeven dat een int
formateert
in een C-string als decimaal getal en rechts uitlijnt op een veldbreedte
van 6 karakters met de format string "%6d"
. De C-string wordt
vervolgens op een LCD display weergegeven met behulp van de
LCD functies.
#include <stdio.h>
#include "lcd.h"
int main(void) {
int i = 0;
char buffer[11];
lcd_init();
lcd_cursor(false, false);
while (1) {
lcd_home();
snprintf(buffer, sizeof buffer, "i = %6d", i++);
lcd_puts(buffer);
}
return 0;
}
De operator
sizeof
bepaalt de grootte van de variabele
buffer
in bytes. Dit is dus het
maximale aantal karakters wat
snprintf
mag wegschrijven omdat
anders voorbij het einde van de variabele
buffer
wordt geschreven.
uint16_t
.
In programma's voor microcontrollers wordt vaak gebruik gemaakt van de integer
types die gedefinieerd zijn in C99 (in de header file stdint.h). Zie:
http://en.wikibooks.org/wiki/C_Programming/C_Reference/stdint.h
en /of pagina 164 e.v. in
avr-libc-user-manual.pdf
. Door gebruik te maken van
deze types kunnen we exact bepalen hoe groot (hoeveel bits) een integer variabele
is. Als we de C99 integer types willen printen dan moeten we gebruik maken
van de formats die in de C99 include file inttypes.h zijn gedefinieerd. Zie:
http://en.wikibooks.org/wiki/C_Programming/C_Reference/inttypes.h
en /of pagina 137 e.v. in
avr-libc-user-manual.pdf
. Voor een variabele van het
type uint16_t
is het bijbehorende print format gedefinieerd
in de macro PRIu16
. Deze macro definieert een
C-string
literal en kan via
C-string
literal concatination
gecombineerd worden met de rest van de format string.
Hieronder is een AVR gcc programma gegeven dat een uint16_t
formateert in een C-string als decimaal getal en rechts uitlijnt op een
veldbreedte van 5 karakters met de format string "%5"PRIu16
.
De C-string wordt vervolgens op een LCD display weergegeven met behulp van
de LCD functies.
#include <stdio.h>
#include <inttypes.h>
#include "lcd.h"
int main(void) {
int i = 0;
char buffer[11];
lcd_init();
lcd_cursor(false, false);
while (1) {
lcd_home();
snprintf(buffer, sizeof buffer, "i = %5"PRIu16, i++);
lcd_puts(buffer);
}
return 0;
}
double
.
Hieronder is een AVR gcc programma gegeven dat een double
formateert
in een C-string als floatingpoint getal en rechts uitlijnt op een
veldbreedte van 8 karakters met 6 cijfers achter de decimalpoint met de format
string "%8.6lf"
. De C-string wordt vervolgens op een LCD display
weergegeven met behulp van de LCD functies.
#include <stdio.h>
#include <math.h>
#include "lcd.h"
int main(void) {
char buffer[14];
lcd_init();
lcd_cursor(false, false);
snprintf(buffer, sizeof buffer, "pi = %8.6lf", M_PI);
lcd_puts(buffer);
while (1);
return 0;
}
De constante M_PI
is gedefinieerd in
<math.h>
. Zie pagina 155 in
avr-libc-user-manual.pdf
.
De uitvoer van dit programma is:
pi = ?
Om doubles (en floats) te kunnen gebruiken moet je het volgende doen:
libprintf_flt.a
en libm.a
toe. Let op: de
volgorde is belangrijk!-Wl,-u,vfprintf
toe.De uitvoer van het programma is nu wel correct:
pi = 3.141593
De LCD wordt aangestuurd met een een Hitachi HD44780 controller. Op pagina 17 van dit document kun je de karakterpatronen vinden. Je ziet dat de griekse letter pi kan worden weergegeven met karaktercode 0xF7. In het volgende programma maken we hier gebruik van:
#include <stdio.h>
#include <math.h>
#include "lcd.h"
int main(void) {
char buffer[13];
lcd_init();
lcd_cursor(false, false);
snprintf(buffer, sizeof buffer, "%c = %8.6lf", 0xF7, M_PI);
lcd_puts(buffer);
while (1);
return 0;
}
De uitvoer van dit programma is:
Helaas geeft de LCD simulatie van de AVE AVR Plugins het teken pi niet weer :-(