Re: format number on gtklabel



>It's locale dependent, so make sure LC_NUMERIC is set to a locale that
>formats in that style (e.g. da_DK, and presumably your own).  In order
>to use the locale stuff in C or C++, you need to call setlocale to set
>the locale stuff up.

that much is true.

>In C:
>
>  #include <locale.h>
>  setlocale(LC_ALL, "");

as noted by someone else, this is a very very unfriendly thing to do
unless it is restricted to places where you are doing "serialization"
(ie. saving state to disk). users expect programs to obey their i18n
settings, not override them. it is hard to do the right thing in C
without being very careful.

>In C++:
>
>  #include <locale>
>  std::locale::global(std::locale(""));

C++'s iostreams pays no attention to the ordinary locale
settings. with iostreams, locale is a property of the stream, and has
to be set explicitly using a stream operator. i find this pretty
horrendous, so i never use it. and anyway, iostreams is pretty nasty
for specifically formatted output anyway.

because the problems of saving state to disk in a portable
(cross-locale) way, i wrote a small C++ object to take care of things:


/*
    Copyright (C) 2004 Paul Davis 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

struct LocaleGuard {
    LocaleGuard (const char*);
    ~LocaleGuard ();
    const char* old;
};

LocaleGuard::LocaleGuard (const char* str)
{
	old = strdup (setlocale (LC_NUMERIC, 0));
	if (strcmp (old, str)) {
		setlocale (LC_NUMERIC, str);
	} 
}

LocaleGuard::~LocaleGuard ()
{
	setlocale (LC_NUMERIC, old);
	free ((char*)old);
}

example usage:

void
some_function (... some args ...)
{
	LocaleGuard ("POSIX");

	... you are now in POSIX mode for LC_NUMERIC so any file
	    I/O done using printf-based functions will be 
	    portable across locale domains ...

        char buf[128];
	snprintf (buf, sizeof (buf), "value=%f", one_of_the_args);
	/* now write it to disk ...*/


	... LocaleGuard destructor allows the compiler to make sure
	    that we switch back to the LC_NUMERIC setting no
	    matter how we leave the scope of this function ...

}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]