Як перетворити дубль у рядок у C ++?


171

Мені потрібно зберігати дубль як рядок. Я знаю, що можу використати, printfякщо хотів його відобразити, але просто хочу зберігати його в рядковій змінній, щоб згодом я міг зберігати її на карті (як значення , а не як ключ ).


2
Питання для відповіді на ваше запитання: чому ви зберігаєте подвійне значення у рядку, щоб зберігати його на карті? Чи збираєтесь ви використовувати подвійний подвійний рядок як ключ? Якщо ні, то чому б не залишити подвійний, як є?
Метт МакКлеллан

1
Цікавий момент. Використання подвійного в якості ключа карти може загрожувати небезпекою, однак завжди є точними порівняннями значень з плаваючою комою. Індексація на рядковому поданні дозволяє уникнути проблеми.
Фред Ларсон

2
Навіщо це взагалі конвертувати? Зберігайте її на карті як подвійну, а також уникайте перетворення на та з нього.
EvilTeach

3
Це все ще звучить як заклик до об'єктів. Спілка працювала б. Кожен об'єкт повинен вставити в нього різні значення та дати йому самовивірку.
EvilTeach

2
У файлі є лише пара імен / значень. Це не вимагає об'єктів.
Білл Ящірка

Відповіді:


183

Спосіб збільшення (тм) :

std::string str = boost::lexical_cast<std::string>(dbl);

У Standard C ++ спосіб:

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

Примітка . Не забувайте#include <sstream>


3
Я думаю, що boost :: lexical_cast в значній мірі є стандартним способом C ++, просто гарно упакованим для вас. BTW, litb, у вас є незначна помилка - "boot: lexical_cast".
Фред Ларсон

2
boost :: lexical_cast - це не просто проста обгортка навколо рядкового коду. Багато підпрограми перетворення реалізовані вбудовано. Відповідно до вимірювань продуктивності внизу цієї сторінки ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ), boost :: lexical_cast швидше, ніж використання потокових потоків і, в більшості випадків, швидше, ніж scanf / printf
Ferruccio

1
@Ferr хто сказав, що це проста оболонка? І спасибі за надану посилання, я на самому ділі так думаю , що це було більш-менш простий обгорткою :)
Johannes Schaub - LITB

27
не забувайте про #include <sstream>спосіб c ++ :)
VladL

3
Заради документації, якщо ви цього не зробите #include <sstream>, ви отримаєте помилку "неповний тип заборонений".
Тревор Салліван

194
// The C way:
char buffer[32];
snprintf(buffer, sizeof(buffer), "%g", myDoubleVar);

// The C++03 way:
std::ostringstream sstream;
sstream << myDoubleVar;
std::string varAsString = sstream.str();

// The C++11 way:
std::string varAsString = std::to_string(myDoubleVar);

// The boost way:
std::string varAsString = boost::lexical_cast<std::string>(myDoubleVar);

1
Ваш C ++ спосіб не працюватиме, тому що operator <<повертає std::ostream&скоріше ніж a stringstream&.
Конрад Рудольф

Здається, мої струнні потоки трохи іржаві, я віддаю перевагу способам ol 'C. Виправлено зараз (сподіваюся).
Адам Розенфілд

Ваш код C спочатку мене відкинув. Я все ще виступав за те, щоб дати правильні альтернативи.
Білл Ящірка

2
пропозиція щодо включення способу С. просто здається мені набагато чистішим.
Неалон

11
Запропоновано на C ++ 11 шлях. Я новачок у C ++ і не зрозумів, що є to_stringфункція. Я використовую Microsoft Visual C ++ 2013.
Тревор Салліван

123

Стандарт C ++ 11 спосіб (якщо ви не дбаєте про формат виведення):

#include <string>

auto str = std::to_string(42.5); 

to_string- це нова функція бібліотеки, запроваджена в N1803 (r0), N1982 (r1) та N2408 (r2) " Простий числовий доступ ". Існує також stodфункція виконання зворотної операції.

Якщо ви хочете мати інший вихідний формат, ніж "%f"скористайтеся методами snprintfабо ostringstreamметодами, як показано в інших відповідях.


3
о так, дитино. Тонінгрінг та stod обидва працюють у Visual Studio 11.
BSalita

О, дорогий мій ..., схоже, to_string не працює у VisualStudio 2010): Це, або я не знаю, що я роблю (дуже можливо)
chessofnerd

1
Це повинно бути вище, оскільки це сучасніше!
gsamaras

1
Чи є спосіб, щоб ця функція не додала більше десятків, ніж потрібно? Коли я перетворюю подвійний, 8.0він дає мені рядок "8.000000", хоча це "8"було б чудово.
HelloGoodbye

1
Це не працює для невеликих чисел ... наприклад: 1e-9виробляє0.000000
user3728501

24

Якщо ви використовуєте C ++, уникайте sprintf. Це un-C ++ y і має кілька проблем. Stringstreams - це метод вибору, бажано інкапсульований як у Boost.LexicalCast, який можна зробити досить легко:

template <typename T>
std::string to_string(T const& value) {
    stringstream sstr;
    sstr << value;
    return sstr.str();
}

Використання:

string s = to_string(42.5);

24

Ви можете використовувати std :: to_string в C ++ 11

double d = 3.0;
std::string str = std::to_string(d);

Мої цифри були насправді невеликими і std::to_string()просто поверталися 0,000000, а не в науковій формі.
erfan

11

sprintfце нормально, але в C ++ кращий, безпечніший, а також трохи повільніший спосіб здійснення конверсії stringstream:

#include <sstream>
#include <string>

// In some function:
double d = 453.23;
std::ostringstream os;
os << d;
std::string str = os.str();

Ви також можете використовувати Boost.LexicalCast :

#include <boost/lexical_cast.hpp>
#include <string>

// In some function:
double d = 453.23;
std::string str = boost::lexical_cast<string>(d);

В обох випадках strмає бути "453.23"згодом. LexicalCast має деякі переваги тим, що забезпечує трансформацію завершену. Він використовує stringstreams внутрішньо.


10

Я б подивився на бібліотеку C ++ String Toolkit Libary . Щойно розмістив подібну відповідь в іншому місці. Я знайшов це дуже швидко і надійно.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );


6

Проблема з lexical_cast полягає в неможливості визначити точність. Зазвичай, якщо ви перетворюєте подвійний на рядок, це тому, що ви хочете роздрукувати його. Якщо точність занадто велика або занадто мала, це вплине на результат.



4

Хе, я щойно написав це (не пов'язане з цим питанням):

string temp = "";
stringstream outStream;
double ratio = (currentImage->width*1.0f)/currentImage->height;
outStream << " R: " << ratio;
temp = outStream.str();

/* rest of the code */

2

Ви можете прочитати мою попередню публікацію на SO. (Версія для макросів з тимчасовим об'єктом потокового потоку.)

Для запису: У власному коді я віддаю перевагу snprintf (). Маючи масив char на локальному стеку, це не так ефективно. (Ну, можливо, якщо ви перевищили розмір масиву і циклічно це зробили вдвічі ...)

(Я також завершив це через vsnprintf (). Але це коштує мені перевірки типу. Yelp, якщо ви хочете код ...)


2

Погляньте і на sprintf()родину.


2
Я згадав printf, тому що googling виявив купу статей, в яких говориться про перетворення з подвійного на рядок, який ви використовуєте printf. Вони роблять припущення, що єдине, що ви могли б зробити - це друк, що в моєму випадку є помилковим.
Білл Ящірка

чому ти голосуєш -1? Я думаю, спринт добре. @BilltheLizard, спринт друкує щось на екрані char * not. Хтось відповів методом c все-таки отримав багато голосів.
worldterminator

2

Зазвичай для цих операцій потрібно використовувати функції ecvt, fcvt або gcvt:

/* gcvt example */
#include <stdio.h>
#include <stdlib.h>

main ()
{
  char buffer [20];
  gcvt (1365.249,6,buffer);
  puts (buffer);
  gcvt (1365.249,3,buffer);
  puts (buffer);
  return 0;
}

Output:
1365.25
1.37e+003   

Як функція:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}

0

Ви можете спробувати більш компактний стиль:

std::string number_in_string;

double number_in_double;

std::ostringstream output;

number_in_string = (dynamic_cast< std::ostringstream*>(&(output << number_in_double <<

std::endl)))->str(); 

0

Використовуйте to_string().
приклад:

#include <iostream>   
#include <string>  

using namespace std;
int main ()
{
    string pi = "pi is " + to_string(3.1415926);
    cout<< "pi = "<< pi << endl;

  return 0;
}

запустіть його самостійно: http://ideone.com/7ejfaU
Вони також доступні:

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned 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);

0

Ви можете перетворити будь-яку річ у що завгодно за допомогою цієї функції:

template<class T = std::string, class U>
T to(U a) {
    std::stringstream ss;
    T ret;
    ss << a;
    ss >> ret;
    return ret;
};

використання:

std::string str = to(2.5);
double d = to<double>("2.5");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.