web-dev-qa-db-fra.com

Utilisation de floats avec sprintf () dans C intégré

Les gars, je veux savoir si les variables float peuvent être utilisées dans la fonction sprintf().

Comme si on écrivait:

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

adc_read est une variable entière, il stockera la chaîne 

"adc_read = 1023 \n" 

dans str (en supposant que adc_read = 1023)

Comment puis-je utiliser une variable float à la place d'un entier?

24
aditya

Puisque vous êtes sur une plate-forme intégrée, il est fort possible que vous n’ayez pas toute la gamme des fonctionnalités des fonctions de style printf()-.

En supposant que vous ayez des flottants (ce qui n’est pas forcément une donnée pour les éléments incorporés), vous pouvez l’imiter avec quelque chose comme:

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);

Vous devrez limiter le nombre de caractères après la décimale en fonction de la taille de vos entiers. Par exemple, avec un entier signé de 16 bits, vous êtes limité à quatre chiffres (9 999 est la plus grande puissance de dix moins un pouvant être représentée).

Cependant, il existe des moyens de gérer cela en traitant plus avant la partie décimale, en la décalant de quatre décimales à chaque fois (et en utilisant/en soustrayant la partie entière) jusqu'à obtenir la précision souhaitée.


Mettre à jour:

Un dernier point, vous avez mentionné que vous utilisiez avr-gcc dans une réponse à l’une des autres réponses. J'ai trouvé la page Web suivante qui semble décrire ce que vous devez faire pour utiliser %f dans vos déclarations printf()ici .

Comme je le pensais au départ, vous devez faire des démarches supplémentaires pour obtenir un soutien en virgule flottante. Cela est dû au fait que les éléments incorporés ont rarement besoin de virgule flottante (du moins aucun de ceux que j'ai jamais réalisés). Cela implique la définition de paramètres supplémentaires dans votre makefile et la liaison avec des bibliothèques supplémentaires.

Toutefois, cela risque d’augmenter considérablement la taille de votre code en raison de la nécessité de gérer les formats de sortie généraux. Si vous pouvez limiter vos sorties en virgule flottante à 4 décimales ou moins, je suggérerais de transformer mon code en une fonction et de l'utiliser simplement: cela risque de prendre beaucoup moins de place.

Au cas où ce lien disparaîtrait, vous devez vous assurer que votre commande gcc a "-Wl,-u,vfprintf -lprintf_flt -lm ". Cela se traduit par:

  • force vfprintf à être initialement indéfini (de sorte que l'éditeur de liens doit le résoudre).
  • spécifiez la bibliothèque printf() à virgule flottante pour la recherche.
  • spécifiez la bibliothèque mathématique pour la recherche.
44
paxdiablo

Est-ce que quelque chose comme ça n'est pas vraiment plus facile:

#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);
3
crharper

Oui, vous pouvez. Cependant, cela dépend de la bibliothèque C avec laquelle vous vous connectez et vous devez être conscient des conséquences.

Étant donné que vous programmez des applications intégrées, sachez que la prise en charge en virgule flottante est émulée pour de nombreuses architectures intégrées. Compiler dans cette prise en charge en virgule flottante augmentera considérablement la taille de votre exécutable.

2
sybreon

Ne vous attendez pas à ce que sprintf (ou toute autre fonction avec varargs) lance automatiquement quoi que ce soit. Le compilateur n'essaye pas de lire la chaîne de format et de faire le casting pour vous; au moment de l'exécution, sprintf ne dispose d'aucune méta-information disponible pour déterminer le contenu de la pile; il suffit de faire apparaître des octets et de les interpréter comme étant donnés par la chaîne de format. sprintf (myvar, "% 0", 0); immédiatement segfaults.

Donc: Les chaînes de format et les autres arguments doivent correspondre!

1

Oui et non. Malgré ce que d'autres réponses ont dit, le compilateur C est requis pour effectuer les conversions pour sprintf() et toutes les autres fonctions variables, comme suit:

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

(et variantes signées/non signées des types intégraux ci-dessus)

Il le fait précisément parce que sprintf() (et les autres fonctions print()- family) serait inutilisable sans cela. (Bien sûr, ils sont plutôt inutilisables tels quels .)

Mais vous ne pouvez pas supposer d’autres conversions et votre code aura un comportement indéfini - lisez: crash! - si tu le fais.

0
dcw

Ne fais pas ça les entiers en C/C++ sont toujours arrondis, il n’est donc pas nécessaire d’utiliser la fonction floor.

char str[100]; 
int d1 = value;

Mieux vaut utiliser 

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

Il n’est alors difficile d’éviter d’arrondir la partie entière (68.9999999999999999 devient 69.00 ..) ..__ 68.09999847 au lieu de 68.1 - tout format en virgule flottante a une précision limitée.

0
setltd

% g peut faire ceci:

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

utilisez le modificateur %f:

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

Par exemple:

#include <stdio.h>

int main (void) 
{
    float x = 2.5;
    char y[200];

    sprintf(y, "x = %f\n", x);
    printf(y);
    return 0;
}

Donne ceci:

x = 2.500000

0
Nathan Fellman

Oui bien sûr, il n'y a rien de spécial avec les flotteurs. Vous pouvez utiliser les chaînes de format utilisées dans printf () pour les floats et autres types de données.

EDIT J'ai essayé cet exemple de code:

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

La sortie était: Test = 0.61

0
Naveen

Consultez la documentation de sprintf pour votre plate-forme. C'est généralement% f ou% e. Le seul endroit où vous trouverez une réponse définitive est la documentation ... si ce n’est pas documenté, vous ne pouvez que contacter le fournisseur.

De quelle plateforme s'agit-il? Quelqu'un pourrait déjà savoir où sont les documents ... :)

0
jheriko