【问题标题】:C++ How to get first letter of wstringC ++如何获取wstring的第一个字母
【发布时间】:2013-12-13 14:52:14
【问题描述】:

这听起来像一个简单的问题,但 C++ 让它变得困难(至少对我来说):我有一个 wstring,我想将第一个字母作为 wchar_t 对象,然后从字符串中删除这个第一个字母。

这里不适用于非 ASCII 字符:

wchar_t currentLetter = word.at(0);  

因为它会返回两个字符(循环中)用于诸如德语变音符号之类的字符。

这里也不行:

wchar_t currentLetter = word.substr(0,1);

error: no viable conversion from 'std::basic_string<wchar_t>' to 'wchar_t'

这也不是:

wchar_t currentLetter = word.substr(0,1).c_str();

error: cannot initialize a variable of type 'wchar_t' with an rvalue of type 'const wchar_t *'

还有其他想法吗?

干杯,

马丁

---- 更新 ----- 这是一些应该演示问题的可执行代码。该程序将遍历所有字母并一一输出:

#include <iostream>
using namespace std;

int main() {
    wstring word = L"für";
    wcout << word << endl;
    wcout << word.at(1) << " " << word[1] << " " << word.substr(1,1) << endl;

    wchar_t currentLetter;
    bool isLastLetter;

    do {
        isLastLetter = ( word.length() == 1 );
        currentLetter = word.at(0);
        wcout << L"Letter: " << currentLetter << endl;

        word = word.substr(1, word.length()); // remove first letter
    } while (word.length() > 0);

    return EXIT_SUCCESS;
}

但是,我得到的实际输出是:

f?r ? ? ? 字母:f 信件: ? 字母:r

源文件采用 UTF8 编码,控制台的编码也设置为 UTF8。

【问题讨论】:

  • 第一个版本到底有什么问题?你可以为你的元音变音问题发布代码吗?
  • C++ 字符串函数本身并不支持 Unicode。不要指望他们知道变音符号和字母之间的区别。
  • wstring::substr() 返回一个新的wstring,而不是单个字符。

标签: c++ wstring


【解决方案1】:

这是Sehe提供的解决方案:

#include <iostream>
#include <string>
#include <boost/regex/pending/unicode_iterator.hpp>

using namespace std;

template <typename C>
std::string to_utf8(C const& in)
{
    std::string result;
    auto out = std::back_inserter(result);
    auto utf8out = boost::utf8_output_iterator<decltype(out)>(out);

    std::copy(begin(in), end(in), utf8out);
    return result;
}

int main() {
    wstring word = L"für";

    bool isLastLetter;

    do {
        isLastLetter = ( word.length() == 1 );
        auto currentLetter = to_utf8(word.substr(0, 1));
        cout << "Letter: " << currentLetter << endl;

        word = word.substr(1, word.length()); // remove first letter
    } while (word.length() > 0);

    return EXIT_SUCCESS;
}

输出:

Letter: f

Letter: ü

Letter: r

是的,您需要 Boost,但似乎无论如何您都需要一个外部库。

1

C++ 不知道 Unicode。使用外部库,例如 ICU (UnicodeString 类)或 Qt(QString 类),都支持 Unicode, 包括 UTF-8。

2

由于 UTF-8 具有可变长度,各种索引都可以 以代码单元而不是代码点为索引。这是不可能的 随机访问 UTF-8 序列中的代码点,因为它是 可变长度性质。如果你想要随机访问,你需要使用 固定长度编码,如 UTF-32。为此,您可以使用 U 前缀 在字符串上。

3

C++ 语言标准没有显式编码的概念。它只是 包含“系统编码”的不透明概念,其中 wchar_t 是 一个“足够大”的类型。

从不透明的系统编码转换为显式的外部编码 编码,您必须使用外部库。选择的图书馆 将是 iconv() (从 WCHAR_T 到 UTF-8),它是 Posix 和 在许多平台上可用,尽管在 Windows 上 WideCharToMultibyte 函数保证生成 UTF8。

C++11 以 std::string s = u8"Hello 的形式添加了新的 UTF8 文字 世界:\U0010FFFF";。那些已经是 UTF8,但他们不能 与不透明的 wstring 交互,而不是通过我的方式 描述。

4 (about source files but still sorta relevant)

C++ 中的编码相当复杂。这是我的理解 。

每个实现都必须支持来自基本源的字符 字符集。这些包括 §2.2/1 中列出的常见字符 (C++11 中的第 2.3/1 节)。这些字符都应该适合一个字符。在 另外的实现必须支持一种命名其他的方法 字符使用一种称为通用字符名称的方式,看起来像 \uffff 或 \Uffffffff 可用于指代 unicode 字符。一种 它们的子集可用于标识符(列在附件 E 中)。

这一切都很好,但是从文件中的字符映射到 源字符(在编译时使用)是实现定义的。 这构成了使用的编码。

【讨论】:

  • 非常感谢您的帮助。不过,我更喜欢不依赖外部库的解决方案。我无法想象像这样简单的东西没有包含在“开箱即用”的 C++ 中。
  • @marw 实际上并不是那么简单,而且 AFAIK(来自我引用的来源),标准对此并不十分清楚。如果您想要一致性,请使用库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-30
  • 2013-10-29
  • 2019-01-16
  • 1970-01-01
  • 1970-01-01
  • 2018-07-11
  • 2015-07-02
相关资源
最近更新 更多