Типографский апостроф + широкий строковый литерал сломал мой мир (C ++) - PullRequest
1 голос
/ 03 мая 2009

Я только что столкнулся с некоторым странным поведением, когда имел дело со зловещим типографским апострофом (’) - не апострофом пишущей машинки ('). Используемый с широким строковым литералом, апостроф разрывается по потоку.

Этот код работает

ofstream file("test.txt");
file << "A’B" ;
file.close();

==> A’B

Этот код работает

wofstream file("test.txt");
file << "A’B" ;
file.close();

==> A’B

Этот код не работает

wofstream file("test.txt");
file << L"A’B" ;
file.close();

==> A

Этот код не работает ...

wstring test = L"A’B";
wofstream file("test.txt");
file << test ;
file.close();

==> A

Есть идеи?

Ответы [ 3 ]

1 голос
/ 03 мая 2009

Вы должны "включить" локаль перед использованием wofstream:

std::locale::global(std::locale()); // Enable locale support 
wofstream file("test.txt");
file << L"A’B";

Так что, если у вас есть системная локаль en_US.UTF-8, тогда файл test.txt будет включать Данные в кодировке utf8 (4 байта), если у вас есть системная локаль en_US.ISO8859-1, то она будет кодироваться как 8-битная кодировка (3 байта), если только ISO 8859-1 не пропустит такой символ.

wofstream file("test.txt");
file << "A’B" ;
file.close();

Этот код работает, потому что "A’B" на самом деле является строкой utf-8, и вы сохраняете utf-8 строка в файл побайтно.

Примечание: Я предполагаю, что вы используете POSIX-подобную ОС, и у вас есть локаль по умолчанию, отличная от "C", которая является локалью по умолчанию.

0 голосов
/ 03 мая 2009

Попробуйте поместить символ вставки потока в блок try-catch и скажите, что, если таковое имеется, генерирует исключение.

Я не уверен, что здесь происходит, но я все равно буду беспокоить догадку. Типографский апостроф, вероятно, имеет значение, которое умещается в один байт. Это работает с "A’B", поскольку оно слепо копирует байты, не заботясь о базовой кодировке. Однако при L"A’B" в игру вступает фактор кодирования, зависящий от реализации. Вероятно, он не находит правильное значение UTF-16 (если вы в Windows) или UTF-32 (если вы используете * nix / Mac) для хранения для этого конкретного символа.

0 голосов
/ 03 мая 2009

Вы уверены, что это не поддержка вашего компилятора символов юникода в исходных файлах, которая "сломана"? Что если вы используете \x или подобное для кодирования символа в строковом литерале? Ваш исходный файл даже в какой-либо кодировке может составлять wchar_t для вашего компилятора?

...