C ++ 20为UTF-8添加了char8_t
和std::u8string
。但是,没有std::cout
的UTF-8版本,并且OS API通常期望char
和执行字符集。因此,我们仍然需要一种在UTF-8和执行字符集之间进行转换的方法。
我正在重读char8_t paper,看来在UTF-8和ECS之间转换的唯一方法是使用std::c8rtomb
和std::mbrtoc8
函数。但是,它们的API极为混乱。有人可以提供示例代码吗?
答案 0 :(得分:1)
在C ++ 20中,UTF-8“支持”似乎是个坏笑话。
STL中唯一的UTF功能是支持字符串和string_views(std :: u8string,std :: u8string_vew,std :: u16string等)。就这些。对于正则表达式,格式,文件I / O等中的UTF编码,不提供STL支持。
在C ++ 17中,您可以-至少-轻松地将任何UTF-8数据视为'char'数据,从而可以使用std :: regex,std :: fstream,std :: cout等。不会损失性能。
在C ++ 20中,情况将会改变。例如,您不能再写std::string text = u8"...";
,将不可能写出类似的内容
std::u8fstream file; std::u8string line; ... file << line;
因为它不是std :: u8fstream。
即使新的C ++ 20 std :: format根本不支持UTF,因为所有必需的重载都被丢失了。你不会写
std::u8string text = std::format(u8"...{}...", 42);
更糟糕的是,在std :: string和std :: u8string之间(甚至在const char *和const char8_t *之间)进行简单的转换(或转换)是不容易的。因此,如果要格式化(使用std :: format)或输入/输出(std :: cin,std :: cout,std :: fstream等),您必须在内部复制所有字符串。 -那将是不必要的性能杀手。
最后,如果没有输入,输出和格式,UTF将有什么用途?
答案 1 :(得分:1)
VS 2019
ostream& operator<<(ostream& os, const u8string& str)
{
os << reinterpret_cast<const char*>(str.data());
return os;
}
要将控制台设置为 UTF-8,请使用 https://github.com/MicrosoftDocs/cpp-docs/issues/1915#issuecomment-589644386
答案 2 :(得分:0)
目前,std::c8rtomb
和std::mbrtoc8
是该标准提供的仅有的使执行编码和UTF-8之间转换的接口。接口很尴尬。它们旨在匹配std::c16rtomb
和std::mbrtoc16
之类的现有接口。在C ++标准中为这些新接口添加的措辞有意与在C标准中针对预先存在的相关功能的措辞相匹配(希望这些新功能最终会被添加到C中;我仍然需要继续这样做)。与C标准措辞相匹配的目的,是要使之困惑,这是为了确保熟悉C措辞的任何人都认识到char8_t
接口的工作方式相同。
cppreference.com提供了这些函数的UTF-16版本的一些示例,这些示例对于理解char8_t
变体应该很有用。
答案 3 :(得分:0)
当前(2019年11月)尚未提供“ {3”制作的未来C ++ 20就绪的编译器提供的std::c8rtomb
和std::mbrtoc8
,以实现执行编码之间的转换和UTF-8。它们在C ++ 20标准中进行了描述。
对我来说,这可能是主观的,但是c8rtomb()
并不是一个“尴尬”的界面。
// g++ prog.cc -std=gnu++2a
// clang++ prog.cc -std=c++2a
#include <stdio.h>
#include <clocale>
#ifndef __clang__
#include <cuchar>
#else
// clang has no <cuchar>
#include <uchar.h>
#endif
#include <climits>
template<typename C32, size_t N>
void u32sample( const C32 (&str32)[N] )
{
#ifndef __clang__
std::mbstate_t state{};
#else
mbstate_t state{};
#endif
char out[MB_LEN_MAX]{};
for(char32_t const & c : str32)
{
#ifndef __clang__
/*std::size_t rc =*/ std::c32rtomb(out, c, &state);
#else
/* std::size_t rc =*/ ::c32rtomb(out, c, &state);
#endif
printf("%s", out ) ;
}
}
template<typename C8, size_t N>
void u8sample( const C8 (& str8)[N])
{
#ifndef __clang__
std::mbstate_t state{};
#else
mbstate_t state{};
#endif
char out[MB_LEN_MAX]{};
for(char8_t const & c : str8)
{
#ifndef __clang__
// not in std for gcc 10, C++20
/* std::size_t rc = */ /* std::c8rtomb(out, c, &state); */
printf("%s", "std::c8rtomb() is not implemented, " __DATE__ ) ;
break;
#else
// not there for clang 10, C++20
/* std::size_t rc = */ /* ::c8rtomb(out, c, &state); */
printf("%s", "::c8rtomb() is not implemented, " __DATE__ ) ;
break;
#endif
printf("%s", out ) ;
}
}
int main () {
std::setlocale(LC_ALL, "en_US.utf8");
#ifdef __linux__
printf("\nLinux like OS, ") ;
#endif
#ifdef __clang__
printf(" clang %d.%d.%d\n", __clang_major__ , __clang_minor__ , __clang_patchlevel__ ) ;
#else
printf(" gcc %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__ ) ;
#endif
printf("\nchar32_t *, Converting to 'char *', and then printing\n" ) ;
u32sample( U"ひらがな" ) ;
printf("\nDone ...\n" ) ;
printf("\nchar8_t *, Converting to 'char *', and then printing\n" ) ;
u8sample( u8"ひらがな" ) ;
printf("\nDone ..." ) ;
return 42;
}
我已经注释掉并记录下来,直到今天仍未编译的行。
答案 4 :(得分:0)
C ++权威机构在年度CppCon大会(例如在2018年和2019年)上给出的常见答案是,您应该选择自己的UTF8库来这样做。有各种各样的口味,只需选择您喜欢的一种即可。在C ++方面,对unicode的理解和支持仍然很少。
有些人会在C ++ 23中实现某些功能,但到目前为止我们还没有正式的工作组。
答案 5 :(得分:0)
以下是应符合C ++ 20的代码。由于目前没有编译器(2020年3月)实现本文中定义的转换函数,因此我决定不限制自己使用当前实现的功能,并使用C ++ 20的完整规范。因此,我采用的是代码单元范围,而不是采用import {
writable,
get
} from 'svelte/store'
const signUp = writable()
const signUpStore = {
subscribe: signUp.subscribe,
setSignUp: (items) => {
signUp.set(items)
// console.log('items : ', items, signUp)
},
addSignUp: (data) => {
signUp.update(items => {
return items.concat(data)
})
},
getSignUp: () => {
get(signUp)
}
}
export default signUpStore;
或std::basic_string
。返回值的通用性较差,但将其更改为采用输出范围并不容易。这留给读者练习。
std::basic_string_view
答案 6 :(得分:0)
AFAIK C++ 还没有为这种转换提供工具。但是,我首先建议使用 std::u8string
,因为它在标准中的支持很差,并且根本不受任何系统 API 支持(并且可能永远不会因为兼容性原因而支持)。在大多数平台上,正常的 char
字符串已经是 UTF-8,而在带有 MSVC 的 Windows 上,您可以使用 /utf-8
进行编译,这将为您在主要操作系统上提供可移植的 Unicode 支持。