Autor Wątek: Unicode (wydzielony z: Zagadki językoznawcze)  (Przeczytany 4667 razy)

Offline Xirdus

  • Redaktor

# Czerwiec 25, 2014, 23:43:09
Proste pytanie: jak przez printf() wypisać unsigned long long int w sposób przenośny, zgodny ze standardem i dobrymi praktykami?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Paweł

  • Użytkownik

# Czerwiec 25, 2014, 23:47:27
"%llu" ?

Offline Xirdus

  • Redaktor

# Czerwiec 26, 2014, 00:17:39

Offline lethern

  • Użytkownik

# Czerwiec 26, 2014, 00:29:51
zacząłbym od tego, czy używasz:
#ifdef __GNUC__
__extension__ //// long long is not supported by ISO C++ 1998. This prevents warning
typedef long long int64;
#else
typedef __int64 int64;
#endif

możesz nadpisać printf'a swoją definicją, właśnie bawiąc się w ifdef i dla Win stosuje Winskłądnię, dla Niewin stosuje nie-wiem-co-składnię. Albo inne podobne rozwiązanie, ale na moje oko takie "przenośne" rozwiązania to kończą się na #ifach
Tutaj musiałbyś pewnie wyłapać kompilator, czyli #if defined(_MSC_VER)
Ale to oznacza, że musiałbyś sobie zrobić workaround dla każdego kompilatora który ma swoją "wyższość" w tym poglądzie
Czyli sposób przenośny polega na zrobieniu wszystkich sposobów nieprzenośnych w jednym :)

Ja bym poszedł w makro, gdyby mi coś takiego było potrzebne
printf("M_I64", liczba);:D

No chyba że jest jakieś proste rozwiązanie, ale zakładam że gdyby było to by nie było pytania
« Ostatnia zmiana: Czerwiec 26, 2014, 00:41:46 wysłana przez lethern »

Offline Xirdus

  • Redaktor

# Czerwiec 26, 2014, 00:38:15
zacząłbym od tego, czy używasz:
#ifdef __GNUC__
__extension__ //// long long is not supported by ISO C++ 1998. This prevents warning
typedef long long int64;
#else
typedef __int64 int64;
#endif
Nie, bo C++11 ;)

No chyba że jest jakieś proste rozwiązanie, ale zakładam że gdyby było to by nie było pytania
To są zagadki językoznawcze - pytanie zadałem bo właśnie dzisiaj znalazłem to proste rozwiązanie :P

Offline karol57

  • Użytkownik

# Czerwiec 26, 2014, 01:02:28
"%llu" ?
Microsoft się nie zgadza (mimo że na Visualu działa).
Czemu MS nie dość, że jest do tyłu ze standardem to jeszcze normalne rzeczy robi na odwrót...

@topic
Chodzi o PRIi64PRIu64?

EDIT:
Nie zobaczyłem, że to header z C++11, ale no... tak jakby mamy już 2014 rok, więc tłumaczenie, że to "nowy" standard jak dla mnie odpada.

EDIT2:
To jak mamy użyć unsigned long long, skoro jest on dopiero od C++11 (według tego przynajmniej).

EDIT3:
Idiot... "Nie, bo C++11 ;)" zrozumiałem jako, żeby bez użycia C++11 robić -.-
« Ostatnia zmiana: Czerwiec 26, 2014, 01:17:47 wysłana przez karol57 »

Offline Xirdus

  • Redaktor

  • +1
# Czerwiec 26, 2014, 01:13:39
Chodzi o PRIi64?
Prawie. Pytanie było o unsigned - czyli PRIu64. Wpadłem na to szukając sposobu jak się pozbyć warninga w MinGW na temat że format %llu jest zły i jest jeden argument za dużo, mimo że wszystko działało. Swoją drogą, takie nagłówki bardzo dobrze świadczą o krótkowzroczności standardów C/C++ ("zróbmy chara nieokreślonej wielkości, shorta dowolną wielokrotnością chara, inta dowolną wielokrotnością shorta itd.", "8 bitów na znak to za mało - wprowadźmy 16-bitowe znaki", "trzeba zachować 100% zgodność z C, bo mamy masę kodu legacy który musi, musi, MUSI się kompilować nowym kompilatorem").

Offline lethern

  • Użytkownik

# Czerwiec 26, 2014, 01:17:27
Co do "Microsoft się nie zgadza", czy na pewno? http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf to link z ich strony z napisem "long long - yes"

Cytuj
krótkowzroczności standardów C/C++
wut?
« Ostatnia zmiana: Czerwiec 26, 2014, 01:22:28 wysłana przez lethern »

Offline karol57

  • Użytkownik

# Czerwiec 26, 2014, 01:21:10
A co oni wprowadzili... Ostatnio dostałem licencję na wersję Pro 2013, przeniosłem projekt z MinGW. I? Pełno errorów, bo tutaj nie obsługuje default dla move konstruktorów, tutaj tego nie obsługuje, tam tamtego. IDE mają fajne, ale kompilator (przynajmniej C++) ssie.

"zróbmy chara nieokreślonej wielkości, shorta dowolną wielokrotnością chara, inta dowolną wielokrotnością shorta itd.", "8 bitów na znak to za mało - wprowadźmy 16-bitowe znaki"
Na szczęście w 2011 się obudzili i jest cstdint. Swoją drogą, dopiero teraz zauważam, że większość rzeczy które używam i się dziwię czemu inni nie używają pochodzi z C++11.
« Ostatnia zmiana: Czerwiec 26, 2014, 01:24:16 wysłana przez karol57 »

Offline Xirdus

  • Redaktor

# Czerwiec 26, 2014, 12:09:38
wut?
Każdy z przytoczonych przeze mnie przykładów to decyzje projektowe, które jakiś tam sens przy powstawaniu miały, ale potem doprowadziły do masy problemów wraz z rozwojem technologii - i żeby jakoś uporządkować to, wprowadzano nagłówki typu stdint.h z typedefami, które gwarantują, że uint32_t na pewno będzie 32-bitową liczbą bez znaku (bo język sam w sobie żadnych gwarancji nie daje).

Na szczęście w 2011 się obudzili
Dokładnie to w 1999 - razem ze standardem C99, który wprowadził wiele z rzeczy teraz obecnych w C++11, m.in. standardowy long long int. Tak więc tego PRIu64 dało się używać już 15 lat temu - tylko nie w Visualu ;)

Offline Xender

  • Użytkownik

# Czerwiec 27, 2014, 10:33:56
"8 bitów na znak to za mało - wprowadźmy 16-bitowe znaki"
Akurat wchar (z akcentem na WC) to nie wymysł ze standardu C++, tylko praktyka z czasów, kiedy powstawał Unicode (UCS-2, nie mylić z UTF-16).

Obecnie nie ma powodu, żeby tego używać. Nawet, jeśli jakieś API tego wymaga, to trzymać wszystko w UTF-8 w normalnym stringu (normalnych charach) i robić konwersję tuż przed podaniem stringa do zwapniałego API (Ohayou, WinAPI-chan ^ ^).

Offline Xirdus

  • Redaktor

# Czerwiec 27, 2014, 11:12:30
Akurat wchar (z akcentem na WC) to nie wymysł ze standardu C++, tylko praktyka z czasów, kiedy powstawał Unicode (UCS-2, nie mylić z UTF-16).
OK. Rozszerzam moją opinię na wszystkie dwudziestowieczne standardy :) BTW - zapomniałem dodać, że najgorsze w wchar_t jest rozmiar zależny od implementacji - co jest o wiele gorsze od samego zmiennego rozmiaru intów, bo całkiem rozpieprza to stringi (oczywiście C11/C++11 dodaje typy char16_t i char32_t...).

Obecnie nie ma powodu, żeby tego używać. Nawet, jeśli jakieś API tego wymaga, to trzymać wszystko w UTF-8 w normalnym stringu (normalnych charach) i robić konwersję tuż przed podaniem stringa do zwapniałego API (Ohayou, WinAPI-chan ^ ^).
Dobra. Ale standardowy std::string AFAIK nie obsługuje multibyte charów? Chodzi mi o iterowanie po znakach i w konsekwencji "zły" (nieprzydatny) wynik funkcji length(). Zdaje mi się, że linkowałeś kiedyś w którymś temacie fajną bibliotekę do obsługi UTF-8 w C++?

Offline albireo

  • Użytkownik

# Czerwiec 27, 2014, 11:45:34
Dobra. Ale standardowy std::string AFAIK nie obsługuje multibyte charów? Chodzi mi o iterowanie po znakach i w konsekwencji "zły" (nieprzydatny) wynik funkcji length().
Nawet jakby działał na UTF-32, to i tak length nie zawsze byłby poprawny, bo zwracałby wynik w codepointach a nie w znakach.

Offline Xirdus

  • Redaktor

# Czerwiec 27, 2014, 12:20:26
Nawet jakby działał na UTF-32, to i tak length nie zawsze byłby poprawny, bo zwracałby wynik w codepointach a nie w znakach.
Jak dla mnie takie zachowanie byłoby OK - znaki kontrolne to też znaki i też są ważne (a jak nie, to zawsze można pominąć).

Zdaje mi się, że linkowałeś kiedyś w którymś temacie fajną bibliotekę do obsługi UTF-8 w C++?
Znalazłem już: http://utfcpp.sourceforge.net

Offline albireo

  • Użytkownik

# Czerwiec 27, 2014, 13:01:49
Jak dla mnie takie zachowanie byłoby OK - znaki kontrolne to też znaki i też są ważne (a jak nie, to zawsze można pominąć).
Nie chodzi mi o znaki kontrolne, a o combining characters, czyli w skrócie o takie kody które np dodają nad/pod literkę kreseczkę, kropeczkę czy inną dupereleczkę (przy czym nie łączy to się z każdym znakiem), sporo znaków ma podwójną reprezentację, jedną jako pojedynczy kod i inną jako połączenie dwóch (lub więcej kodów), co więcej występują też takie cuda jak ligatury (np ff), czyli połączenie dwóch lub więcej znaków w jeden kod.
« Ostatnia zmiana: Czerwiec 27, 2014, 13:44:06 wysłana przez albireo »