2010-09-30 2 views
2

Когда дело доходит до интернационализации & Unicode, я идиот, американский программист. Вот сделка.Строка literal to basic_string <unsigned char>

#include <string> 
using namespace std; 

typedef basic_string<unsigned char> ustring; 

int main() 
{ 
    static const ustring my_str = "Hello, UTF-8!"; // <== error here 
    return 0; 
} 

Это испускает не-неожиданные жалобы:

cannot convert from 'const char [14]' to 'std::basic_string<_Elem>'

Может быть, у меня была неправильная часть кофе сегодня. Как это исправить? Могу ли я сохранить базовую структуру:

ustring something = {insert magic incantation here};

?

+0

Не отвечаю на ваш вопрос, но читать эту статью на i18n: http://www.joelonsoftware.com/articles/Unicode.html – Starkey

+0

Seen it, но thx –

+1

Вероятно, вам нужно предоставить свою специальную специализацию 'char_traits . AFAIK, '' предоставляет только специализации для 'char' и' wchar_t'. – Praetorian

ответ

4

Узкие строковые литералы определяются как const char и нет беззнаковых строковые литералы [1], так что вам придется бросить:

ustring s = reinterpret_cast<const unsigned char*>("Hello, UTF-8"); 

Конечно, вы можете положить, что длинные вещи в инлайн функция:

inline const unsigned char *uc_str(const char *s){ 
    return reinterpret_cast<const unsigned char*>(s); 
} 

ustring s = uc_str("Hello, UTF-8"); 

Или вы можете просто использовать basic_string<char> и уйти с него 99,9% времени, вы имеете дело с UTF-8.

[1] Если char не подпадает под, но является ли это или нет, определяется реализацией, бла, бла.

+0

Я * думаю * это ответ ... –

+0

@Steve, I знаете, что это старый, но мне любопытно, когда 'basic_string ' не работает для хранения кодированных строк UTF-8? Это просто сохранение последовательности байтов, которая до сих пор не сработала. Я не знаю, что такое угловой случай? – Matthew

1

Использование разных типов символов для разных кодировок имеет преимущества, которые компилятор лает на вас, когда вы их испортите. Недостатком является то, что вы должны вручную преобразовать.

Несколько вспомогательных функций к спасению:

inline ustring convert(const std::string& sys_enc) { 
    return ustring(sys_enc.begin(), sys_enc.end()); 
} 

template< std::size_t N > 
inline ustring convert(const char (&array)[N]) { 
    return ustring(array, array+N); 
} 

inline ustring convert(const char* pstr) { 
    return ustring(reinterpret_cast<const ustring::value_type*>(pstr)); 
} 

Конечно, все это не в состоянии тихо и фатально, когда строка для преобразования содержит ничего, кроме ASCII.

+0

Как-то я не могу использовать третью перегрузку 'convert'.Я получаю следующую ошибку компиляции: 'error: cast from 'const char *' to 'std :: __ cxx11 :: basic_string :: value_type {aka unsigned char}' теряет точность [-fpermissive] return ustring (reinterpret_cast (pstr)); '. [coliru link] (http://coliru.stacked-crooked.com/a/66b1d6c08a1ad63e) – Patryk

+0

@Patryk: Я считаю, что исправил это сейчас. Извините, я так давно ошибался. – sbi

+1

Это то, что у нас есть для :) – Patryk

0

Сделайте вашу жизнь проще, используйте библиотеку строк UTF-8, такую ​​как http://utfcpp.sourceforge.net/, или зайдите в std :: wstring и используйте UTF-16. Вы можете быть заинтересованы в обсуждении другого вопроса о переполнении стека: C++ strings: UTF-8 or 16-bit encoding?

+0

Невозможно использовать UTF-16. Входящий файл - UTF-8. –

+0

Я предполагаю, что следующий вопрос: что вам нужно делать с данными из файла после его загрузки? Может иметь смысл преобразовать его в UTF-16, или может быть проще и эффективнее хранить его как UTF-8. – Matthew

+0

UTF-16 на самом деле не имеет таких преимуществ перед UTF-8. Фактически, единственное, о чем я могу думать, это A) это родная кодировка Unicode для Windows, поэтому, когда вы делаете Windows, это упрощает и B), когда вы используете много таких символов (CJK?), Которые нужен три байта в UTF-8, но только в UTF-16, тогда UTF-16 требует меньше памяти. – sbi

Смежные вопросы