Преобразование строки Unicode в C++ в верхний регистр
Как мы можем преобразовать многоязычную строку или строку Юникода в верхний / нижний регистр в C или C++.
10 ответов
Если ваша система уже в UTF-8, с помощью std::use_facet
, ты можешь написать:
#include <iostream>
#include <locale.h>
int main() {
std::locale::global(std::locale("")); // (*)
std::wcout.imbue(std::locale());
auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());
std::wstring str = L"Zoë Saldaña played in La maldición del padre Cardona.";
f.toupper(&str[0], &str[0] + str.size());
std::wcout << str << std::endl;
return 0;
}
И вы получите ( http://ideone.com/AFHoHC):
ZOË SALDAÑA, ПОЛУЧЕННЫЕ В ЛА МАЛЬДИЧИН ДЕЛЬ ПАДРЕ КАРДОНА.
Если это не сработает, вам придется изменить (*) на std::locale::global(std::locale("en_US.UTF8"));
или локаль UTF-8, которая у вас есть на платформе.
Если вы хотите разумное и зрелое решение, посмотрите на ICU IBM. Вот пример:
#include <iostream>
#include <unicode/unistr.h>
#include <string>
int main(){
icu::UnicodeString us("óóßChloë");
us.toUpper(); //convert to uppercase in-place
std::string s;
us.toUTF8String(s);
std::cout<<"Upper: "<<s<<"\n";
us.toLower(); //convert to lowercase in-place
s.clear();
us.toUTF8String(s);
std::cout<<"Lower: "<<s<<"\n";
return 0;
}
Выход:
Upper: ÓÓSSCHLOË
Lower: óósschloë
Примечание: на более позднем этапе SS
не рассматривается как столица Германии ß
Я нашел 2 решения этой проблемы_
1. setlocale (LC_CTYPE, "en_US.UTF-8"); // локаль будет английская с поддержкой UTF-8
std::wstring str = L"Zoë Saldaña played in La maldición del padre Cardona.ëèñ";
std::wcout << str << std::endl;
for (wstring::iterator it = str.begin(); it != str.end(); ++it)
*it = towupper(*it);
std::wcout << "toUpper_onGCC_LLVM_1 :: "<< str << std::endl;
это работает на компиляторе LLVM GCC 4.2.
2. std:: locale:: global (std:: locale ("en_US.UTF-8")); // локаль будет английская с поддержкой UTF-8
std::wcout.imbue(std::locale());
const std::ctype<wchar_t>& f = std::use_facet< std::ctype<wchar_t> >(std::locale());
std::wstring str = L"Chloëè";//"Zoë Saldaña played in La maldición del padre Cardona.";
f.toupper(&str[0], &str[0] + str.size());
std::wcout << str << std::endl;
Это работает в Apple LLVM 4.2.
В обоих случаях я бегал на Xocde. Но я нахожу способ запустить этот код в Eclipse с помощью компилятора g++.
С большим трудом, если вы собираетесь сделать это правильно.
Обычный вариант использования для этого предназначен для сравнения, но проблема более общая, чем эта.
Здесь есть довольно подробная статья из C++ Report около 2000 года от Matt Austern (PDF)
В Windows рассмотрим CharUpperBuffW
а также CharLowerBuffW
для приложений на разных языках, где локаль неизвестна. Эти функции обрабатывают диакритические знаки, где toupper()
не.
Сначала установите локаль, например:
setlocale(LC_ALL, "German")); /*This won't work as per comments below */
setlocale(LC_ALL, "English"));
setlocale( LC_MONETARY, "French" );
setlocale( LC_ALL, "" ); //default locale
Тогда используйте
std:: use_facet std:: locale следующим образом:-
typedef std::string::value_type char_t;
char_t upcase( char_t ch )
{
return std::use_facet< std::ctype< char_t > >( std::locale() ).toupper( ch );
}
std::string toupper( const std::string &src )
{
std::string result;
std::transform( src.begin(), src.end(), std::back_inserter( result ), upcase );
return result;
}
const std::string src = "Hello World!";
std::cout << toupper( src );
На основании Kyle_the_hacker -----> Ответ с моими статистами.
Ubuntu
В терминале Список всех языков
locale -a
Установить все локали
sudo apt-get install -y locales locales-all
Скомпилируйте main.cpp
$ g++ main.cpp
Запустить скомпилированную программу
$ ./a.out
Полученные результаты
Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë
Windows
В cmd запустите инструменты разработчика VCVARS
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
Скомпилируйте main.cpp
> cl /EHa main.cpp /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /std:c++17 /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MTd
Compilador de optimización de C/C++ de Microsoft (R) versión 19.27.29111 para x64
(C) Microsoft Corporation. Todos los derechos reservados.
main.cpp
Microsoft (R) Incremental Linker Version 14.27.29111.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:main.exe
main.obj
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib
Запускаем main.exe
>main.exe
Полученные результаты
Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
ZOË SALDAÑA PLAYED IN LA MALDICIÓN DEL PADRE CARDONA. ËÈÑ ΑΩ ÓÓCHLOË
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë
zoë saldaña played in la maldición del padre cardona. ëèñ αω óóchloë
Код - main.cpp
Этот код был протестирован только в Windows x64 и Ubuntu Linux x64.
/*
* Filename: c:\Users\x\Cpp\main.cpp
* Path: c:\Users\x\Cpp
* Filename: /home/x/Cpp/main.cpp
* Path: /home/x/Cpp
* Created Date: Saturday, October 17th 2020, 10:43:31 pm
* Author: Joma
*
* No Copyright 2020
*/
#include <iostream>
#include <locale>
#include <string>
#include <algorithm>
#include <set>
#include <cstdlib>
#include <clocale>
#if defined(_WIN32)
#define WINDOWSLIB 1
#define DLLCALL STDCALL
#define DLLIMPORT _declspec(dllimport)
#define DLLEXPORT _declspec(dllexport)
#define DLLPRIVATE
#define NOMINMAX
#include <Windows.h>
#include <objbase.h>
#include <filesystem>
#include <intrin.h>
#include <conio.h>
#elif defined(__ANDROID__) || defined(ANDROID) //Android
#define ANDROIDLIB 1
#define DLLCALL CDECL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#elif defined(__APPLE__) //iOS, Mac OS
#define MACOSLIB 1
#define DLLCALL CDECL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#elif defined(__LINUX__) || defined(__gnu_linux__) || defined(__linux__) || defined(__linux) || defined(linux) //_Ubuntu - Fedora - Centos - RedHat
#define LINUXLIB 1
#include <cpuid.h>
#include <experimental/filesystem>
#include <unistd.h>
#include <termios.h>
#define DLLCALL CDECL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#define CoTaskMemAlloc(p) malloc(p)
#define CoTaskMemFree(p) free(p)
#elif defined(__EMSCRIPTEN__)
#define EMSCRIPTENLIB 1
#include <unistd.h>
#include <termios.h>
#define DLLCALL
#define DLLIMPORT
#define DLLEXPORT __attribute__((visibility("default")))
#define DLLPRIVATE __attribute__((visibility("hidden")))
#endif
typedef std::string String;
typedef std::wstring WString;
#define LINE_FEED_CHAR (static_cast<char>(10))
enum class ConsoleTextStyle
{
DEFAULT = 0,
BOLD = 1,
FAINT = 2,
ITALIC = 3,
UNDERLINE = 4,
SLOW_BLINK = 5,
RAPID_BLINK = 6,
REVERSE = 7,
};
enum class ConsoleForeground
{
DEFAULT = 39,
BLACK = 30,
DARK_RED = 31,
DARK_GREEN = 32,
DARK_YELLOW = 33,
DARK_BLUE = 34,
DARK_MAGENTA = 35,
DARK_CYAN = 36,
GRAY = 37,
DARK_GRAY = 90,
RED = 91,
GREEN = 92,
YELLOW = 93,
BLUE = 94,
MAGENTA = 95,
CYAN = 96,
WHITE = 97
};
enum class ConsoleBackground
{
DEFAULT = 49,
BLACK = 40,
DARK_RED = 41,
DARK_GREEN = 42,
DARK_YELLOW = 43,
DARK_BLUE = 44,
DARK_MAGENTA = 45,
DARK_CYAN = 46,
GRAY = 47,
DARK_GRAY = 100,
RED = 101,
GREEN = 102,
YELLOW = 103,
BLUE = 104,
MAGENTA = 105,
CYAN = 106,
WHITE = 107
};
class Console
{
public:
static void Clear();
static void WriteLine(const String &s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {});
static void Write(const String &s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {});
static void WriteLine(const WString &s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {});
static void Write(const WString &s, ConsoleForeground foreground = ConsoleForeground::DEFAULT, ConsoleBackground background = ConsoleBackground::DEFAULT, std::set<ConsoleTextStyle> styles = {});
static void WriteLine();
static void Pause();
static int PauseAny(bool printWhenPressed = false);
private:
static void EnableVirtualTermimalProcessing();
static void SetVirtualTerminalFormat(ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles);
static void ResetTerminalFormat();
};
class Strings
{
public:
static String WideStringToString(const WString &wstr);
static WString StringToWideString(const String &str);
static WString ToUpper(const WString &data);
static String ToUpper(const String &data);
static WString ToLower(const WString &data);
static String ToLower(const String &data);
};
String Strings::WideStringToString(const WString &wstr)
{
if (wstr.empty())
{
return String();
}
size_t pos;
size_t begin = 0;
String ret;
size_t size;
#ifdef WINDOWSLIB
pos = wstr.find(static_cast<wchar_t>(0), begin);
while (pos != WString::npos && begin < wstr.length())
{
WString segment = WString(&wstr[begin], pos - begin);
wcstombs_s(&size, nullptr, 0, &segment[0], _TRUNCATE);
String converted = String(size, 0);
wcstombs_s(&size, &converted[0], size, &segment[0], _TRUNCATE);
ret.append(converted);
begin = pos + 1;
pos = wstr.find(static_cast<wchar_t>(0), begin);
}
if (begin <= wstr.length())
{
WString segment = WString(&wstr[begin], wstr.length() - begin);
wcstombs_s(&size, nullptr, 0, &segment[0], _TRUNCATE);
String converted = String(size, 0);
wcstombs_s(&size, &converted[0], size, &segment[0], _TRUNCATE);
converted.resize(size - 1);
ret.append(converted);
}
#elif defined LINUXLIB
pos = wstr.find(static_cast<wchar_t>(0), begin);
while (pos != WString::npos && begin < wstr.length())
{
WString segment = WString(&wstr[begin], pos - begin);
size = wcstombs(nullptr, segment.c_str(), 0);
String converted = String(size, 0);
wcstombs(&converted[0], segment.c_str(), converted.size());
ret.append(converted);
ret.append({0});
begin = pos + 1;
pos = wstr.find(static_cast<wchar_t>(0), begin);
}
if (begin <= wstr.length())
{
WString segment = WString(&wstr[begin], wstr.length() - begin);
size = wcstombs(nullptr, segment.c_str(), 0);
String converted = String(size, 0);
wcstombs(&converted[0], segment.c_str(), converted.size());
ret.append(converted);
}
#elif defined MACOSLIB
#endif
return ret;
}
WString Strings::StringToWideString(const String &str)
{
if (str.empty())
{
return WString();
}
size_t pos;
size_t begin = 0;
WString ret;
size_t size;
#ifdef WINDOWSLIB
pos = str.find(static_cast<char>(0), begin);
while (pos != String::npos)
{
String segment = String(&str[begin], pos - begin);
WString converted = WString(segment.size() + 1, 0);
mbstowcs_s(&size, &converted[0], converted.size(), &segment[0], _TRUNCATE);
converted.resize(size - 1);
ret.append(converted);
ret.append({0});
begin = pos + 1;
pos = str.find(static_cast<char>(0), begin);
}
if (begin < str.length())
{
String segment = String(&str[begin], str.length() - begin);
WString converted = WString(segment.size() + 1, 0);
mbstowcs_s(&size, &converted[0], converted.size(), &segment[0], _TRUNCATE);
converted.resize(size - 1);
ret.append(converted);
}
#elif defined LINUXLIB
pos = str.find(static_cast<char>(0), begin);
while (pos != String::npos)
{
String segment = String(&str[begin], pos - begin);
WString converted = WString(segment.size(), 0);
size = mbstowcs(&converted[0], &segment[0], converted.size());
converted.resize(size);
ret.append(converted);
ret.append({0});
begin = pos + 1;
pos = str.find(static_cast<char>(0), begin);
}
if (begin < str.length())
{
String segment = String(&str[begin], str.length() - begin);
WString converted = WString(segment.size(), 0);
size = mbstowcs(&converted[0], &segment[0], converted.size());
converted.resize(size);
ret.append(converted);
}
#elif defined MACOSLIB
#endif
return ret;
}
WString Strings::ToUpper(const WString &data)
{
WString result = data;
auto &f = std::use_facet<std::ctype<wchar_t>>(std::locale());
f.toupper(&result[0], &result[0] + result.size());
return result;
}
String Strings::ToUpper(const String &data)
{
return WideStringToString(ToUpper(StringToWideString(data)));
}
WString Strings::ToLower(const WString &data)
{
WString result = data;
auto &f = std::use_facet<std::ctype<wchar_t>>(std::locale());
f.tolower(&result[0], &result[0] + result.size());
return result;
}
String Strings::ToLower(const String &data)
{
return WideStringToString(ToLower(StringToWideString(data)));
}
void Console::Clear()
{
#ifdef WINDOWSLIB
std::system(u8"cls");
#elif defined LINUXLIB
std::system(u8"clear");
#elif defined EMSCRIPTENLIB
emscripten::val::global()["console"].call<void>(u8"clear");
#elif defined MACOSLIB
#endif
}
void Console::Pause()
{
char c;
do
{
c = getchar();
} while (c != LINE_FEED_CHAR);
}
int Console::PauseAny(bool printWhenPressed)
{
int ch;
#ifdef WINDOWSLIB
ch = _getch();
#elif defined LINUXLIB
struct termios oldt, newt;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
#elif defined MACOSLIB
#endif
return ch;
}
void Console::EnableVirtualTermimalProcessing()
{
#if defined WINDOWSLIB
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
GetConsoleMode(hOut, &dwMode);
if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
{
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);
}
#endif
}
void Console::ResetTerminalFormat()
{
std::cout << u8"\033[0m";
}
void Console::SetVirtualTerminalFormat(ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles)
{
String format = u8"\033[";
format.append(std::to_string(static_cast<int>(foreground)));
format.append(u8";");
format.append(std::to_string(static_cast<int>(background)));
if (styles.size() > 0)
{
for (auto it = styles.begin(); it != styles.end(); ++it)
{
format.append(u8";");
format.append(std::to_string(static_cast<int>(*it)));
}
}
format.append(u8"m");
std::cout << format;
}
void Console::Write(const String &s, ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles)
{
EnableVirtualTermimalProcessing();
SetVirtualTerminalFormat(foreground, background, styles);
String str = s;
#ifdef WINDOWSLIB
WString unicode = Strings::StringToWideString(str);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), static_cast<DWORD>(unicode.length()), nullptr, nullptr);
#elif defined LINUXLIB
std::cout << str;
#elif defined MACOSLIB
#endif
ResetTerminalFormat();
}
void Console::WriteLine(const String &s, ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles)
{
Write(s, foreground, background, styles);
std::cout << std::endl;
}
void Console::Write(const WString &s, ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles)
{
EnableVirtualTermimalProcessing();
SetVirtualTerminalFormat(foreground, background, styles);
WString str = s;
#ifdef WINDOWSLIB
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), str.c_str(), static_cast<DWORD>(str.length()), nullptr, nullptr);
#elif defined LINUXLIB
std::cout << Strings::WideStringToString(str); //NEED TO BE FIXED. ADD locale parameter
#elif defined MACOSLIB
#endif
ResetTerminalFormat();
}
void Console::WriteLine(const WString &s, ConsoleForeground foreground, ConsoleBackground background, std::set<ConsoleTextStyle> styles)
{
Write(s, foreground, background, styles);
std::cout << std::endl;
}
int main()
{
std::locale::global(std::locale(u8"en_US.UTF-8"));
String dataStr = u8"Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë";
WString dataWStr = L"Zoë Saldaña played in La maldición del padre Cardona. ëèñ αω óóChloë";
std::string locale = u8"";
//std::string locale = u8"de_DE.UTF-8";
//std::string locale = u8"en_US.UTF-8";
Console::WriteLine(dataStr);
Console::WriteLine(dataWStr);
dataStr = Strings::ToUpper(dataStr);
dataWStr = Strings::ToUpper(dataWStr);
Console::WriteLine(dataStr);
Console::WriteLine(dataWStr);
dataStr = Strings::ToLower(dataStr);
dataWStr = Strings::ToLower(dataWStr);
Console::WriteLine(dataStr);
Console::WriteLine(dataWStr);
Console::PauseAny();
return 0;
}
Вы можете использовать следующий код для преобразования std::wstring (строки Юникода) в верхний регистр в C++. Этот код также обрабатывает случай, когда языковой стандарт «en_US.UTF8» недоступен, путем возврата к языковому стандарту по умолчанию. Языковой стандарт по умолчанию не изменяется, поэтому другие части программного обеспечения, использующие глобальный стандарт, не будут затронуты.
#include <locale>
#include <string>
std::locale CreateLocale()
{
try {
return std::locale("en_US.UTF8"); // some OS may not support this locale
}
catch (const std::runtime_error&) {
return std::locale(); // fallback to the default locale
}
}
// Lazy initialize facet
const std::ctype<wchar_t>& FacetUtf8() {
static const std::locale localeUtf8(CreateLocale());
static const std::ctype<wchar_t>& facet = std::use_facet<std::ctype<wchar_t> >(localeUtf8);
return facet;
}
void MakeUpper(std::wstring& str)
{
FacetUtf8().toupper(&str[0], &str[str.size()]);
}
void MakeLower(std::wstring& str)
{
FacetUtf8().tolower(&str[0], &str[str.size()]);
}
Вот пример того, как его использовать:
std::wstring str = L"hello, world! áăắặẳẵ";
MakeUpper(str);
wcout << str; // Outputs: "HELLO, WORLD! ÁĂẮẶẲẴ"
Для C I будет использовать toupper
после настройки языка Си в текущем потоке.
setlocale(LC_CTYPE, "en_US.UTF8");
Для C++ я бы использовал toupper
метод std::ctype<char>
:
std::locale loc;
auto& f = std::use_facet<std::ctype<char>>(loc);
char str[80] = "Hello World";
f.toupper(str, str+strlen(str));