2012-12-03 16 views
39

Dzisiaj wypróbowałem kilka nowych funkcji C++ 11 STL i napotkałem std::to_string.C++ 11 std :: to_string (podwójne) - Bez końcowych zer

Piękny, piękny zestaw funkcji. Tworzenie obiektu stringstream na tylko jeden pokój na ciąg znaków nawrócenia zawsze wydawało mi się przesadą, więc cieszę się, że możemy teraz zrobić coś takiego:

std::cout << std::to_string(0.33) << std::endl; 

wynik?

0.330000 

Nie jestem do końca zadowolony z tego. Czy istnieje sposób, aby powiedzieć std::to_string, aby pominąć końcowe zera? Przeszukałem internet, ale z tego, co widzę, funkcja przyjmuje tylko jeden argument (wartość do przeliczenia). Wracając do dawnych czasów za pomocą stringów, możesz ustawić szerokość strumienia, ale wolałbym nie konwertować z powrotem.

Ktoś napotkał ten problem przed/ma rozwiązanie? Niektóre wyszukiwania StackOverflow nie przyniosły niczego.

(C++ 11 odniesienie STL: http://en.cppreference.com/w/cpp/string/basic_string/to_string)

+0

@chris: nie po wywołaniu 'std :: to_string'. Zwraca łańcuch, a nie liczbę, a jego formatowanie wydaje się trudne do modyfikacji. – rubenvb

+0

@rubenvb, Strzelaj, nie myślę poprawnie, czy ja ... – chris

+1

"Piękny, piękny zestaw funkcji. Tworzenie obiektu stringstream dla jednej podwójnej konwersji zawsze wydawało mi się przesadzone". A potem widzisz, dlaczego tak naprawdę nie jest to przesada - to strumienie, które zawierają całą infrastrukturę do określania formatu. Aby uzyskać to, czego chcesz, 'to_string' musiałoby duplikować wszystko w równoważnym API. To może nie jest okropny pomysł, ale nie jest to pomysł, z którym komisja się zgadza. Powód 'to_string' jest piękny: nie ma opcji ;-) –

Odpowiedz

26

C++ 11 Standardowy jawnie mówi (21.5/7):

Powroty: Każda funkcja zwraca obiekt ciąg znaków posiadających reprezentację wartości swoich argumentów, które byłyby generowane przez wywołanie sprintf (buf, fmt, val) ze specyfikatorem formatu "% d", "% u", "% ld", "% lu", "% lld", "% llu", "% f", "% f" lub „% Lf” odpowiednio, gdzie buf wyznacza wewnętrzny bufor postaci wystarczającej wielkości

dla funkcji zgłoszone w tej kolejności:

string to_string(int val); 
string to_string(unsigned val); 
string to_string(long val); 
string to_string(unsigned long val); 
string to_string(long long val); 
string to_string(unsigned long long val); 
string to_string(float val); 
string to_string(double val); 
string to_string(long double val); 

W ten sposób nie można kontrolować formatowania wynikowego ciągu znaków.

+1

+1 za dowód. – chris

13

std::to_string daje żadnej kontroli nad formatem; otrzymujesz taki sam wynik, jak sprintf z odpowiednim specyfikatorem formatu dla tego typu ("%f" w tym przypadku).

Jeśli potrzebujesz większej elastyczności, potrzebujesz bardziej elastycznego formatyzatora - na przykład std::stringstream.

+1

OK, to oczywiście nie była odpowiedź, na którą liczyłem, ale dzięki za oczyszczenie :) –

3

std::to_string(double) jest zdefiniowany przez standard, aby po prostu zwrócić tę samą sekwencję znaków, która byłaby generowana przez sprintf(buf, "%f", value). Nie więcej, nie mniej, zwłaszcza nie ma sposobu na dostosowanie specyfikatora formatu. Więc nie, nic nie możesz zrobić.

29

Jeśli wszystko, co chcesz zrobić, to usunąć końcowe zera, cóż, to proste.

std::string str = std::to_string (f); 
str.erase (str.find_last_not_of('0') + 1, std::string::npos); 
+5

Działa prawie idealnie, z wyjątkiem przypadku narożnego, w którym liczba zmiennopozycyjna/podwójna jest liczbą całkowitą. Rezultatem jest np. '440., Podczas gdy niektórzy mogą preferować' 440.0', jeśli i tak chcą uzyskać dobre wyniki. Nic, co zwykłe sprawdzenie ostatniej postaci nie rozwiąże. –

+4

prawidłowa, to dlaczego ja dostosować kod Marshalls: 'nazw util { szablon std :: string to_string (const T & T) { std :: string str {std :: to_string (t)}; int offset {1}; if (str.find_last_not_of ('0') == str.find ('.')) { offset = 0; } str.erase (str.find_last_not_of ('0') + odsunięcie, std :: string :: npos); powrót str; } } ' powoduje to również usunięcie niepotrzebnej kropki. – antibus

-1
double val 
std::wstringstream wss; 
wss << val; 
cout << wss.str().c_str(); 
-1

Aby pominąć zera kończące:

std::ostringstream oss; 
oss << std::setprecision(8) << std::noshowpoint << double; 
std::string str = oss.str(); 

nadzieję, że pomoże.

Powiązane problemy