• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Błędne kodowanie znaków w konsoli

VPS Starter Arubacloud
+1 głos
763 wizyt
pytanie zadane 24 czerwca 2020 w C i C++ przez Marcinuq Użytkownik (640 p.)
edycja 24 czerwca 2020 przez Marcinuq
Witam!

Mam problem z kodowaniem znaków. Gdy chcę zapisać informację do pliku tekstowego.

fstream plik(nazwa.txt);

pojawia się w prawym dolnym rogu informacja:

The saved document contained characters which were illegal in the selected encoding. The file's encoding has been changed to UTF-8 to prevent you from losing data.

I w konsoli pojawiają się krzaczki mimo tego że w funkcji main() mam zapisane:

setlocale(LC_ALL,"")

problem ten nie występuje w momencie gdy danych nie zapisuje do pliku czyli linijkę otwierającą plik tekstowy biorę w komentarz.

Chciałbym dowiedzieć się co zrobić aby krzaczki te nie pojawiały się w konsoli.
komentarz 24 czerwca 2020 przez j23 Mędrzec (194,920 p.)
Jaki system?
komentarz 25 czerwca 2020 przez Marcinuq Użytkownik (640 p.)
Windows 10. Używam CodeBlocks

1 odpowiedź

+4 głosów
odpowiedź 25 czerwca 2020 przez j23 Mędrzec (194,920 p.)
wybrane 25 czerwca 2020 przez Marcinuq
 
Najlepsza

Co do komunikatu. Zapewne w pliku źródłowym zawarte są znaki, których nie ma w domyślnym kodowaniu ANSI, np. cyrylica w polskim kodowaniu Window-1250. Generalnie pliki źródłowe powinny być zapisywane w utf-8.

Co do krzaków: w Windowsie sprawa jest zagmatwana, bo konsola ze względów historycznych używa kodowania OEM, system - kodowania ANSI, chociaż tak na prawdę jest w pełni unikodowy.

W skrócie (dla wersji PL):

  • konsola: CP852
  • system: Windows-1250

Kompilując program wszystkie literały mają kodowanie takie, jak plik źródłowy, który je zawiera. Jeśli plik jest unikodowy - zamieniane są na kodowanie ANSI (1250). Jak łatwo się domyśleć, podawanie konsoli, która oczekuje kodowania OEM, znaków w kodowaniu ANSI skończy się niepoprawnym wyświetlaniem napisów.

Jednym z rozwiązań jest wymuszenie na kompilatorze użycia kodowania OEM. W MinGW można to zrobić parametrem -fexec-charset=cp852. Ważne, by zapisać pliki źródłowe w utf-8 z BOM-em. Minusem tego rozwiązania jest to, że wszystkie pliki tekstowe stworzone w systemie najprawdopodobniej będą w kodowaniu ANSI. Musisz o tym pamiętać.

Inne rozwiązanie to pisanie aplikacji w unikodzie z użyciem znaków szerokich i unikodowych odpowiedników strumieni - std::wcin, std::wcout, std::wifstream itd.

komentarz 25 czerwca 2020 przez Marcinuq Użytkownik (640 p.)

Dziękuję wstawiłem -fexec-charset=cp852 w opcje kompilatora i zmieniłem kodowanie pliku tekstowego na UTF-8 z Bomem, i faktycznie działa. Tylko chcę dowiedzieć się w jaki sposób mogę jeszcze zrobić coś takiego że jak wpisuje tekst z polskimi znakami do konsoli to wyświetla się ten tekst z polskimi znakami w konsoli i jeszcze potem w pliku tekstowym, a nie tekst z zamienionymi polskimi znakami na inne. Czyli np,widzę coś takiego: Ąľ«┼?˘c , a chcę widzieć ten ciąg znaków: ąćżźłóę.

komentarz 25 czerwca 2020 przez j23 Mędrzec (194,920 p.)
Chyba nie rozumiem, o co pytasz. Jeśli do pliku zapisujesz tekst pobrany z konsoli, to ten plik będzie miał kodowanie OEM, a taki np. notatnik będzie oczekiwać ANSI, dlatego źle się to wyświetla (z reguły wystarczy przełączyć kodowanie na DOS czy coś w tym stylu).

Niestety w standardowej bibliotece nie ma funkcji umożliwiającej transkodowanie ANSI -> ANSI. Możliwe jest jedynie ANSI <-> unikod.

Mało elegancki sposób, ale działający, to napisać sobie funkcję zamieniającą kody znaków diaktrytycznych. Poszukaj na forum, bo były takie funkcje tutaj.
komentarz 25 czerwca 2020 przez Marcinuq Użytkownik (640 p.)

 Poszukam tych funkcji na forum. Dziękuje bardzo za pomocsmiley.

komentarz 25 czerwca 2020 przez j23 Mędrzec (194,920 p.)
Jutro może podam inne rozwiązanie, nieco wygodniejsze.
komentarz 25 czerwca 2020 przez Marcinuq Użytkownik (640 p.)

OK :) yes

komentarz 26 czerwca 2020 przez j23 Mędrzec (194,920 p.)

Jednak nie podam innego rozwiązania. Chciałem zrobić klasę pochodną od std::codecvt<char, char> tak, by można było kulturalnie używać strumieni std::cin i std::cout. Z jakichś powodów bufor strumienia, który jest  pochodną od std::basic_filebuf, nie widzi klasy konwertującej.

Może jest jakiś mag, który wytłumaczy mi, dlaczego tak się dzieje.

komentarz 19 kwietnia 2022 przez PolskiArrow Nowicjusz (120 p.)

@j23, Mam pytanie dotyczące tego całego "-fexec-charset=cp852". Gdzie ja mam to wpisać? "W MinGW", czyli gdzie?

Mam zainstalowany kompilator i pracuję na nim w VS Code. To gdzieś w ustawieniach środowiska mam znaleźć, czy jak?

komentarz 19 kwietnia 2022 przez j23 Mędrzec (194,920 p.)
Tak, w ustawieniach środowiska/projektu, w opcjach kompilatora

Nie powiem Ci szczegółowo gdzie to zrobić, bo nie wiem, jak to wygląda w VSC, jaki jest tam build system.

Podobne pytania

+1 głos
2 odpowiedzi 1,116 wizyt
pytanie zadane 8 sierpnia 2016 w Java przez niezalogowany
0 głosów
2 odpowiedzi 4,165 wizyt
pytanie zadane 21 marca 2018 w Grafika i multimedia przez xxkondzioxx15 Obywatel (1,440 p.)
+1 głos
1 odpowiedź 2,732 wizyt
pytanie zadane 21 czerwca 2016 w C i C++ przez gagyn Stary wyjadacz (11,050 p.)

92,452 zapytań

141,262 odpowiedzi

319,080 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...