Page 1 of 1

Problème utilisation va_list et conversion double/float

Unread postPosted: 24 Sep 2012, 16:02
by Lepzulnag
Bonjour ! :)

J'utilise dans un de mes programmes la structure va_list qui permet d'envoyer un nombre variable d'éléments à une fonction, comme on le fait avec printf. J'attends trois types de valeurs : des int, des char * (des strings), et des float.

Cependant mon compilateur se plaignait qu'il ne pouvait pas prendre en compte des int, mais seulement des floats. Voici donc ce que j'ai fait :

Code: Select all
      char c;

      while ((c=elements[x++])) {
         if (c == '-') {
            if (!(c=elements[x++]))
               break;
            if         (c == 'i') Table_AddInt(va_arg(v1, int));
            else if   (c == 'f')   Table_AddFloat((float) va_arg(v1, double));
            else if   (c == 's')   Table_AddString(va_arg(v1, char *));
         }
      }


Par exemple, si elements = "-i -i -s -f -i", alors les arguments sont 2 entiers, 1 chaîne de caractères, 1 flottant et 1 entier.

Cela marche parfaitement avec les entiers et les chaînes de caractères, mais avec les flottants cela bug complètement, bien que le compilo soit content. Il enregistre dans le flottant 0.0000000 et les valeurs suivantes sont erronées.

Ce qui m'étonne le plus, c'est que les valeurs qui suivent sont fausses. :~o

Bref, j'ai retourné ce problème nombre de fois et je n'en trouve pas la solution. Je viens mendier un peu de savoir sur les va_list et l'utilisation des double. Peut-être fais-je quelque chose de mal ?

Merci d'avance.

Re: Problème utilisation va_list et conversion double/float

Unread postPosted: 24 Sep 2012, 17:38
by Lionel Debroux
Il faudrait que tu nous postes le code complet (et le Makefile), puis vérifier le code assembleur généré - mais je crains que tu soies en train de te heurter à une des limitations de la programmation en code natif sur Nspire.

Re: Problème utilisation va_list et conversion double/float

Unread postPosted: 24 Sep 2012, 18:21
by critor
Les va_list du code source Doom, j'ai du les supprimer/contourner pour nDoom.

J'ai eu beau tourner dans tous les sens, j'ai eu absolument tout et n'importe quoi, sauf ce que j'attendais.

Re: Problème utilisation va_list et conversion double/float

Unread postPosted: 24 Sep 2012, 20:08
by Lepzulnag
Bon alors voici le code concerné (on enregistre les données fournies par l'utilisateur dans 1--,2--, 3-- et 4--. A 5-- on affiche ce qui a été enregistré) :

1-- on utilise la va_list :

Code: Select all
      char c;
      va_list v1;
      va_start(v1, elements);
      
      while ((c=elements[x++])) {
         if (c == '-') {
            if (!(c=elements[x++]))
               break;
            if         (c == 'i') Table_AddInt(w, va_arg(v1, int));
            else if   (c == 'f') Table_AddFloat(w, (float) va_arg(v1, double));
            else if   (c == 's') Table_AddString(w, va_arg(v1, char *));
         }
      }
      
      va_end(v1);


2-- la fonction Table_AddFloat (les fonctions Table_AddInt et Table_AddStr sont similaires) :

Code: Select all
int Table_AddFloat(Widget *table, float value)
{
   return Table_AddExFloat(table, value, -1, NULL, 0);
}


3-- la fonction Table_AddExFloat (les fonctions Table_AddExInt et Table_AddExStr sont similaires) :

Code: Select all
int Table_AddExFloat(Widget *table, float value, int alignment, nSDL_Font *font, Uint32 background)
{
   char val[4];
   memcpy(val, &value, 4);
   return Table_AddElement(table, ELEMENT_FLOAT, val, alignment, font, background);
}


4-- En gros, table_AddElement fait ceci :

Code: Select all
   memcpy(newElement->value, value, 4);

où value est val fournie parTable_AddExFloat.

5-- Ecriture à l'écran des données :

Code: Select all
      void *val = el->value;
      char str[100];
      int el_w;
      int str_x;
      int alignment;

      if (el->type == ELEMENT_INT)
         sprintf(str, "%100i", *((int *) val));
      else if (el->type == ELEMENT_FLOAT)
         sprintf(str, "%100f", *((float *) val));
      else if (el->type == ELEMENT_STRING)
         sprintf(str, "%100s", *((char **) val));

...

      nSDL_DrawString(scr, el->font? el->font : theme->font, str_x, cell.y + 2, str);


Je n'ai pas tout explicité dans cette dernière fonction, seulement mis ce qui importait.


-- Et enfin le makefile :

Code: Select all
SOURCES = test.c Label.c common.c BasicLayout.c Check.c theme.c keys.c Panel.c scrollbar.c Table.c Pixmap.c
TARGET = test.tns
OBJECTS = $(SOURCES:.c=.o)

CC = nspire-gcc
LD = nspire-ld
OBJCOPY = arm-none-eabi-objcopy
CFLAGS = -Wall -Wextra -Ofast
LDFLAGS =
LIBS = -lSDL

all: $(TARGET)

$(TARGET): $(OBJECTS)
   $(LD) $(LDFLAGS) $^ $(LIBS) -o $(@:.tns=.elf)
   $(OBJCOPY) -O binary $(@:.tns=.elf) $(TARGET)

.c.o:
   $(CC) $(CFLAGS) -c $< -o $@

clean:
   rm -f $(OBJECTS) $(TARGET:.tns=.elf) $(TARGET)

Re: Problème utilisation va_list et conversion double/float

Unread postPosted: 26 Sep 2012, 17:51
by Lepzulnag
Bon de toute façon, comme le montre le témoignage de Critor (qui a eu les même problèmes que moi avant moi :D ), il y a des bugs avec les va_list, donc ça ne cherche à rien de chercher plus loin. Je vais juste trouver une autre technique pour afficher des flottants.

Merci à vous.

Re: Problème utilisation va_list et conversion double/float

Unread postPosted: 26 Sep 2012, 17:54
by critor
Tu peux faire 5 fonctions... une avec 1 argument, une avec 2 arguments, etc...

Ou sinon, si tu aimes les tableaux et pointeurs, tu passes 2 arguments à ta fonction: un float* et le nombre de float.