[gcc] coś dziwnego z wchar_t (UTF8) pod FreeBSD

0

Witam

Napisałem taki oto programik testowy:

//---POCZĄTEK PROGRAMU--------
#include <string>
#include <iostream>

int main()
{
	
	std::wcout<<std::endl<<std::endl;
	std::wcout<<L"Podaj to co chcesz wyswietlic: ";
	std::wstring wtmp;
	std::getline(std::wcin, wtmp);
	std::wcout<<wtmp<<std::endl;	
	std::wcout<<L"Dlugosc podanego przez Ciebie napisu to: "<<wtmp.size()<<std::endl<<std::endl;
	
	std::string napis = "ąęść";
	std::cout<<"Napis: "<<napis<<std::endl;
	std::cout<<"Długość: "<<napis.size()<<std::endl;
	for (std::string::size_type i = 0; i < napis.size(); i++)
	{
		int hex = static_cast<unsigned char>(napis[i]);
		std::cout<<std::hex<<hex<<" ";
	}
	
	std::cout<<std::endl<<std::endl;
	std::cout<<"Podaj \"ąęść\": ";
	std::cin>>napis;
	std::cout<<"Napis: "<<napis<<std::endl;
	std::cout<<"Długość: "<<napis.size()<<std::endl;
	for (std::string::size_type i = 0; i < napis.size(); i++)
	{
		int hex = static_cast<unsigned char>(napis[i]);
		std::cout<<std::hex<<hex<<" ";
	}
	
	std::cout<<std::endl<<std::endl;
	std::wstring wnapis = L"ąęść";
	std::cout<<"Napis: ";
	std::wcout<<wnapis;
	std::cout<<std::endl;
	std::cout<<"Dlugosc: "<<wnapis.size()<<std::endl;
	for (std::string::size_type i = 0; i < napis.size(); i++)
	{
		std::cout<<std::hex<<wnapis[i]<<" ";
	}
	
	std::cout<<std::endl<<std::endl;
	std::cout<<"Podaj \"ąęść\": ";
	std::wcin>>wnapis;
	std::cout<<"Napis: ";
	std::wcout<<wnapis;
	std::cout<<std::endl;
	std::cout<<"Dlugosc: "<<wnapis.size()<<std::endl;
	for (std::string::size_type i = 0; i < napis.size(); i++)
	{
		std::cout<<std::hex<<wnapis[i]<<" ";
	}
	
	std::cout<<std::endl;
	std::wcout<<std::endl<<std::endl;
	
	return 0;
}
//-----KONIEC PROGRAMU---------

W wyniku otrzymałem:

//-------WYNIK--------
> g++ -Wall -o main main.cc && ./main


Podaj to co chcesz wyswietlic: kośćią
kośćią
Dlugosc podanego przez Ciebie napisu to: 9

Napis: ąęść
Długość: 8
c4 85 c4 99 c5 9b c4 87 

Podaj "ąęść": ąęść
Napis: ąęść
Długość: 8
c4 85 c4 99 c5 9b c4 87 

Napis: 
Dlugosc: 4
105 119 15b 107

Podaj "ąęść": ąęść
Napis: 
Dlugosc: 8
c4 85 c4 99 c5 9b c4 87 
> 
//-----KONIEC WYNIKU---------

I teraz gorąca prośba... Niech ktoś mi powie o co tu chodzi....:|:|

Dodam, że lokalizacja jest ustawiona na UTF-8 (FreeBSD), plik źródłowy jest w UTF-8 (z tego co wiem kompilator pobiera zmienne z lokalizacji (np. LC_ALL) żeby okreslić w jakim kodowaniu mają być stringi w programie (binarce, execu).
W związku z tym w ogóle nie rozumiem o co w tym chodzi:/

0

Wygląda na to, że standardowe strumienie nie zapewniają konwersji wchar_t <=> UTF-8.

Przy wczytywaniu łańcucha fragmenty sekwencji dwubajtowych zostały potraktowane każda jak osobny znak (każdy ładnie rozszerzony do 16 bitów zerami) a przy wypisywaniu to w ogóle był kosmos.

Mógłbyś spróbować dwóch rzeczy: a) odpalić programik na terminalu obsługujących 16bitowe znaki z odpowiedni innymi locale b) odpuścić sobie wchar_t i jego ciemne sprawki i łańcuchy trzymać i przetwarzać z normalnym char, pamiętając tylko, że zawierają dane w UTF-8 (gcc nie ingeruje w treść łańcuchów, więc jeżeli używasz edytora z UTF-8 wszystko powinno być OK), masz tylko ten minus wtedy, że liczba znaków najczęściej nie jest równa liczbie literek wypisanych na terminalu.

0

hm.. wchar_t jest zawsze 2xchar, wiec to by sugerowalo wspolprace ze utf16 (o stalej szerokosci) raczej niz z utf8 (multibyte) :|

0

A to w ogóle jest określony rozmiar wchar_t? Z tego co czytałem to jest tylko zapewnione tyle (;) ), że mieści się w tym największy obsługiwany znak we wszystkich kodowaniach wspieranych przez system. Szczerze przyznam, że napisy w c++ mnie irytują...

0

hm.. szczerze, nie pamietam. na platformach na ktorych siedzialem dotad, byl to zawsze 2x char

0

U mnie ma 4 bajty.

0

napisy w c++ są jako takie, ale w Visual Studio, gdzie jest naprawdę ładne wsparcie dla unicode. w gcc to jest masakra, jak już muszę użyć unicode w gcc, to mam generalnie 3 zasady:

  1. nie używam literałów L"hello", bo na pewno coś się wywali
  2. jak tylko mogę, do obsługi tekstu używam bibliotek third-party
  3. jeśli jestem pod windows, to korzystam z WinAPI i dziękuję Bogu, za to, że istnieje microsoft ;)
0
Ranides napisał(a)
  1. nie używam literałów L"hello", bo na pewno coś się wywali

e bez przesady ;) dopóki nie ma znaków o wartościach ponad 127 jest ok, no chyba, że są to rzeczywiście jest "masakra"

0

Co do wchar_t jest ponoć taka zasada, że musi on być w stanie zachować kod każdego unikodowego znaku. wchat_t dwubajtowy de facto nie jest w stanie tego zrobić, wszak UTF-16 jest kodowaniem maksymalnie 4 bajtowym. Na platformach windowsowych typ ten jest dwubajtowy, być może dlatego, że pierwsze unikodowe API obsługiwało tylko UCS-2 (na sztywno 2 bajty).

1 użytkowników online, w tym zalogowanych: 0, gości: 1