Это похоже на простую проблему, но 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.
Здесь решение, предоставленное 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, но, похоже, вам понадобится внешняя библиотека.
C++ понятия не имеет о Unicode. Используйте внешнюю библиотеку, такую как ICU (класс UnicodeString) или Qt (класс QString), поддерживающие Unicode, включая UTF-8.
Поскольку UTF-8 имеет переменную длину, все виды индексирования будут индексировать в кодовых единицах, а не в кодовых точках. Невозможно сделать произвольный доступ к кодовым точкам в последовательности UTF-8 из-за его переменной длины. Если вам нужен произвольный доступ, вам нужно использовать кодировку с фиксированной длиной, например UTF-32. Для этого вы можете использовать префикс U для строк.
Стандарт языка 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).
Это все хорошо, но отображение из символов в файле, исходных символов (используется во время компиляции) определяется реализацией. Это составляет используемую кодировку.