sprintf pro mplab comando c embedded floating-point printf

mplab - sprintf pro c



Usando flotadores con sprintf() en C incrustado (11)

Busque en la documentación de sprintf para su plataforma. Por lo general es% f o% e. El único lugar donde encontrará una respuesta definitiva es la documentación ... si todo lo que puede documentar no está documentado, entonces póngase en contacto con el proveedor.

¿Qué plataforma es? Alguien podría ya saber dónde están los documentos ... :)

Chicos, quiero saber si las variables float pueden usarse en la función sprintf() .

Como si escribiéramos:

sprintf(str,"adc_read = %d /n",adc_read);

donde adc_read es una variable entera, almacenará la cadena

"adc_read = 1023 /n"

en str (asumiendo que adc_read = 1023 )

¿Cómo puedo usar una variable flotante en lugar de entero?


No es algo así realmente fácil:

#include <stdio.h> #include <stdlib.h> #include <string.h> char str[10]; float adc_read = 678.0123; dtostrf( adc_read, 3, 4, temp ); sprintf(str,"adc_read = %10s /n", temp); printf(temp);


No esperes que sprintf (o cualquier otra función con varargs) lance automáticamente cualquier cosa. El compilador no intenta leer la cadena de formato y hacer la conversión por ti; en tiempo de ejecución, sprintf no tiene metainformación disponible para determinar qué hay en la pila; simplemente marca los bytes y los interpreta según lo indicado por la cadena de formato. sprintf (myvar, "% 0", 0); Inmediatamente segfaults.

Entonces: ¡Las cadenas de formato y los otros argumentos deben coincidir!


No hagas esto los enteros en C / C ++ siempre se redondean hacia abajo, por lo que no es necesario utilizar la función de piso.

char str[100]; int d1 = value;

Mejor usar

int d1 = (int)(floor(value));

Entonces no obtendrá el redondeo de la parte entera (68.999999999999999999 se convierte en 69.00 ..). 68.09999847 en lugar de 68.1 es difícil de evitar: cualquier formato de punto flotante tiene una precisión limitada.


Sí tu puedes. Sin embargo, depende de la biblioteca C con la que se está vinculando y debe ser consciente de las consecuencias.

Como está programando para aplicaciones integradas, tenga en cuenta que el soporte de punto flotante se emula para muchas arquitecturas integradas. La compilación en este soporte de punto flotante terminará aumentando significativamente el tamaño de su ejecutable.


Sí, por supuesto, no hay nada especial con flotadores. Puede usar las cadenas de formato que usa en printf () para flotadores y cualquier otro tipo de datos.

EDITAR He intentado este código de ejemplo:

float x = 0.61; char buf[10]; sprintf(buf, "Test=%.2f", x); printf(buf);

La salida fue: Prueba = 0.61


Si usa% f


Si y no. A pesar de lo que han dicho algunas otras respuestas, se requiere que el compilador de C realice conversiones para sprintf() , y todas las demás funciones variadic, de la siguiente manera:

  • char => int
  • short => int
  • float => double

(y variantes firmadas / sin firmar de los tipos integrales anteriores)

Lo hace precisamente porque sprintf() (y las otras funciones de familia de print() ) serían inutilizables sin él. (Por supuesto, son bastante inutilizables como son ).

Pero no puede asumir otras conversiones, y su código tendrá un comportamiento indefinido - lea: ¡falla! - Si lo haces.


Ya que está en una plataforma integrada, es muy posible que no tenga todas las capacidades de las funciones de estilo printf() .

Suponiendo que tenga flotadores (aún no necesariamente un determinado para cosas incrustadas), puede emularlo con algo como:

char str[100]; float adc_read = 678.0123; char *tmpSign = (adc_read < 0) ? "-" : ""; float tmpVal = (adc_read < 0) ? -adc_read : adc_read; int tmpInt1 = tmpVal; // Get the integer (678). float tmpFrac = tmpVal - tmpInt1; // Get fraction (0.0123). int tmpInt2 = trunc(tmpFrac * 10000); // Turn into integer (123). // Print as parts, note that you need 0-padding for fractional bit. sprintf (str, "adc_read = %s%d.%04d/n", tmpSign, tmpInt1, tmpInt2);

Deberá restringir cuántos caracteres vienen después del decimal en función del tamaño de sus números enteros. Por ejemplo, con un entero con signo de 16 bits, está limitado a cuatro dígitos (9,999 es la mayor potencia de diez menos uno que puede representarse).

Sin embargo, hay maneras de manejar esto mediante el procesamiento adicional de la parte fraccionaria, cambiándola con cuatro dígitos decimales cada vez (y utilizando / restando la parte entera) hasta que tenga la precisión que desea.

Actualizar:

Un punto final que mencionó fue que estaba usando avr-gcc en respuesta a una de las otras respuestas. Encontré la siguiente página web que parece describir lo que debe hacer para usar %f en sus declaraciones de printf() here .

Como sospeché originalmente, necesita hacer un poco de trabajo adicional para obtener soporte de punto flotante. Esto se debe a que las cosas incrustadas rara vez necesitan punto flotante (al menos ninguna de las cosas que he hecho). Implica establecer parámetros adicionales en su makefile y vincularlos con bibliotecas adicionales.

Sin embargo, es probable que aumente bastante el tamaño de su código debido a la necesidad de manejar formatos de salida generales. Si puede restringir sus salidas flotantes a 4 lugares decimales o menos, sugeriría convertir mi código en una función y simplemente usarlo, es probable que ocupe mucho menos espacio.

En caso de que el enlace desaparezca, lo que debe hacer es asegurarse de que su comando gcc tenga "-Wl,-u,vfprintf -lprintf_flt -lm ". Esto se traduce en:

  • forzar que vfprintf esté inicialmente indefinido (para que el enlazador tenga que resolverlo).
  • Especifique la biblioteca printf() punto flotante para la búsqueda.
  • Especifique la biblioteca de matemáticas para la búsqueda.

use el modificador %f :

sprintf (str, "adc_read = %f/n", adc_read);

Por ejemplo:

#include <stdio.h> int main (void) { float x = 2.5; char y[200]; sprintf(y, "x = %f/n", x); printf(y); return 0; }

Rinde esto:

x = 2.500000


% g puede hacer esto:

#include <stdio.h> int main() { float w = 234.567; char x[__SIZEOF_FLOAT__]; sprintf(x, "%g", w); puts(x); }