2010-12-18 25 views
10

Gdy używasz scanf() i jego wariantów, specyfikator formatu %i przyjmuje dane w postaci heksadecymalnej (prefiks "0x"), ósemkowy (prefiksowany "0") lub dziesiętny (bez przedrostka), więc na przykład ciągi "0x10" , "020" i "16" są konwertowane na liczbę całkowitą z wartością dziesiętną 16.Czy `std :: istream :: operator >>()` może przyjmować prefiksy w postaci liczb całkowitych jak np. Specyfikator formatu% i stdio?

Czy można to zrobić przy użyciu sformatowanego wejścia std::istream::operator>>?

Plain >> i bez manipulatora I/O „0x10” jest zamienione na zero (lub raczej prowadzi 0 znaczy „x10” część nie jest wykonywana) i „020” do 20. hex, oct i dec Manipulatory zachowują się odpowiednio: %x, %o i %d. Szukam ogólnego wejściowego manipulatora wejściowego, który działa jak %i.

Co ciekawe, manipulator hex akceptuje zarówno "0x10", jak i "10", dokonując konwersji do 16 miejsc po przecinku.

W przypadku, gdy zastanawiasz się, wdrażam narzędzie do oceny ekspresji i chciałbym, żeby operandy całkowite były szesnastkowe, ósemkowe lub dziesiętne, używając konwencji prefiksów C/C++. Obecna implementacja przy użyciu sscanf() robi to automatycznie przy użyciu %i i jestem ciekawy, czy można to zmodyfikować, aby użyć iostream bez konieczności jawnego analizowania formatu liczbowego.

+0

Interestin. +1. Zastanawiam się, czy w książce C++ IOStreams i Locales jest coś takiego ... –

+0

Ponieważ jestem prawie w 100% pewny, że nie ma bezpośredniego odpowiednika, uważam, że najmodniejsze i najbardziej pilne rozwiązanie byłoby wdrożenie nowego manipulatora postaci 'std :: ios_base & integer (std :: ios_base & str);' – Clifford

+0

@Johannes ma odpowiedź, która zapewnia również sposób implementacji powyższego manipulatora. – Clifford

Odpowiedz

10

Pole podstawowe w flagach formatu basic_istream określa sposób interpretowania liczb. Pole można ustawić na dec, oct i na hex. Domyślnie jest ustawiony na dec. Jeśli jest ustawiony na żadnym z nich, basic_istream będą zachowywać się jak scanf „s %i flagi:

// automatically detect the base, depending on prefix 
std::cin.unsetf(std::ios_base::basefield); 
+0

Geniusz. Teraz widzę, jak to się robi, o wiele łatwiej jest znaleźć dokumentację, która mówi, jak! np .: http://stdcxx.apache.org/doc/stdlibug/28-3.html – Clifford