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ść
RazzorFlame
Temat założony przez niniejszego użytkownika
Biblioteki łatające dziury standardu C++
» 2018-04-07 17:29:01
Jakich bibliotek używacie w swoich projektach, żeby załatać dziury standardowej biblioteki? Mówię np. o:

- obsłudze Unicode-u i wielu kodowań znaków: różne transformacje znaków, obsługa I/O (std io/pliki)
- połączeniach sieciowych
- parsowaniu popularnych formatów plików np. z ustawieniami

Oprócz tego, powiedzcie jak ich używacie: czy w całości, czy tylko kawałek, który odpowiada za daną funkcjonalność (np. w przypadku boosta). Jak często spotykacie się z tym, że biblioteka standardowa nie wystarcza Wam do podstawowych rzeczy?
P-170506
jankowalski25
» 2018-04-07 18:33:11
obsłudze Unicode-u i wielu kodowań znaków
Wszędzie używam UTF-8, jeśli to możliwe. Z innych formatów korzystam tylko w razie konieczności (na przykład pisząc coś pod UEFI niektóre funkcje wymagają UTF-16). W takich przypadkach wewnętrznie trzymam wszystko w UTF-8 i zamieniam na odpowiednie kodowanie dopiero, gdy zajdzie taka potrzeba, w locie, w czasie wykonania. A potem jak trzeba przechować gdzieś wynik, to od razu następuje konwersja z powrotem do UTF-8. Wyjątek stanowią przypadki, gdzie inne kodowanie jest używane ze względu na optymalizacje (ciągłe przeskakiwanie między UTF-8 i UTF-32 nie zawsze jest dobrym pomysłem).

różne transformacje znaków
Zdefiniuj, co rozumiesz pod pojęciem "transformacja znaku".

obsługa I/O (std io/pliki)
Dopóki
#include <fstream>
 wystarcza, to tego używam. Jak potrzeba czegoś lepszego, to kombinuję inaczej. Gdzieś na forum był temat dotyczący obsługi plików, wraz z kilkoma testami wydajności (jak znajdę, to wstawię link). Jeśli dobrze pamiętam, to gołe syscalle okazały się najszybsze.

połączeniach sieciowych
SFML Network całkiem nieźle nadaje się do trywialnych zastosowań, WinSock do nieco ogólniejszych rzeczy (jakiś czas temu Beej zaktualizował tutorial, przydałoby się kiedyś go przetłumaczyć i zaktualizować naszą wersję).

parsowaniu popularnych formatów plików np. z ustawieniami
Podaj przykłady takich formatów. Jeśli chodzi o serializację ustawień programu, to zwykle każdy program miał to nieco inaczej zorganizowane, więc ustawienia w plikach binarnych trzeba było definiować oddzielnie dla każdego przypadku. Do XML używam biblioteki RapidXML, z JSONa rzadziej korzystałem, ale też były do tego jakieś biblioteki. Do prostej serializacji binarnej wystarczy spokojnie
sf::Packet
, a w razie potrzeby zrobienia tego lokalnie zawsze można kierować dane do localhosta. Do szybkich prototypów przy braku innych możliwości wystarczy pobieranie rozmiaru przez
sizeof( typDanych )
 i rzutowanie wszystkiego na
char *
, co opisał pekfos w artykule Zapis binarny.

jak ich używacie: czy w całości, czy tylko kawałek, który odpowiada za daną funkcjonalność
RapidXML w całości, bo w praktycznych zastosowaniach głupio byłoby siekać te cztery nagłówki na coś drobniejszego. W przypadku SFML czasem wystarczyły tylko niektóre moduły, na przykład samo Network i System.

Jak często spotykacie się z tym, że biblioteka standardowa nie wystarcza Wam do podstawowych rzeczy?
Dość często, ale coraz rzadziej z powodu nowości pojawiających się w kolejnych standardach. Na przykład obsługa plików w C++17 jest już nieco bardziej rozbudowana.
P-170507
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2018-04-07 20:58:28
Wszędzie używam UTF-8, jeśli to możliwe.
Właśnie to mnie interesuje. Czego używasz do obsługi UTF-8? Czy korzystasz z jakichś ciekawych iteratorów, czy jak? Jak korzystasz (o ile w ogóle) z konsoli w trybie UTF-8? Linux/Windows?
Zdefiniuj, co rozumiesz pod pojęciem "transformacja znaku".
Zamienianie na lower case i upper case, a poza transformacją, pozyskiwanie cech znaku - is upper, is lower, is space itd.
P-170511
jankowalski25
» 2018-04-07 21:23:05
Czego używasz do obsługi UTF-8?
Głównie
std::string
 oraz
char *
, edytor ma ustawione odpowiednie kodowanie, a kompilator po prostu wrzuca wszystkie bajty do właściwych zmiennych. I tyle.

Czy korzystasz z jakichś ciekawych iteratorów, czy jak?
Zależy, co chcesz zrobić z danym tekstem. Zapisać go do pliku? Wtedy wysyłasz ciąg bajtów do
std::ofstream
 i gotowe. Wyświetlić na ekranie? SFML spokojnie sobie z tym poradzi, byle czcionka miała odpowiednie glify. Potrzebujesz jakichś specyficznych działań?

Jak korzystasz (o ile w ogóle) z konsoli w trybie UTF-8? Linux/Windows?
Zarówno gnome-terminal, jak i lxterminal oraz jk-terminal_2018-04-03 (najnowsza wersja) wspiera UTF-8. W przypadku Windowsa można użyć funkcji korzystających z UTF-16 (to samo dotyczy UEFI). Stron kodowych lepiej nie ruszać, chyba że gdzieś potrzebujesz zgodności z DOSem.

Zamienianie na lower case i upper case, a poza transformacją, pozyskiwanie cech znaku - is upper, is lower, is space itd.
Korzystam ze standardowej biblioteki. Jeśli są problemy z implementacją, szukam alternatywnych wersji (jak dotąd, rzadko tego potrzebowałem). Zamieszanie z ustawieniami lokalnymi to grubszy problem, zwykle najlepiej ustawić to na tyle rozsądnie, na ile jest to możliwe, a w razie wątpliwości samodzielnie dostarczyć odpowiednią implementację (jeśli potrzebujesz tylko polskich znaków, to samodzielne zaimplementowanie tych osiemnastu przypadków nie powinno sprawiać większych problemów). Zwykle jest tak, że nakładam jakieś ograniczenia na to, jakie znaki wspieram, a resztę traktuję jako "Nie zaimplementowano (jeszcze)". Zresztą i tak trzeba sprawdzić, jakie znaki wspiera czcionka. Jeśli jest jakaś wydumana, to może się okazać, że pokrywa tylko niewielki kawałek Unikodu.
P-170513
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2018-04-07 23:53:10
Korzystam ze standardowej biblioteki.
Z tego co czytałem, to standardowa biblioteka nie nadaje się do jakichkolwiek operacji na tekście zakodowanym inaczej niż jako ASCII.
std::tolower
 zwraca jedną zmienną: jeden znak i to dodatkowo typu int (rly?).
std::ctype::tolower
 również zwraca jeden znak. Co jeśli ktoś będzie np. chciał zuppercaseować "ß"? Niemieckie "ß" jeszcze do niedawna nie miało odpowiednika w wielkiej literze i było pisane jako "SS" (o ironio). Standard nie ma wsparcia dla unicode. To co jest to tylko jakaś nieudana próba.
P-170516
jankowalski25
» 2018-04-08 10:15:10
standardowa biblioteka nie nadaje się do jakichkolwiek operacji na tekście zakodowanym inaczej niż jako ASCII
Hmm, spodziewam się, że jeszcze znajdzie się parę mniej typowych kodowań pokroju EBCDIC, które dla jednobajtowych znaków zadziałają prawidłowo.

std::tolower
 zwraca jedną zmienną: jeden znak i to dodatkowo typu int (rly?)
Niestety. Ale cóż, zwykle było tak, że używałem tego wewnętrznie, więc nie musiałem wspierać całego Unikodu i mogłem spokojnie ograniczyć się do jednobajtowych znaków.

Co jeśli ktoś będzie np. chciał zuppercaseować "ß"? Niemieckie "ß" jeszcze do niedawna nie miało odpowiednika w wielkiej literze i było pisane jako "SS" (o ironio).
Jak już wspomniałem wcześniej, najpierw sprawdź, czy czcionka, której chcesz użyć, wspiera te znaki. Jeśli nie, to od razu trzeba zabronić wyświetlania takich znaków lub wyświetlać je tylko tak, jak dana czcionka pozwala (akurat konsole pokroju gnome-terminal mają taką zaletę, że w razie problemów wyświetlają znaki w postaci prostokątów z ich numerami w Unikodzie, z kolei gedit z automatu szuka odpowiednich czcionek i proponuje ich instalację).

Standard nie ma wsparcia dla unicode. To co jest to tylko jakaś nieudana próba.
Jak już wspominałem, to jest większy problem. Na razie moja rada jest taka, żeby poszukać jakichś bibliotek, które robią to poprawnie albo po prostu ograniczyć się do tych znaków, których potrzebujesz (zadaj sobie pytanie, czy w obecnej wersji programu wspieranie znaków z alfabetu "chiński tradycyjny" albo prawidłowe wyświetlanie całej talii kart, figur szachowych, czy też wszystkich emotikonów jest konieczne). Przy okazji zwróć uwagę na to, że są znaki, na których niektóre operacje mogą nie mieć sensu (jaki znak ma zwrócić toupper (niekoniecznie standardowa, mowa o jakiejkolwiek implementacji) dla kolby kukurydzy? A może dałoby się w ogóle nie wywoływać takiej funkcji na tych znakach?).
P-170521
pekfos
» 2018-04-08 10:27:01
jaki znak ma zwrócić toupper (niekoniecznie standardowa, mowa o jakiejkolwiek implementacji) dla kolby kukurydzy?
A co toupper zwraca dla '4'? Chyba nie ma "dużego 4".
P-170523
RazzorFlame
Temat założony przez niniejszego użytkownika
» 2018-04-08 12:28:17
Wsparcie standardu dla unicode:

- wszystkie
std::basic_string < CharT >::size()
 oraz
std::basic_string < CharT >::length()
 zwracają liczbę elementów w tablicy a nie ilość znaków.
- 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
- 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. 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.
- nie istnieją utfXiteratory, które pozwalałyby sprawnie iterować po kolejnych znakach. Trzeba pisać to samemu
- nie ma żadnego identyfikatora dla std::stringa, że przechowuje UTF-8 a nie ASCII
- locale są biedne: "jak wyświetlić polskie/niemieckie/... znaki w konsoli?" - ile ludzi tyle opinii, praktycznie pod każdą odpowiedzią na stackoverflow są komentarze "this is not working".

To nie jest wsparcie. To wygląda jakby próbowali dodać wsparcie, ale na etapie 10-15% odpuścili i powiedzieli, że mają to gdzieś. Przecież dostosowanie
std::basic_string < CharT >
 i stworzenie iteratorów do nich to jest fraszka, w porównaniu do innych rzeczy, które trafiają do standardu.

Pekfos, a Ty, jeśli miałbyś napisać sprawnie działający edytor tekstu, to jakich bibliotek byś użył? Omińmy Qt - chciałbym coś z tego tematu wyciągnąć do projektów, w których same okienka nie mają takiego znaczenia, a Qt w takich sytuacjach się raczej nie nadaje. Boost? Jeśli tak to 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". Dzięki.
P-170534
« 1 » 2 3 4 5
  Strona 1 z 5 Następna strona