std :: wstring VS std :: string - PullRequest
       83

std :: wstring VS std :: string

695 голосов
/ 31 декабря 2008

Я не могу понять разницу между std::string и std::wstring. Я знаю, wstring поддерживает широкие символы, такие как символы Юникода. У меня есть следующие вопросы:

  1. Когда я должен использовать std::wstring сверх std::string?
  2. Может ли std::string содержать весь набор символов ASCII, включая специальные символы?
  3. Поддерживается ли std::wstring всеми популярными компиляторами C ++?
  4. Что такое " широкий символ "?

Ответы [ 12 ]

944 голосов
/ 31 декабря 2008

string? wstring

std::string - это basic_string, настроенный на char, и std::wstring на wchar_t.

char против wchar_t

char должен содержать символ, обычно 8-битный символ.
wchar_t должен содержать широкий символ, а затем все становится сложнее:
В Linux wchar_t составляет 4 байта, а в Windows - 2 байта.

А как же Unicode , тогда?

Проблема в том, что ни char, ни wchar_t не связаны напрямую с юникодом.

В Linux?

Давайте возьмем ОС Linux: моя система Ubuntu уже поддерживает Unicode. Когда я работаю со строкой символа, она изначально кодируется в UTF-8 (т.е. строка символов Unicode). Следующий код:

#include <cstring>
#include <iostream>

int main(int argc, char* argv[])
{
   const char text[] = "olé" ;


   std::cout << "sizeof(char)    : " << sizeof(char) << std::endl ;
   std::cout << "text            : " << text << std::endl ;
   std::cout << "sizeof(text)    : " << sizeof(text) << std::endl ;
   std::cout << "strlen(text)    : " << strlen(text) << std::endl ;

   std::cout << "text(ordinals)  :" ;

   for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
   {
      std::cout << " " << static_cast<unsigned int>(
                              static_cast<unsigned char>(text[i])
                          );
   }

   std::cout << std::endl << std::endl ;

   // - - - 

   const wchar_t wtext[] = L"olé" ;

   std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ;
   //std::cout << "wtext           : " << wtext << std::endl ; <- error
   std::cout << "wtext           : UNABLE TO CONVERT NATIVELY." << std::endl ;
   std::wcout << L"wtext           : " << wtext << std::endl;

   std::cout << "sizeof(wtext)   : " << sizeof(wtext) << std::endl ;
   std::cout << "wcslen(wtext)   : " << wcslen(wtext) << std::endl ;

   std::cout << "wtext(ordinals) :" ;

   for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
   {
      std::cout << " " << static_cast<unsigned int>(
                              static_cast<unsigned short>(wtext[i])
                              );
   }

   std::cout << std::endl << std::endl ;

   return 0;
}

выводит следующий текст:

sizeof(char)    : 1
text            : olé
sizeof(text)    : 5
strlen(text)    : 4
text(ordinals)  : 111 108 195 169

sizeof(wchar_t) : 4
wtext           : UNABLE TO CONVERT NATIVELY.
wtext           : ol�
sizeof(wtext)   : 16
wcslen(wtext)   : 3
wtext(ordinals) : 111 108 233

Вы увидите, что текст "olé" в char действительно состоит из четырех символов: 110, 108, 195 и 169 (не считая конечного нуля). (Я позволю вам изучить код wchar_t в качестве упражнения)

Таким образом, при работе с char в Linux вы обычно должны использовать Unicode, даже не подозревая об этом. И поскольку std::string работает с char, то std::string уже готов к Unicode.

Обратите внимание, что std::string, как и API-интерфейс C string, будет считать, что строка "olé" имеет 4 символа, а не три. Поэтому вы должны быть осторожны при усечении / игре с символами Юникода, потому что в UTF-8 запрещена некоторая комбинация символов.

В Windows?

В Windows это немного по-другому. Win32 должен был поддерживать множество приложений, работающих с char и на различных кодировках / кодовых страницах , созданных во всем мире, до появления Unicode.

Так что их решение было интересным: если приложение работает с char, то строки символов кодируются / печатаются / отображаются на этикетках графического интерфейса с использованием локальной кодировки / кодовой страницы на машине. Например, «olé» будет «olé» в локализованной на французском языке Windows, но будет отличаться в локализованной на кириллице Windows («olй», если вы используете Windows-1251 ). Таким образом, «исторические приложения» обычно будут работать так же, как и раньше.

Для приложений на основе Unicode Windows использует wchar_t, который имеет ширину 2 байта и кодируется в UTF-16 , который кодируется в Unicode с 2-байтовыми символами (или как минимум , в основном совместимый UCS-2, который почти то же самое, что IIRC).

Приложения, использующие char, называются «многобайтовыми» (потому что каждый глиф состоит из одного или нескольких char с), в то время как приложения, использующие wchar_t, называются «широкоформатными» (потому что каждый глиф состоит из одного или двух wchar_t. Подробнее см. MultiByteToWideChar и WideCharToMultiByte API преобразования Win32.

Таким образом, если вы работаете в Windows, вы крайне хотите, чтобы использовал wchar_t (если только вы не используете фреймворк, скрывающий это, например GTK + или QT ...). Дело в том, что за кулисами Windows работает со строками wchar_t, поэтому даже исторические приложения будут преобразовывать свои строки char в wchar_t при использовании API, например SetWindowText() (функция API низкого уровня для установки метки на Win32 GUI).

Проблемы с памятью?

UTF-32 имеет размер 4 байта на символы, поэтому добавлять нечего, если только текст UTF-8 и текст UTF-16 всегда будут использовать меньше или одинаковое количество памяти, чем текст UTF-32 ( и обычно меньше).

Если есть проблема с памятью, то вы должны знать, что для большинства западных языков текст UTF-8 будет использовать меньше памяти, чем тот же UTF-16.

Тем не менее, для других языков (китайский, японский и т. Д.) Используемая память будет либо такой же, либо немного большей для UTF-8, чем для UTF-16.

В целом, UTF-16 будет в основном использовать 2 и иногда 4 байта на символы (если вы не имеете дело с какими-то глифами эзотерического языка (клингон? Эльфийский?), В то время как UTF-8 будет тратить от 1 до 4 байт.

Подробнее см. http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16.

Заключение

  1. Когда мне следует использовать std :: wstring вместо std :: string?

    В Linux? Почти никогда (§).
    На винде? Почти всегда (§).
    На кроссплатформенный код? Зависит от вашего инструментария ...

    (§): если вы не используете инструментарий / фреймворк, говорящий иначе

  2. Может ли std::string содержать весь набор символов ASCII, включая специальные символы?

    Примечание: std::string подходит для хранения «двоичного» буфера, где std::wstring - нет!

    В Linux? Да.
    На винде? Для текущей локали пользователя Windows доступны только специальные символы.

    Редактировать (После комментария от Иоганн Герелл ):
    std::string будет достаточно для обработки всех строк char (каждая char - это число от 0 до 255). Но:

    1. Предполагается, что значение ASCII должно быть от 0 до 127. Более высокие значения char НЕ являются значениями ASCII.
    2. a char от 0 до 127 будет удерживаться правильно
    3. a char от 128 до 255 будет иметь значение в зависимости от вашей кодировки (Unicode, Non-Unicode и т. Д.), Но он сможет содержать все символы Unicode до тех пор, пока они закодированы в UTF-8 .
  3. Поддерживается ли std::wstring почти всеми популярными компиляторами C ++?

    В основном, за исключением компиляторов на основе GCC, портированных на Windows.
    Он работает на моем g ++ 4.3.2 (под Linux), и я использовал Unicode API на Win32 начиная с Visual C ++ 6.

  4. Что такое широкий символ?

    На C / C ++ это тип символов, написанный wchar_t, который больше, чем простой тип символов char. Предполагается, что он используется для помещения символов, индексы которых (например, глифы Unicode) больше 255 (или 127, в зависимости ...).

58 голосов
/ 29 декабря 2009

Я рекомендую избегать std::wstring в Windows или где-либо еще, за исключением случаев, когда это требуется интерфейсом, или где-либо рядом с вызовами Windows API и соответствующими преобразованиями кодировки в качестве синтаксического сахара.

Мое мнение суммировано в http://utf8everywhere.org, соавтором которого я являюсь.

Если ваше приложение не ориентировано на вызовы API, например В основном это пользовательский интерфейс, рекомендуется хранить строки Unicode в std :: string и кодировать в UTF-8, выполняя преобразование рядом с вызовами API. Преимущества, изложенные в статье, перевешивают очевидное раздражение конверсии, особенно в сложных приложениях. Это вдвойне верно для мультиплатформенной и библиотечной разработки.

А теперь, отвечая на ваши вопросы:

  1. Несколько слабых причин. Он существует по историческим причинам, когда считалось, что Widechars - это правильный способ поддержки Unicode. Теперь он используется для интерфейса API, которые предпочитают строки UTF-16. Я использую их только в непосредственной близости от таких вызовов API.
  2. Это не имеет ничего общего с std :: string. Он может содержать любую кодировку, которую вы положили в него. Вопрос только в том, как Вы относитесь к его содержанию. Я рекомендую UTF-8, поэтому он сможет правильно удерживать все символы Юникода. Это обычная практика для Linux, но я думаю, что программы для Windows также должны это делать.
  3. Нет.
  4. Широкий символ - запутанное имя. В первые дни Unicode существовало мнение, что символ может быть закодирован в два байта, отсюда и название. Сегодня это означает «любая часть символа длиной два байта». UTF-16 рассматривается как последовательность таких байтовых пар (или широких символов). Символ в UTF-16 принимает одну или две пары.
37 голосов
/ 07 ноября 2011

Итак, каждый читатель здесь должен иметь четкое представление о фактах, ситуации. Если нет, то вы должны прочитать выдающийся исчерпывающий ответ paercebal [кстати: спасибо!].

Мой прагматический вывод шокирующе прост: все эти «кодировки символов» в C ++ (и STL) по сути сломаны и бесполезны. Винить это в Microsoft или нет, это все равно не поможет.

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

  1. Примите, что вы сами должны нести ответственность за кодирование и преобразование (и вы увидите, что многое из этого довольно тривиально)

  2. использовать std :: string для любых строк в кодировке UTF-8 (просто typedef std::string UTF8String)

  3. принять, что такой объект UTF8String - просто тупой, но дешевый контейнер. Никогда не открывайте и / или не манипулируйте в нем символами напрямую (без поиска, замены и т. Д.). Вы могли бы, но вы действительно просто действительно не хотите тратить свое время на написание алгоритмов манипулирования текстом для многобайтовых строк! Даже если другие люди уже делали такие глупости, не делайте этого! Будь как будет! (Ну, есть сценарии, в которых это имеет смысл ... просто используйте для этого библиотеку ICU).

  4. использование std :: wstring для строк в кодировке UCS-2 (typedef std::wstring UCS2String) - это компромисс и уступка путанице, которую представил WIN32 API). UCS-2 достаточно для большинства из нас (подробнее об этом позже ...).

  5. использовать экземпляры UCS2String всякий раз, когда требуется посимвольный доступ (чтение, манипулирование и т. Д.). Любая символьная обработка должна выполняться в не многобайтовом представлении. Это просто, быстро, легко.

  6. добавить две служебные функции для преобразования туда и обратно между UTF-8 и UCS-2:

    UCS2String ConvertToUCS2( const UTF8String &str );
    UTF8String ConvertToUTF8( const UCS2String &str );
    

Преобразования просты, Google должен помочь здесь ...

Вот и все. Используйте UTF8String везде, где память драгоценна и для всех операций ввода-вывода UTF-8. Используйте UCS2String везде, где строка должна быть проанализирована и / или обработана. Вы можете конвертировать эти два представления в любое время.

Альтернативы и улучшения

  • преобразования из & в однобайтовые кодировки символов (например, ISO-8859-1) могут быть реализованы с помощью простых таблиц перевода, например, const wchar_t tt_iso88951[256] = {0,1,2,...}; и соответствующий код для преобразования в и из UCS2.

  • если UCS-2 недостаточно, то переключиться на UCS-4 (typedef std::basic_string<uint32_t> UCS2String)

ICU или другие библиотеки Unicode?

Для продвинутых вещей.

25 голосов
/ 31 декабря 2008
  1. Если вы хотите, чтобы широкие символы сохранялись в вашей строке. wide зависит от реализации. Visual C ++ по умолчанию 16-битный, если я правильно помню, в то время как GCC по умолчанию в зависимости от цели. Это 32 бит длиной здесь. Обратите внимание, что wchar_t (тип широких символов) не имеет ничего общего с юникодом. Просто гарантируется, что он может хранить все члены самого большого набора символов, поддерживаемого реализацией его локалями, и, по крайней мере, столько же, сколько и char. Вы можете хранить строки Unicode в точности в std::string, используя также кодировку utf-8. Но он не поймет значения кодовых точек юникода. Поэтому str.size() не даст вам количество логических символов в вашей строке, а просто количество элементов char или wchar_t, хранящихся в этой строке / wstring. По этой причине разработчики gtk / glib C ++ разработали класс Glib::ustring, который может обрабатывать utf-8.

    Если ваш wchar_t имеет длину 32 бита, то вы можете использовать utf-32 в качестве кодировки Unicode, и вы можете хранить и строки обработки Unicode, используя фиксированные (utf-32 фиксированная длина) кодирование. Это означает, что функция s.size() вашей wstring будет , затем вернет нужное количество логических символов элементов wchar_t и .

  2. Да, char всегда имеет длину не менее 8 бит, что означает, что он может хранить все значения ASCII.
  3. Да, все основные компиляторы поддерживают его.
5 голосов
/ 31 декабря 2008

Я часто использую std :: string для хранения символов utf-8 без каких-либо проблем. Я от всей души рекомендую делать это при взаимодействии с API, которые также используют utf-8 как собственный тип строки.

Например, я использую utf-8 при взаимодействии моего кода с интерпретатором Tcl.

Главным предупреждением является длина std :: string, больше не количество символов в строке.

3 голосов
/ 31 декабря 2008
  1. Когда вы хотите сохранить символы 'широкие' (Unicode).
  2. Да: 255 из них (исключая 0).
  3. Да.
  4. Вот вступительная статья: http://www.joelonsoftware.com/articles/Unicode.html
2 голосов
/ 11 сентября 2011

Приложения, которые не удовлетворены только 256 различными символами, могут либо использовать широкие символы (более 8 бит), либо кодирование переменной длины (многобайтовое кодирование в терминологии C ++), например UTF-8. Широкие символы обычно требуют больше места, чем кодирование переменной длины, но быстрее обрабатываются. Многоязычные приложения, которые обрабатывают большие объемы текста, обычно используют широкие символы при обработке текста, но преобразуют его в UTF-8 при сохранении его на диск.

Единственная разница между string и wstring - это тип данных символов, которые они хранят. В строке хранится char s, размер которого гарантированно должен быть не менее 8 битов, поэтому вы можете использовать строки для обработки, например. ASCII, ISO-8859-15 или UTF-8 текст. Стандарт ничего не говорит о наборе символов или кодировке.

Практически каждый компилятор использует набор символов, первые 128 символов которого соответствуют ASCII. Это также относится и к компиляторам, использующим кодировку UTF-8. При использовании строк в UTF-8 или некоторых других кодировках переменной длины важно помнить, что индексы и длины измеряются в байтах, а не в символах.

Тип данных wstring - wchar_t, размер которого не определен в стандарте, за исключением того, что он должен быть по крайней мере таким же большим, как символ, обычно 16 бит или 32 бита. wstring может использоваться для обработки текста при реализации определенной кодировки широких символов. Поскольку кодировка не определена в стандарте, преобразование между строками и строками не является простым. Нельзя допустить, чтобы у wstrings была кодировка фиксированной длины.

Если вам не нужна многоязычная поддержка, вы можете использовать только обычные строки. С другой стороны, если вы пишете графическое приложение, часто бывает так, что API поддерживает только широкие символы. Тогда вы, вероятно, захотите использовать те же широкие символы при обработке текста. Имейте в виду, что UTF-16 - это кодировка переменной длины, что означает, что вы не можете предполагать, что length() вернет количество символов. Если API использует кодировку фиксированной длины, такую ​​как UCS-2, обработка становится легкой. Преобразование между широкими символами и UTF-8 трудно сделать переносимым способом, но, опять же, API вашего пользовательского интерфейса, вероятно, поддерживает преобразование.

1 голос
/ 31 декабря 2008
  1. когда вы хотите использовать строки Unicode, а не просто ascii, полезно для интернационализации
  2. да, но это не очень хорошо с 0
  3. не знает ничего, что не
  4. широкий символ - это специфический для компилятора способ обработки представления фиксированной длины символа юникода, для MSVC это 2-байтовый символ, для gcc я понимаю, что это 4 байта. и +1 для http://www.joelonsoftware.com/articles/Unicode.html
0 голосов
/ 17 августа 2018

Здесь есть несколько очень хороших ответов, но я думаю, что есть несколько вещей, которые я могу добавить в отношении Windows / Visual Studio. Это основано на моем опыте с VS2015. В Linux, в основном, ответ - везде использовать кодировку UTF-8 std::string. На Windows / VS это становится более сложным. Вот почему. Windows ожидает, что строки, хранящиеся с использованием char s, будут закодированы с использованием кодовой страницы локали. Это почти всегда набор символов ASCII, за которым следуют 128 других специальных символов в зависимости от вашего местоположения. Позвольте мне просто заявить, что это не только при использовании Windows API, есть три других основных места, где эти строки взаимодействуют со стандартным C ++. Это строковые литералы, выводимые в std::cout с использованием << и передачей имени файла в std::fstream.

Я буду прямо здесь, потому что я программист, а не специалист по языку. Я ценю, что USC2 и UTF-16 не совпадают, но для моих целей они достаточно близки, чтобы быть взаимозаменяемыми, и я использую их здесь как таковые. Я на самом деле не уверен, какая Windows использует, но мне, как правило, тоже не нужно знать. Я указал UCS2 в этом ответе, поэтому извините заранее, если я кого-то расстроил своим незнанием этого вопроса, и я рад изменить его, если у меня что-то не так.

Строковые литералы

Если вы вводите строковые литералы, которые содержат только символы, которые могут быть представлены вашей кодовой страницей, VS сохраняет их в вашем файле по 1 байту на кодировку символов на основе вашей кодовой страницы. Обратите внимание, что если вы измените свою кодовую страницу или передадите свой источник другому разработчику, используя другую кодовую страницу, то я думаю (но не проверял), что символ в конечном итоге будет другим. Если вы запустите свой код на компьютере, используя другую кодовую страницу, тогда я не уверен, что этот символ тоже изменится.

Если вы введете какие-либо строковые литералы, которые не могут быть представлены вашей кодовой страницей, VS попросит вас сохранить файл как Unicode. Файл будет закодирован как UTF-8. Это означает, что все символы не ASCII (включая те, которые находятся на вашей кодовой странице) будут представлены 2 или более байтами. Это означает, что если вы передадите свой источник кому-то другому, источник будет выглядеть так же. Однако перед передачей исходного кода компилятору VS преобразует кодированный в кодировке UTF-8 текст в кодированный код, и любые символы, отсутствующие в кодовой странице, заменяются на ?.

Единственный способ гарантировать правильное представление строкового литерала Unicode в VS - это предшествовать строковому литералу L, что делает его широким строковым литералом. В этом случае VS преобразует кодированный в UTF-8 текст из файла в UCS2. Затем вам нужно передать этот строковый литерал в конструктор std::wstring, или вам нужно преобразовать его в utf-8 и поместить в std::string. Или, если вы хотите, вы можете использовать функции Windows API для кодирования, используя кодовую страницу, чтобы поместить его в std::string, но тогда вы, возможно, также не использовали широкий строковый литерал.

станд :: соиЬ

При выводе на консоль с использованием << вы можете использовать только std::string, а не std::wstring, и текст должен быть закодирован с использованием вашей кодовой страницы локали. Если у вас есть std::wstring, то вы должны конвертировать его, используя одну из функций API Windows, и любые символы, отсутствующие на вашей кодовой странице, заменяются на ? (возможно, вы можете изменить символ, я не помню).

std :: fstream filenames

ОС Windows использует имена файлов UCS2 / UTF-16, поэтому независимо от вашей кодовой страницы вы можете иметь файлы с любым символом Unicode. Но это означает, что для доступа или создания файлов с символами, которые не находятся на вашей кодовой странице, вы должны использовать std::wstring. Другого пути нет. Это специфичное для Microsoft расширение std::fstream, поэтому, вероятно, не будет компилироваться в других системах. Если вы используете std :: string, то вы можете использовать только те имена файлов, которые содержат только символы на вашей кодовой странице.

Ваши варианты

Если вы просто работаете над Linux, вы, вероятно, не зашли так далеко. Просто используйте UTF-8 std::string везде.

Если вы просто работаете в Windows, просто используйте UCS2 std::wstring везде. Некоторые пуристы могут сказать, что используют UTF8, а затем конвертируют, когда это необходимо, но зачем беспокоиться?

Если вы кроссплатформенный, то это откровенный беспорядок. Если вы пытаетесь использовать UTF-8 повсюду в Windows, вам нужно быть очень осторожным с строковыми литералами и выводом на консоль. Вы можете легко повредить свои строки там. Если вы используете std::wstring повсюду в Linux, то у вас может не быть доступа к широкой версии std::fstream, поэтому вам придется выполнять конвертацию, но нет риска повреждения. Так что лично я думаю, что это лучший вариант. Многие могут не согласиться, но я не одинок - это путь, выбранный, например, wxWidgets.

Другой вариант может заключаться в том, чтобы ввестиdef unicodestring как std::string в Linux и std::wstring в Windows, и иметь макрос UNI (), который префикс L в Windows и ничего в Linux, а затем код

#include <fstream>
#include <string>
#include <iostream>
#include <Windows.h>

#ifdef _WIN32
typedef std::wstring unicodestring;
#define UNI(text) L ## text
std::string formatForConsole(const unicodestring &str)
{
    std::string result;
    //Call WideCharToMultiByte to do the conversion
    return result;
}
#else
typedef std::string unicodestring;
#define UNI(text) text
std::string formatForConsole(const unicodestring &str)
{
    return str;
}
#endif

int main()
{

    unicodestring fileName(UNI("fileName"));
    std::ofstream fout;
    fout.open(fileName);
    std::cout << formatForConsole(fileName) << std::endl;
    return 0;
}

было бы хорошо на любой платформе, я думаю.

Ответы

Итак, чтобы ответить на ваши вопросы

1) Если вы программируете для Windows, то все время, если кроссплатформенное, то, возможно, все время, если вы не хотите иметь дело с возможными проблемами повреждения в Windows или пишете код с платформой #ifdefs для обхода различия, если просто использовать Linux, то никогда.

2) Да. В дополнение к Linux вы можете использовать его для всех Unicode тоже. В Windows вы можете использовать его только для всех Unicode, если вы решите вручную кодировать с использованием UTF-8. Но Windows API и стандартные классы C ++ будут ожидать, что код std::string будет закодирован с использованием кодовой страницы локали. Сюда входят все ASCII плюс еще 128 символов, которые меняются в зависимости от кодовой страницы, которую ваш компьютер настроил для использования.

3) Я верю в это, но если нет, то это просто определение типа std :: basic_string с использованием wchar_t вместо char

4) Широкий символ - это тип символа, который больше, чем 1-байтовый стандартный тип char. В Windows это 2 байта, в Linux это 4 байта.

0 голосов
/ 29 октября 2013

Хороший вопрос! Я думаю, КОДИРОВАНИЕ ДАННЫХ (иногда CHARSET также используется) - MEMORY EXPRESSION МЕХАНИЗМ для сохранения данных в файл или передачи данных по сети, поэтому Я отвечаю на этот вопрос как:

1. Когда мне следует использовать std :: wstring вместо std :: string?

Если программная платформа или функция API является однобайтовой, и мы хотим обработать или проанализировать некоторые данные Unicode, например, прочитать из файла Windows.REG или 2-байтового сетевого потока, мы должны объявить std :: wstring переменная, чтобы легко обрабатывать их. Например: wstring ws = L "中国 a" (память 6 октетов: 0x4E2D 0x56FD 0x0061), мы можем использовать ws [0] для получения символа '中' и ws [1] для получения символа '国' и ws [2] для получить символ «а» и т. д.

2. Может ли std :: string содержать весь набор символов ASCII, включая специальные символы?

Да. Но обратите внимание: американский ASCII означает, что каждый октет 0x00 ~ 0xFF обозначает один символ, включая печатный текст, такой как «123abc & * _ &», и вы сказали специальный, в основном напечатайте его как '.' Избегайте путаницы в редакторах или терминалах. А некоторые другие страны расширяют свою собственную кодировку "ASCII", например Китайский, используйте 2 октета для обозначения одного символа.

3.Поддерживается ли std :: wstring всеми популярными компиляторами C ++?

Может быть, или в основном. Я использовал: VC ++ 6 и GCC 3.3, ДА

4. Что такое «широкий символ»?

широкий символ в основном указывает на использование 2 или 4 октетов для хранения символов всех стран. 2 октета UCS2 является репрезентативной выборкой и, например, Английский «а», его память составляет 2 октета 0x0061 (по сравнению с ASCII в памяти «а» 1 октет 0x61)

...