Влияет ли std :: locale :: global make на функцию printf ()?

Я использую настройки русского языка на моем ПК.

Если бы я установил:

class numpunct_withpoint: public numpunct<char>
{
protected:
/// Override the function that gives the decimal separator.
char do_decimal_point() const
{
return '.';
}
};
...
locale loc(std::locale::classic(), new numpunct_withpoint);
std::locale::global(loc);

и тогда

printf("%f", 3.14);

Выход:

3,14

Десятичный разделитель — «,» не так, как в функции do_decimal_point!
Как я могу изменить настройки языка C для десятичного разделителя с языком C ++?


Спасибо за ответ!
Но влияет ли функция setlocale на C на объект Cout c ++?

setlocale(LC_NUMERIC, "C");

Повлияет ли это на печать десятичного значения через cout?

6

Решение

Когда вы устанавливаете глобальный языковой стандарт C ++, языковой стандарт C также изменяется. Если вы измените языковой стандарт C, глобальный языковой стандарт C ++ не является модифицирована.

Ниже демонстрируется настройка глобальной локали C ++.

#include <cstdio>
#include <clocale>
#include <fstream>

int main() {
const char * locale_name = "French_France.1252"; // or "fr_Fr.UTF-8" on Unix
double value = 1.2;

std::locale::global(std::locale(locale_name));

std::ofstream("out.txt") << "C++ " << value << '\n';

if (FILE *f = std::fopen("out.txt", "a")) {
std::fprintf(f, "C %1.1e\n", value);
std::fclose(f);
}
}

Для вывода как на C, так и на C ++ следует использовать десятичную запятую.

C ++ 1,2
C 1,2e + 000

Если вы замените настройку языка C ++ на настройку языка C, std::setlocale(LC_ALL, locale_name);, тогда выходные данные должны измениться так, чтобы только выходные данные C использовали десятичную запятую, в то время как выходные данные C ++ все еще использовали десятичный символ периода по умолчанию.

C ++ 1.2
C 1,2e + 000

Однако тот факт, что установка языкового стандарта C ++ влияет на языковой стандарт C, не делает расширяемые языковые стандарты C такими же, какими являются языковые стандарты C ++. Пользовательские фасеты C ++ никогда не будут использоваться функциями, основанными на локали C. Вместо этого вы должны полагаться на свою систему, поддерживающую некоторую именованную локаль, обладающую необходимой вам функциональностью.

В частности, std::locale::global() определяется для установки языкового стандарта C с использованием имени выбранного языкового стандарта C ++, если у него есть имя. Поведение определяется реализацией, если у локали C ++ нет имени. Кроме того, C ++ указывает, что объединение двух именованных локалей создает именованную локаль. Некоторые реализации создают полезные комбинированные имена, которые позволяют смешивать категории языковых стандартов C, просто устанавливая языковой стандарт C ++:

std::locale::global(std::locale(std::locale("ru_RU"), "C", std::locale::numeric));

С libstdc ++ это производит локаль с именем:

LC_CTYPE = ru_RU; LC_NUMERIC = С; LC_TIME = ru_RU; LC_COLLATE = ru_RU; LC_MONETARY = ru_RU; LC_MESSAGES = ru_RU; LC_PAPER = ru_RU; lc_name = ru_RU; LC_ADDRESS = ru_RU; LC_TELEPHONE = ru_RU; LC_MEASUREMENT = ru_RU; LC_IDENTIFICATION = ru_RU
LC_CTYPE = ru_RU; LC_NUMERIC = С; LC_TIME = ru_RU; LC_COLLATE = ru_RU; LC_MONETARY = ru_RU; LC_MESSAGES = ru_RU; LC_PAPER = ru_RU; lc_name = ru_RU; LC_ADDRESS = ru_RU; LC_TELEPHONE = ru_RU; LC_MEASUREMENT = ru_RU; LC_IDENTIFICATION = ru_RU

Так что языковой стандарт C устанавливается в той же смеси между языковыми стандартами «ru_RU» и «C», что и языковой стандарт C ++.

К сожалению, другие реализации выбирают менее полезное, хотя и технически совместимое поведение. В Visual Studio

std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));

производит локаль с именем «C». Таким образом, в то время как языковой стандарт C ++ представляет собой подходящую смесь категорий русского языка и языка C, языковой стандарт C просто устанавливается на «C». Таким образом, на этих платформах для смешивания категорий локали C вы должны напрямую установить локаль C:

// set the C++ locale first
std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));

// set the C locale second, because it will not overwrite the changes you made to the C++ locale
std::setlocale(LC_ALL, "Russian_Russia.1251");
std::setlocale(LC_NUMERIC, "C");
5

Другие решения

Библиотека C не использует те же настройки локали, что и C ++. Для переопределения локали, используемой printfиспользовать Setlocale:

setlocale(LC_NUMERIC, "POSIX");

или похожие.

0

По вопросам рекламы [email protected]