setlocale i cin.imbue(locale("")) gryzą się

0

Dzień dobry.

Próbuję ustawić prawidłowe kodowanie znaków, zarówno, dla stringów stałych, wpisanych w kodzie programu, jak i dla tekstów wpisywanych z konsoli. Ale kicha, albo rybka, albo p... Jak działa jedno to drugie nie działa, i na odwrót.

#include <iostream>
#include <locale>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

int main()
{
	using namespace std;
	
	setlocale(LC_ALL, "");
	// cin.imbue(locale(""));
	
	vector<string> v = {"ąę", "bb"};
	sort(v.begin(), v.end(), locale(""));
	copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
	
	string str;
	getline(cin, str);
	cout << str;
	
	return 0;
}

Zmieniłem stronę kodową pliku na ascii (w Notepadzie++) i po odsłonieniu setlocale, a zasłonieniu cin.imbue treść vector'a wyświetla i sortuje się prawidłowo. Jednak tekst wpisany z klawiatury nie wyświetla polskich znaków. Jak odwrócę komentarz i przysłonię setlocale a odsłonię cin.imbue to z kolei vector nie ma polskich znaków, a tekst z klawiatury ma. Czy da się to jakoś pogodzić?

Dzieki
Michał

1

Spróbuj użyć biblioteki utf8.h http://utfcpp.sourceforge.net/ do konwersji stringu str na kodowanie utf8.
Jeżeli to nie zadziała i nie będziesz miał już żadnych pomysłów to możesz napisać własną funkcję dekodującą:

string decode( const string& str )
{
    string str_decode {""};
    for( const char& c : str )
    {
        if( c == 'krzak1' ) str_decode += 'ą' ;
        else if( c == 'krzak2' ) str_decode += 'ć' ;
        else if( c == 'krzak3' ) str_decode += 'ę' ;
        ...
        ...
        else str_decode += c;
    }
   return  str_decode;
}

Pamiętaj tylko że taka funkcja może nie zadziałać na innym systemie. Jeżeli istnieje taka możliwość to powinniśmy unikać używania polskich znaków w konsoli.

0

std::setlocale - cppreference.com

Defined in header [<clocale>](https://en.cppreference.com/w/cpp/header/clocale "cpp/header/clocale")

char* setlocale( int category, const char* locale);

The setlocale function installs the specified system locale or its portion as the new C locale. The modifications remain in effect and influences the execution of all locale-sensitive C library functions until the next call to setlocale. If locale is a null pointer, setlocale queries the current C locale without modifying it.

Czyli std::setlocale ma wpływ jedynie na API z C, a std::cin się do tego nie kwalifikuje.
Powinno być tak:

int main()
{
    using namespace std;

    locale::global(std::locale(""));

    vector<string> v = {"ąę", "bb"};
    sort(v.begin(), v.end(), locale());
    copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));

    string str;
    getline(cin, str);
    cout << str;

    return 0;
}

Twój kod nie działał bo ustawiłeś locale tylko na cin a na cout nie, wiec wejscie i wyjscie nie było konsystentne.

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