C++如何获取wstring的第一个字母

C++ How to get first letter of wstring

本文关键字:wstring 第一个 获取 何获取 C++      更新时间:2023-10-16

这听起来是一个简单的问题,但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 *'

还有其他想法吗?

干杯,

Martin

----更新-----以下是一些应该说明问题的可执行代码。该程序将循环所有字母并逐一输出:

#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。

以下是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(关于源文件,但仍排序相关)

用C++进行编码有点复杂。以下是我的理解

每个实现都必须支持来自基本源的字符字符集。其中包括§2.2/1中列出的常见字符(C++11中的§2.3/1)。这些字符都应该放在一个字符中。在里面附加实现必须支持命名其他使用一种称为通用字符名的方式的字符\uffff或\Uffffff,可以用来指代unicode字符。A.它们的子集可用于标识符(见附件E)。

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