See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: sprintf avec un pointeur void  (Read 2767 times)

0 Members and 1 Guest are viewing this topic.

Offline Bibi Uncle

  • Legend
  • ******
  • Posts: 2264
  • Country: Canada ca
  • Karma: 17
22 June 2011, 19:23:46
Bonjour à tous !

J'essais de créer une classes me permettant de sauvegarder et de charger une donnée quelconque d'un vaisseau. Puisque ces données peuvent des entiers, des nombres à virgules, des nombres à double précision et etc, j'ai pensé à utiliser un pointeur void pour envoyer mes données.

Pour écrire dans un scénario, j'utilise oapiWriteScenario_string() afin d'écrire une chaîne de caractères que je crée plus tôt avec un sprintf(). Mais je croyais sprintf() assez intelligent pour pouvoir convertir les données selon le format qu'on lui donne, mais on dirait que non.

Voilà comment ma classe fonctionne. Lorsqu'on veut sauvegarder une valeur, on l'envoie à ma classe LoaderSaver via la fonction AddData(char *name, char *datastring, void *data). name contient le nom à utiliser (à écrire dans le scénario), datastring contient le format (ex : "%i" pour un entier) et data contient un pointeur vers la donnée qu'on veut sauvegarder. Tous ces renseignements sont sauvegardés dans un tableau dynamique géré par ma classe.

Quand j'arrive pour sauvegarder le scénario, voilà ce que je fais :

Code: [Select]
// String buffer
char cbuf[256];

// Default saving features
vessel->VESSEL3::clbkSaveState(scn);

// Write the first variable to the scenario
// TODO : loop to save all variables
sprintf(cbuf, datas[0].datastring, &datas[0].data);
oapiWriteScenario_string (scn, datas[0].name, cbuf);

datas est mon tableau dynamique contenant toutes les infos. Pour l'instant, je ne sauvegarde que la première variable. Avec ce code, ça me renvoie un nombre quelconque. Mais si je cast mon pointeur void, j'obtiens le bon nombre. Voici le code qui marche :

Code: [Select]
// String buffer
char cbuf[256];

// Default saving features
vessel->VESSEL3::clbkSaveState(scn);

// Write the first variable to the scenario
// TODO : loop to save all variables
sprintf(cbuf, datas[0].datastring, *((int*)datas[0].data));
oapiWriteScenario_string (scn, datas[0].name, cbuf);

Mais voilà, je ne veux pas caster à chaque fois, le but étant que le tout soit "universel" (toutes forme de données en nombres).

Vous avez une idée à part le casting ?


Émile

Pluton, Saturne et Jupiter
Entendez-vous monter vers vous le chant de la Terre?

- Luc Plamondon

Offline Apofis

  • Sr. Member
  • ****
  • Posts: 349
  • Karma: 0
Reply #1 - 23 June 2011, 08:47:28
hello

Ton idée des pointeur est plutôt bonne. En général quand tu veux faire du générique, les pointeurs sont ton meilleur ami. La tu fais un pointeur typé void se qui équivaut a dire un pointeur vers un type quelconque. Pour récupérer la valeur tu es obligé de faire une conversion de type sur ton pointeur pas le choix sinon le compilo ne saura pas comment récupérer la valeur et il vas te retourner tout et n'importe quoi. Et le pire il vas même pas broncher à la compilation. Donc en résumé tu as pas le choix...

Proposition 1
Et si tu fais un switch sur datastring et pour chaque type ben tu cast dans le type correspondant.

Proposition 2
S'est un exemple parfait pour faire de la surcharge de fonction. Et ainsi créer une fonction d'écriture pour chaque type de de donnée que tu veux traiter tout en gardant la même syntaxe d'appel.

AddData(char *name,  int data)
AddData(char *name,  double data)
...

Voila choisi tes armes ;)

Perso je penche plus pour la surcharge

PS: j'ai enlevé datastring du profile des fonctions car vu que tu connais le type plus besoin de le passer.



Message modifié ( 23-06-2011 08:49 )

"Oups c quoi se bruit" Fred Haise, apollo 13 :P

Offline Bibi Uncle

  • Legend
  • ******
  • Posts: 2264
  • Country: Canada ca
  • Karma: 17
Reply #2 - 23 June 2011, 15:01:21
J'ai ajouté une énumération tINT, tFLOAT et tBOOL que j'ajoute comme dernier paramètre et j'ai enlevé le datastring puisque avec l'énumération, je sais quelle est le type de la donnée.

Pour la surchage, ça ne m'aurait pas avantagé car AddData ne fait qu'écrire les données dans le tableau dynamique. Et ce tableau a une structure contenant le pointeur void.

Merci pour ton aide Apofis !

J'ai maintenant aussi le chargement des données qui fonctionnent très bien. Pas besoin de caster cette fois-ci. sscanf a besoin d'un pointeur vers la donnée et j'ai un pointeur (void) vers ma donné. Donc tout se sauvegarde comme sur des roulettes !


Émile

Pluton, Saturne et Jupiter
Entendez-vous monter vers vous le chant de la Terre?

- Luc Plamondon

Offline Apofis

  • Sr. Member
  • ****
  • Posts: 349
  • Karma: 0
Reply #3 - 24 June 2011, 13:50:23
de rien j'ai juste lancé quelques idées et précisions s'est tout ^^

content que tu t'en sois sortis ;)


"Oups c quoi se bruit" Fred Haise, apollo 13 :P

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #4 - 24 June 2011, 13:54:57
Quote
Bibi Uncle a écrit:
Bonjour à tous !
J'essais de créer une classes me permettant de sauvegarder et de charger une donnée quelconque d'un vaisseau.

Je ne sais pas si tu as vu que j'ai fait une classe qui fait exactement ça ?: (3eme post, sources+installation)
http://orbiter.dansteph.com/forum/index.php?topic=6381.msg96441#msg96441

A++

Dan


Offline Bibi Uncle

  • Legend
  • ******
  • Posts: 2264
  • Country: Canada ca
  • Karma: 17
Reply #5 - 25 June 2011, 22:56:16
Ah ouais, j'avais pas vu. Je me souviens d'avoir lu le tutoriel sur la sauvegarde mais je ne me souvenais pas qu'il y avais une classe spécialisée.

Pas grave, c'est pour Project Mercury. Mais j'aime bien ton idée de surchage de fonction, je n'y avait pas pensé. Je vais tout de suite améliorer mon code, merci !


Émile

Pluton, Saturne et Jupiter
Entendez-vous monter vers vous le chant de la Terre?

- Luc Plamondon

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15407
  • Karma: 256
  • Hein, quoi !?
    • FsPassengers
Reply #6 - 27 June 2011, 03:37:10
Quote
Bibi Uncle a écrit:
Je vais tout de suite améliorer mon code, merci !

Serviteur :wor:

Dan

« Last Edit: 27 June 2011, 04:55:24 by DanSteph »

Offline Bibi Uncle

  • Legend
  • ******
  • Posts: 2264
  • Country: Canada ca
  • Karma: 17
Reply #7 - 27 June 2011, 04:55:24
Code fraîchement écrit. Maintenant, un simple call du style AddData(&bBoosterJettison); suffit pour sauvegarder un charger une donnée. Et j'écrit les données dans un espace extrèmement restreint (merci à Dan, j'ai pris cette idée de ton tuto). Voilà un extrait du scénario créé :

Code: [Select]
MA-6:Atlas
  STATUS Landed Earth
  POS -80.6758964 28.5227640
  HEADING 72.51
  AFCMODE 7
  NAVFREQ 0 0
  MERCURY :1:1:1
END
Il n'y a que 3 booléens de sauvegardés, mais j'ai testé avec des nombres à virgules et ça fonctionne à merveille.


« Last Edit: 27 June 2011, 04:55:24 by Bibi Uncle »
Émile

Pluton, Saturne et Jupiter
Entendez-vous monter vers vous le chant de la Terre?

- Luc Plamondon