Swisslinux.org

− The GNU/Linux crossroads in Switzerland −

 

Language

 

The Forum

You are not logged in.

#1 16 Jul 2009 10:16:16

[GO]Skywalker13
Modérateur
From: Choëx (VS)
Registered: 05 Oct 2004
Posts: 896
Website

[C] setlocale() et les threads (Résolu)

Hi,

j'ai un problème un peu particulier avec une bibliothèque. Celle-ci fait du parsing via des fonctions tel que atof(), sscanf(), ... et il y a donc des champs à analyser qui ressemblent à FOO=1.2345.
Le problème apparait quand le programme qui utilise cette bibliothèque change de locale. Le programme est internationalisé. Du coup la bibliothèque prend une nouvelle locale et atof() "dans le cas des français" cherche une virgule à la place d'un point pour la séparation des décimales. Le champ FOO=1.2345 est donc compris bêtement en FOO=1,0 vu que atof() ne comprend plus ce qu'est le point.

Une première solution serait de réécrire des fonctions my_atof(), my_sscanf() qui rechangeraient la locale en "C". Mais la bibliothèque étant multi-threads, il n'y a aucun garantie que le programme principal fasse pas quelque chose qui demanderait la locale précédente en même temps.

Il me faut donc pouvoir changer la locale que pour le thread.


Merci pour toutes aides éventuelles.


Mathieu SCHROETER
log.schroetersa.ch

Offline

 

#2 16 Jul 2009 11:44:33

lochost
Citoyen(ne)
From: Genève
Registered: 12 Jun 2009
Posts: 19

Re: [C] setlocale() et les threads (Résolu)

Idée "juste comme ça en passant" :

créer une fonction qui ne fait rien d'autre que de transformer le point en virgule avant de passer le paramètre à la fonction originale; ça t'éviterai de devoir jongler avec les locale.

Je ne sais pas si c'est une bonne idée, ne connaissant rien de rien à la prog multi-thread, mais c'est ce que je tenterais.

En espérant t'avoir été utile (ce dont je doute un peu, mais bon roll)

L.


-----BEGIN GEEK CODE BLOCK-----
Version: 3.1 GCS/IT$/L d- s: a C++ UL P L++ E-- W+ N o? K? w$ O? M V?
PS PE? Y+ PGP t- 5? X R+ tv b++ DI D- G e+ h-- r++ y+
------END GEEK CODE BLOCK------

Offline

 

#3 16 Jul 2009 15:21:37

[GO]Skywalker13
Modérateur
From: Choëx (VS)
Registered: 05 Oct 2004
Posts: 896
Website

Re: [C] setlocale() et les threads (Résolu)

ça implique de savoir exactement ce que font toutes les locales..  en fonction de toutes les langues du monde et donc de leurs spécificités.. peut être bien qu'il n'y a que le point et la virgule qui poseront un problème.. mais peut être pas, je n'ai pas de garanti..

En changeant la locale uniquement pour le thread j'ai pas besoin de me poser la moindre question sur ce qui est utilisé par le système en amont.


Mathieu SCHROETER
log.schroetersa.ch

Offline

 

#4 16 Jul 2009 16:08:55

lochost
Citoyen(ne)
From: Genève
Registered: 12 Jun 2009
Posts: 19

Re: [C] setlocale() et les threads (Résolu)

Petite googlization rapide avec "séparateur décimal" et je suis tombé là-dessus (ouille!) http://fr.wikipedia.org/wiki/S%C3%A9par … C3%A9cimal

...si j'ai tout bien compris il n'y aurait, en gros, que trois sortes de séparateurs décimaux : le point, la virgule et le "momayyez" : une sorte de slash utilisé dans les pays arabes.

Donc, si tu trouves pas d'autre solution, tu pourrais te référer à la soluce proposée à ceci près : elle devrait convertir tout ce qui n'est pas un chiffre en un point.

Acceptable (même comme pis-aller) ?

L.


-----BEGIN GEEK CODE BLOCK-----
Version: 3.1 GCS/IT$/L d- s: a C++ UL P L++ E-- W+ N o? K? w$ O? M V?
PS PE? Y+ PGP t- 5? X R+ tv b++ DI D- G e+ h-- r++ y+
------END GEEK CODE BLOCK------

Offline

 

#5 16 Jul 2009 17:09:06

[GO]Skywalker13
Modérateur
From: Choëx (VS)
Registered: 05 Oct 2004
Posts: 896
Website

Re: [C] setlocale() et les threads (Résolu)

lochost wrote:

Donc, si tu trouves pas d'autre solution, tu pourrais te référer à la soluce proposée à ceci près : elle devrait convertir tout ce qui n'est pas un chiffre en un point.

L'inverse plutôt, car atof() va s'attendre à trouver parfois un point, parfois une virgule et parfois le symbole arabe. Donc le point doit être converti en fonction de la locale. Merci pour ton aide, je vais qu'en même continuer à chercher pour pouvoir forcer la locale par défaut. Autrement c'est un piège à bug à la moindre utilisation de fonctions de string.


Mathieu SCHROETER
log.schroetersa.ch

Offline

 

#6 16 Jul 2009 19:47:55

[GO]Skywalker13
Modérateur
From: Choëx (VS)
Registered: 05 Oct 2004
Posts: 896
Website

Re: [C] setlocale() et les threads (Résolu)

Bien que j'avais regardé l'header locale, j'étais passé à côté d'une extension du GNU:

Code:

195 /* Switch the current thread's locale to DATASET.
196    If DATASET is null, instead just return the current setting.
197    The special value LC_GLOBAL_LOCALE is the initial setting
198    for all threads and can also be installed any time, meaning
199    the thread uses the global settings controlled by `setlocale'.  */
200 extern __locale_t uselocale (__locale_t __dataset) __THROW;

Ça devrait me permettre de régler le problème proprement.

EDIT:
Ainsi ça fonctionne:

Code:

#define _GNU_SOURCE
#include <locale.h>
#include <stdlib.h>

double
my_atof (const char *nptr)
{
  double res;
  locale_t new_locale, prev_locale;
 
  new_locale = newlocale (LC_NUMERIC_MASK, "C", NULL);
  prev_locale = uselocale (new_locale);
  res = atof (nptr);
  uselocale (prev_locale);
  freelocale (new_locale);
 
  return res;
}

Mathieu SCHROETER
log.schroetersa.ch

Offline

 

#7 17 Jul 2009 16:33:39

[GO]Skywalker13
Modérateur
From: Choëx (VS)
Registered: 05 Oct 2004
Posts: 896
Website

Re: [C] setlocale() et les threads (Résolu)

Une autre variante qui évite atof() et uselocale(), et qui est donc plus simple (la valeur de retour peut "échouer" avec HUGE_VAL contrairement à atof()):

Code:

#define _GNU_SOURCE
#include <locale.h>
#include <stdlib.h>

double
my_atof (const char *nptr)
{
  double res;
  locale_t new_locale;

  new_locale = newlocale (LC_NUMERIC_MASK, "C", NULL);
  res = strtod_l (nptr, NULL, new_locale);
  freelocale (new_locale);

  return res;
}

Mathieu SCHROETER
log.schroetersa.ch

Offline

 

Board footer

Powered by FluxBB