C ++ Как получить первую букву wstring

0

Это похоже на простую проблему, но C++ затрудняет (по крайней мере, для меня): у меня есть wstring, и я хотел бы получить первую букву как объект wchar_t, а затем удалить эту первую букву из строки.

Это не работает для символов, отличных от ASCII:

wchar_t currentLetter = word.at(0);  

Потому что он возвращает два символа (в цикле) для таких символов, как German Umlauts.

Это также не работает:

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.

  • 1
    В чем конкретно проблема с первой версией? Можете ли вы опубликовать код для вашей проблемы Umlaut?
  • 0
    Строковые функции C ++ изначально не поддерживают Unicode. Не ожидайте, что они узнают разницу между умлаутом и буквой.
Показать ещё 1 комментарий
Теги:
wstring

1 ответ

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 добавляет новые литералы UTF8 в виде std :: string s = u8 "Hello World:\U0010FFFF" ;. Они уже находятся в UTF8, но они не могут взаимодействовать с непрозрачной wstring, кроме как описанным мной способом.

4 (об исходных файлах, но по-прежнему относится к соответствующим)

Кодирование в C++ довольно сложно. Вот мое понимание этого.

Каждая реализация должна поддерживать символы из базового набора символов источника. К ним относятся общие символы, перечисленные в §2.2/1 (§2.3/1 в C++ 11). Эти персонажи должны вписываться в один символ. Кроме того, реализации должны поддерживать способ для обозначения других символов, используя способ, называемый универсальными именами символов, и выглядят как \uffff или\Uffffffff и могут использоваться для обозначения символов Unicode. Подмножество из них можно использовать в идентификаторах (перечисленных в Приложении E).

Это все хорошо, но отображение из символов в файле, исходных символов (используется во время компиляции) определяется реализацией. Это составляет используемую кодировку.

  • 0
    Большое спасибо за помощь. Я бы предпочел решение без зависимостей от внешних библиотек. Я не могу себе представить, что что-то столь простое, как это, не включено в C ++ "из коробки".
  • 0
    @marw На самом деле это не так просто, и AFAIK (из источников, которые я цитировал), стандарт не совсем ясен в этом. Если вы хотите последовательности, используйте библиотеку.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню