草庐IT

c++ - 使用 C++17 处理 Unicode 的高效、符合标准的机制是什么?

coder 2023-11-14 原文

短版:
如果我想编写可以有效执行 Unicode 字符操作的程序,能够输入和输出 UTF-8 或 UTF-16 编码的文件。使用 C++ 执行此操作的合适方法是什么?
长版:
C++ 早于 Unicode,并且两者都已经有了显着的发展。我需要知道如何编写符合标准且无泄漏的 C++ 代码。我需要一个明确的答案:

  • 我应该选择哪个字符串容器?
  • std::string用UTF-8?
  • std::wstring (不太了解)
  • std::u16string使用 UTF-16?
  • std::u32string使用 UTF-32?

  • 我应该完全坚持使用上述容器之一还是在需要时更换它们?
  • 使用 UTF 字符串时,我可以在字符串文字中使用非英语字符吗,例如波兰语字符:ąćęłńśźż等等?
  • 当我们在 std::string 中存储 UTF-8 编码的字符时会发生什么变化?它们仅限于一字节的 ASCII 字符还是可以是多字节的?
    当我执行以下操作时会发生什么?
     std::string s = u8"foo";
     s += 'x';
    
  • wchar_t 和其他多字节字符类型有什么区别?是 wchar_t字符或 wchar_t能够存储UTF编码的字符串文字?
  • 最佳答案

    Which string container should I pick?


    这真的由您决定,根据您自己的特定需求。您提供的任何选择都可以使用,而且它们各有优缺点。一般来说,UTF-8 适合用于存储和通信目的,并且向后兼容 ASCII。而处理 Unicode 数据时,UTF-16/32 更易于使用。

    std::wstring (don't really know much about it)

    wchar_t尺寸依赖于编译器,甚至依赖于平台。例如,在 Windows 上,wchar_t是 2 个字节,使得 std::wstring可用于 UTF-16 编码的字符串。在其他平台上,wchar_t可能是 4 个字节,使得 std::wstring可用于 UTF-32 编码的字符串。这就是为什么wchar_t/std::wstring一般不用于可移植代码,为什么char16_t/std::u16stringchar32_t/std::u32string是在 C++11 中引入的。偶char UTF-8 可能存在可移植性问题,因为 char可以根据编译器供应商的要求进行签名或不签名,这就是为什么 char8_t/std::u8string是在 C++20 中为 UTF-8 引入的。

    Should I stick entirely to one of the above containers or change them when needed?


    使用任何适合您需要的容器。
    通常,您应该在整个代码中使用一种字符串类型。仅在字符串数据进入/离开程序的边界处执行数据转换。例如,读/写文件、网络通信、平台系统调用等。

    How to properly convert between them?


    有很多方法可以处理。
    C++11 及更高版本有 std::wstring_convert/std::wbuffer_convert .但是这些在 C++17 中被弃用了。
    有第三方Unicode转换库,如ICONV、ICU等。
    有C库函数,平台系统调用等。

    Can I use non-english characters in string literals, when using UTF strings, such as Polish characters: ąćęłńśźż etc?


    是的,如果您使用适当的字符串文字前缀:u8对于 UTF-8。L对于 UTF-16 或 UTF-32(取决于编译器/平台)。u16对于 UTF-16。u32对于 UTF-32。
    另外,请注意用于保存源文件的字符集会影响编译器解释字符串文字的方式。因此,请确保您选择保存文件的任何字符集(例如 UTF-8)告诉编译器该字符集是什么,否则您可能会在运行时得到错误的字符串值。

    What changes when we store UTF-8 encoded characters in std::string? Are they limited to one-byte ASCII characters or can they be multi-byte?


    每个字符串字符可以是单字节,也可以是 Unicode 代码点的多字节表示的一部分。这取决于字符串的编码和被编码的字符。
    正如 std::wstring (当 wchar_t 为 2 个字节时)和 std::u16string可以保存包含 Unicode BMP 之外的补充字符的字符串,这需要 UTF-16 代理进行编码。
    当字符串容器包含 UTF 编码的字符串时,每个“字符”只是一个 UTF 编码的代码单元。 UTF-8 将 Unicode 代码点编码为 1-4 个代码单元(1-4 char s in a std::string) 。UTF-16 将代码点编码为 1-2 个代码单元(1-2 wchar_t s/char16_tstd::wstring/std::u16string 中。UTF-32 将代码点编码为 1 个代码单元(在 char32_t 中为 1 std::u32string)。

    What happens when i do the following?

    std::string s = u8"foo";
    s += 'x';
    

    正是您所期望的。一个 std::string持有 char元素。不管编码如何,operator+=(char)将简单地附加一个 char到最后std::string .

    How can I distinguish UTF char[] and non-UTF char[] or std::string?


    您需要了解字符串原始编码的外部知识,或者对 char[] 执行您自己的启发式分析。/std::string数据以查看它是否符合 UTF。

    What are differences between wchar_t and other multi-byte character types?


    字节大小和 UTF 编码。char = ANSI/MBCS 或 UTF-8wchar_t = DBCS、UTF-16 或 UTF-32,取决于编译器/平台char8_t = UTF-8char16_t = UTF-16char32_t = UTF-32

    Is wchar_t character or wchar_t string literal capable of storing UTF encodings?


    是的,UTF-16 或 UTF-32,取决于编译器/平台。对于 UTF-16,单个 wchar_t只能保存 BMP 中的代码点值。单wchar_t在 UTF-32 中可以保存任何代码点值。一个 wchar_t string 可以以任一编码方式对所有代码点进行编码。

    How to properly manipulate UTF strings (such as toupper/tolower conversion) and be compatible with locales simultaneously?


    这是一个非常广泛的话题,值得单独提出一个问题。

    关于c++ - 使用 C++17 处理 Unicode 的高效、符合标准的机制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48816848/

    有关c++ - 使用 C++17 处理 Unicode 的高效、符合标准的机制是什么?的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

      我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

    3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

      很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

    5. ruby - 在 Ruby 中使用匿名模块 - 2

      假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

    6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

      我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

    7. ruby-on-rails - unicode 字符串的长度 - 2

      在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

    8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    9. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

      我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

    10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    随机推荐