Как распечатать wstring в Linux / OS X? - PullRequest
5 голосов
/ 23 июля 2011

Как я могу напечатать такую ​​строку: €áa¢cée£ на консоли / экране? Я попробовал это:

#include <iostream>    
#include <string>
using namespace std;

wstring wStr = L"€áa¢cée£";

int main (void)
{
    wcout << wStr << " : " << wStr.length() << endl;
    return 0;
}

который не работает. Даже сбивает с толку, если я удаляю из строки, распечатка получается так: ?a?c?e? : 7, но с в строке ничего не печатается после символа .

Если я напишу тот же код на python:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

wStr = u"€áa¢cée£"
print u"%s" % wStr

правильно выводит строку на той же консоли. Чего мне не хватает в c ++ (ну, я просто нуб)? Ура !!


Обновление 1: по предложению n.m.
#include <iostream>
#include <string>
using namespace std;

string wStr = "€áa¢cée£";
char *pStr = 0;

int main (void)
{
    cout << wStr << " : " << wStr.length() << endl;

    pStr = &wStr[0];
    for (unsigned int i = 0; i < wStr.length(); i++) {
        cout << "char "<< i+1 << " # " << *pStr << " => " << pStr << endl;
        pStr++;
    }
    return 0;
}

Прежде всего, он сообщает 14 как длину строки: €áa¢cée£ : 14 Это потому, что он считает 2 байта на символ?

И все, что я получаю это:

char 1 # ? => €áa¢cée£
char 2 # ? => ??áa¢cée£
char 3 # ? => ?áa¢cée£
char 4 # ? => áa¢cée£
char 5 # ? => ?a¢cée£
char 6 # a => a¢cée£
char 7 # ? => ¢cée£
char 8 # ? => ?cée£
char 9 # c => cée£
char 10 # ? => ée£
char 11 # ? => ?e£
char 12 # e => e£
char 13 # ? => £
char 14 # ? => ?

как последний вывод cout. Таким образом, актуальная проблема все еще остается, я считаю. Ура !!


Обновление 2: на основании второго предложения по номеру

#include <iostream>
#include <string>

using namespace std;

wchar_t wStr[] = L"€áa¢cée£";
int iStr = sizeof(wStr) / sizeof(wStr[0]);        // length of the string
wchar_t *pStr = 0;

int main (void)
{
    setlocale (LC_ALL,"");
    wcout << wStr << " : " << iStr << endl;

    pStr = &wStr[0];
    for (int i = 0; i < iStr; i++) {
       wcout << *pStr << " => " <<  static_cast<void*>(pStr) << " => " << pStr << endl;
       pStr++;
    }
    return 0;
}

И вот что я получаю в результате:

€áa¢cée£ : 9
€ => 0x1000010e8 => €áa¢cée£
á => 0x1000010ec => áa¢cée£
a => 0x1000010f0 => a¢cée£
¢ => 0x1000010f4 => ¢cée£
c => 0x1000010f8 => cée£
é => 0x1000010fc => ée£
e => 0x100001100 => e£
£ => 0x100001104 => £
 => 0x100001108 => 

Почему там сообщается как 9, чем 8? Или это то, что я должен ожидать? Ура !!

1 Ответ

7 голосов
/ 23 июля 2011

Бросьте L перед строковым литералом.Используйте std::string, а не std::wstring.

UPD: есть лучшее (правильное) решение.оставьте wchar_t, wstring и L, и в начале вашей программы вызовите setlocale(LC_ALL,"").

В любом случае вам следует вызвать setlocale(LC_ALL,"") в начале вашей программы.Это указывает вашей программе работать с языковым стандартом вашей среды вместо стандартного языкового стандарта «C».В вашей среде есть UTF-8, поэтому все должно работать.

Без вызова setlocale(LC_ALL,"") программа работает с последовательностями UTF-8, не "понимая", что они являются UTF-8.Если на терминале напечатана правильная последовательность UTF-8, она будет интерпретироваться как UTF-8, и все будет выглядеть хорошо.Вот что происходит, если вы используете string и char: gcc использует UTF-8 в качестве кодировки по умолчанию для строк, и ostream с радостью печатает их без применения какого-либо преобразования.Он думает, что имеет последовательность символов ASCII.

Но когда вы используете wchar_t, все ломается: gcc использует UTF-32, правильная перекодировка не применяется (потому что локаль - "C"), а вывод - мусор.

Когда вы звоните setlocale(LC_ALL,""), программа знает, что она должна перекодировать UTF-32 в UTF-8, и все в порядке и снова модно.

Все это предполагает, что мы когда-либо хотим работать только с UTF-8,Использование произвольных локалей и кодировок выходит за рамки этого ответа.

...