Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Biblioteki łatające dziury standardu C++

Ostatnio zmodyfikowano 2018-04-09 00:32
Autor Wiadomość
jankowalski25
» 2018-04-08 13:02:36
A co toupper zwraca dla '4'?
Bardziej chodziło mi o to, że można trafić na implementacje, które ustawiają jakieś flagi błędów lub rzucają wyjątki, gdy czegoś nie uda się zrobić. Oczywiście w przypadku toupper najlepiej byłoby zwracać taki sam znak, ale nie zawsze jest to możliwe. Jeśli chodzi o standardową wersję tej funkcji, to za jednym razem można zwrócić pojedynczy bajt, więc należałoby wywołać taką funkcję kilka razy (oddzielnie dla każdego bajtu) i jednocześnie zadbać o to, aby kolejne wyniki pośrednie dały łącznie odpowiedni znak w danym kodowaniu, przy określonych ustawieniach lokalnych i jeszcze aby to było bezpieczne wielowątkowo. Zrobienie czegoś takiego prawidłowo może być niewykonalne lub wymagać rzucania wyjątków, więc czasami lepiej po prostu użyć czegoś innego lub solidnie obłożyć to testami (albo po prostu nie wywoływać takich funkcji na problematycznych znakach nakładając ograniczenia na dane wejściowe).

Wsparcie standardu dla unicode:
Drobna uwaga techniczna: do wypunktowania można używać znaczników [pkt][/pkt] zamiast myślników.

zwracają liczbę elementów w tablicy a nie ilość znaków
Jak już wspomniałem, to zależy od tego, co chcesz zrobić. Zapisując coś do pliku potrzebujesz ilości bajtów, a nie znaków Unikodowych.

metody find, find_first_of itd nie mają pojęcia, że niektóre znaki mogą być zakodowane na więcej niż 1 code pointcie, więc praktycznie rzecz biorąc - nie działają poprawnie
Jeśli znak jest poprawnie zakodowany w UTF-8, to nie da się zapisać tego samego znaku na dwa sposoby. Używaj metod działających na napisach wszędzie, gdzie korzystasz z Unikodowych znaków (i tak musisz mieć jakąś zmienną o rozmiarze większym niż jeden bajt, aby zrobić to prawidłowo). Z jednobajtowych wersji korzystaj wewnętrznie do trywialnych działań lub nie używaj ich wcale.

nie ma std::u16cout ani std::u32cout, mimo że jest, zależny od platformy, std::wcout. To samo z std::cin.
nie ma std::u16fstream ani std::u32fstream
nie ma żadnego identyfikatora dla std::stringa, że przechowuje UTF-8 a nie ASCII
Do czego potrzebujesz czegoś takiego? Jeśli
char *
 albo
wchar_t *
 zawiera odpowiednie bajty, to całość będzie właściwie wyświetlona. Podaj przykład, w którym to nie działa zgodnie z oczekiwaniami i nie wynika na przykład z błędnie ustawionego kodowania znaków w Twoim IDE.

Przed C++17, z tego co wiem, korzystając z <fstream> nie było możliwości otworzenia plików o ścieżce zakodowanej inaczej niż w ASCII.
To już zależy od implementacji, ja jakoś nie miałem z tym większych problemów. A skoro teraz masz do dyspozycji nowości z C++17, to z nich korzystaj, o ile jest to możliwe. Zresztą, w najprostszych przypadkach wystarczy ograniczyć się do jednobajtowych znaków, a w tych bardziej skomplikowanych i tak pewnie zajdzie potrzeba jakiejś obsługi systemu plików, możliwość zarządzania folderami, obsługa skrótów (czy tam symlinków), więc i tak zaczniesz szukać do tego oddzielnej biblioteki, która zapewne będzie udostępniała coś lepszego niż narzędzia z
#include <fstream>
.

nie istnieją utfXiteratory, które pozwalałyby sprawnie iterować po kolejnych znakach. Trzeba pisać to samemu
Albo szukać biblioteki, która umie robić takie rzeczy. Chociaż, jeśli korzystasz z UTF-8, to ten format jest na tyle regularny, że policzenie liczby znaków Unicode (w takim znaczeniu, w jakim wynik jest równy liczbie znaków zapisanych w UTF-32) nie powinno stanowić większego problemu. A jeśli chcesz na przykład traktować znak i akcent jako jeden znak, to i tak trzeba zagłębić się w złożoność Unikodu, więc przyda się do tego oddzielna biblioteka. Chociaż i tak jeśli chcesz to zrobić na jakimś skończonym podzbiorze Unikodu, to te tablice znaków są na tyle regularnie rozłożone, że pewnie da się to jakoś prosto zapisać.

locale są biedne
O tym już chyba wspominałem. Nie ruszaj ich, jeśli jest to możliwe.

To nie jest wsparcie.
Dlatego moim zdaniem najrozsądniejszym podejściem jest ograniczenie się do jakiegoś prostego, działającego kodu i stopniowe rozszerzanie tego w miarę potrzeb. Osobiście przy pisaniu własnych programów zwykle dochodziłem do wniosku, że wystarczy wspierać jakiś niewielki podzbiór Unikodu, a resztę dodawać wtedy, gdy okaże się to konieczne.

jeśli miałbyś napisać sprawnie działający edytor tekstu, to jakich bibliotek byś użył?
SFML, RapidXML, trochę biblioteki standardowej i parę własnych narzędzi. Chociaż niewykluczone, że może coś z SFGUI albo wxWidgets by się przydało... Ewentualnie jakiś podzbiór WinAPI, gdyby to miało być tylko pod Windowsa i koniecznie musiało być napisane w C++. SFML spokojnie poradzi sobie z czcionkami, RapidXML może się przydać do serializacji oraz do wspierania plików XML, SFGUI albo wxWidgets załatwi potrzebne kontrolki, a WinAPI obejmuje Windowsa i zawiera z grubsza to, co potrzeba, aby się do niego dopasować.

czy wyciągnąłbyś tylko jego kawałek i umieszczał na repozytorium razem z nim czy raczej korzystał z całości i do repo trafiłaby tylko informacja "dołącz boosta w wersji takiej i takiej"
Linkowałbym statycznie tam, gdzie się da i dynamicznie tam, gdzie muszę (bo na przykład licencja tego wymaga). Przy okazji trzeba byłoby jeszcze sprawdzić, czy licencje wszystkich bibliotek się ze sobą nie gryzą i jakoś to rozsądnie poustawiać.
P-170536
DejaVu
» 2018-04-08 14:03:34
@RazzorFlame: Strzelam, że pekfos i ja byśmy użyli własnych bibliotek (przynajmniej w C++).
C/C++
ddt::cmn::FileTextReader file;
if( !file.open( L"ble.txt" ) ) // INFO: tu możesz mieć plik zapisany w dowolnym kodowaniu
     return false;

std::wstring line;
while( file.getNextLine( line ) ) // INFO: tu masz tekst w Unicode, więc się nie przejmujesz kodowaniem pliku
{
    //...
}

 W C# masz takie narzędzia dostępne w standardzie.

/edit:
Co do GUI to możliwe, że podobnie -> byśmy użyli własnego GUI-a (choć nie opiera się on o okienka tylko o samodzielnie renderowane kontrolki w SFML-u). Kwestia jakie wymagania byłyby stawiane takiej aplikacji okienkowej :)
P-170538
jankowalski25
» 2018-04-08 14:44:24
DejaVu: dlaczego
wchar_t
? Pytam z ciekawości, bo względem
char
 różni się jedynie rozmiarem, natomiast można trzymać tam dowolne dane binarne. Piszecie pod Windowsa i używacie w swoim frameworku UTF-16, więc tak było wygodniej?
P-170539
DejaVu
» 2018-04-08 15:02:26
Piszemy cross platform (win+linux), a std::wstring jest w standardzie i nie sprawia żadnych problemów więc... jest wstring :) wstring wspiera poprawnie znaki dowolnego języka i łatwo zaimplementować sensowny algorytm sortowania oraz łatwo iterować znak po znaku. W przypadku string-a nie masz takiej komfortowej sytuacji, ponieważ musiałbyś używać UTF-8, a to z kolei wymuszałoby posiadanie bardziej złożonych algorytmów do ustalania z ilu znaków składa się wyraz oraz nie wiedziałbyś gdzie się zaczyna i kończy jeden znak (np. literka 'ą').

Innymi słowy: lepiej poświęcić trochę więcej ramu na przechowywanie tekstu w postaci wstring ale mieć dużo łatwiejszą pracę z nim niż zaoszczędzić kilka bajtów poprzez zastosowanie string w połączeniu z UTF-8 i potem komplikować sobie wszystkie inne algorytmy w aplikacji (w najgorszym przypadku komplikujesz sobie całą aplikację, jeżeli zajmuje się ona przetwarzaniem tekstu).

Raczej nie ma wielu przypadków, że potrzebujesz koniecznie trzymać 1GB tekstu w ramie w danej chwili i szybko (oraz wielokrotnie) przetwarzać ten sam zbiór danych. Używając wstring użyjesz 2 lub 4 bajty na każdy znak (w zależności od systemu operacyjnego), natomiast w przypadku UTF-8 uzyskasz średnio 1.13 bajta na każdy znak (przy założeniu, że 13% znaków w tekście to znaki z ogonkami). Na tym przykładzie masz odpowiednio:
- 1.13GB RAM dla UTF-8 (string)
- 2GB RAM dla Windowsa (wstring)
- 4GB dla linuxa (wstring)

Jeżeli przetwarzałbym ogromny zbiór danych tekstowych to i tak unikałbym przechowywania ogromnego zbioru tekstowego w RAM, więc... w zasadzie lepiej poświęcić w skrajnym przypadku 4x więcej ramu i pisać proste algorytmy aniżeli zaoszczędzić trochę ramu kosztem znacznie bardziej złożonych algorytmów (czyli mieć bardziej skomplikowany kod).
P-170540
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2018-04-08 16:11:06
W takim razie, czemu nie używasz
char16_t
 albo
char32_t
, przecież one mają ustalony rozmiar.
Osobiście, gdybym miał używać unicode to pewnie w UTF-32 trzymałbym napisy, które często poddaję obróbce albo wykonuje jakieś operacje, a w UTF-8 już gotowy, przetworzony tekst. UTF-16 chyba jest bezużyteczny, bo ani nie można zrobić RandomAccessIteratora ani nie jest jakoś bardzo oszczędny jeśli chodzi o pamięć. Jakimś dziwnym trafem jednak Windows używa głównie UTF-16. Bravo.
Jeśli chodzi o algorytmy, to tym bardziej nie wiem o co chodzi. Algorytmy pozostają te same, jeśli napiszesz je w taki sposób, jak <algorithm>. Wtedy wystarczy, że napiszesz odpowiednie iteratory i gotowe.
C/C++
std::string searchIn = u8 "Ala ma kota";
std::string searchFor = u8 "kot";

auto it = std::search( utf8::string::begin( searchIn ), utf8::string::end( searchIn ), utf8::string::begin( searchFor ), utf8::string::end( searchFor ) );
^ zakładając, że
utf8::string::begin()
 oraz
utf8::string::end()
 to iteratory.
P-170544
pekfos
» 2018-04-08 16:41:34
W takim razie, czemu nie używasz char16_t albo char32_t, przecież one mają ustalony rozmiar.
Pod Windowsem wchar_t to UTF-16, pod linuksem UTF-32. Co dokładnie dałoby przyjęcie używania zawsze UTF-16, lub UTF-32? Tzn poza całkowicie zbędnymi konwersjami?

UTF-16 chyba jest bezużyteczny, bo ani nie można zrobić RandomAccessIteratora ani nie jest jakoś bardzo oszczędny jeśli chodzi o pamięć. Jakimś dziwnym trafem jednak Windows używa głównie UTF-16. Bravo.
Za to Ty zjadłeś wszystkie umysły :)
P-170546
DejaVu
» 2018-04-08 16:56:09
Wyciągnij n-ty znak z tekstu Utf8 ze zlozonoscia O(1) - powodzenia :)

/edit: Ty chyba argumenty wymyslasz na poczekaniu dlaczego wstring jest zly :) przez x-lat wstring funkcjonowal i jakos swiat sie nie zawalil :p
P-170547
jankowalski25
» 2018-04-08 17:19:23
UTF-16 chyba jest bezużyteczny
Dlaczego od razu bezużyteczny? Jak masz znaki mieszczące się co najwyżej na dwóch bajtach, to wybór tego kodowania jest dość rozsądnym pomysłem. Nie trzeba wszędzie wciskać UTF-32, jeśli nie ma takiej potrzeby.

Jakimś dziwnym trafem jednak Windows używa głównie UTF-16. Bravo.
Zgodność wsteczna. UTF-8 jeszcze wtedy nie istniało, a cały Unikod mieścił się na dwóch bajtach. Przeczytaj post P-148826 na drugiej stronie tematu Cyfry zamiast liter w wchar_t.

Wyciągnij n-ty znak z tekstu Utf8 ze zlozonoscia O(1) - powodzenia :)
Nie ma problemu, wystarczy sprawić, by całość trwała równie długo dla każdego przypadku (ale chyba nie o to chodziło). Wszystko da się zrobić ze złożonością O(1), ale nie zawsze jest to dobrym pomysłem i lepiej wybrać inną złożoność, jeśli stałe będą mniejsze (lub przechowywać dane w innej formie, na przykład zmieniając kodowanie znaków).

Ty chyba argumenty wymyslasz na poczekaniu dlaczego wstring jest zly
Nie musi, podobne argumenty występują na innych stronach, choćby http://utf8everywhere.org/, tylko tam są wyrażone nieco łagodniej, bez kategorycznego twierdzenia, że na pewno ich autorzy mają rację.
P-170548
1 « 2 » 3 4 5
Poprzednia strona Strona 2 z 5 Następna strona