Якщо Ви вказали, що код на С++, то й використовуйте засоби С++. У string із STL є цілком зручні функції для перетворення в числа: stoi(), stod() і т.д. Єдине обмеження – потрібно використовувати С++11 (або новіше). Ось приклад використання:
#include // std::cout #include // std::string, std::stod int main () < std::string orbits ("365.24 29.53"); std::string::size_type sz; // або з size_t double earth = std::stod (orbits,&sz); double moon = std::stod (orbits.substr(sz)); std::cout
Подібні
Підписатися на стрічку
Для підписки на стрічку скопіюйте та вставте це посилання у вашу програму для читання RSS.
Site design/logo © 2024 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2024.11.28.19452
Переклад рядка в double
Як перекласти рядок типу
string s = "0000000000000f8bf"
значення double ? Я знаю, як прочитати з файлу таке значення, і правильно перекласти. А як з рядком не можу зрозуміти (може тому, що кінець робочого дня). Приклад програми, яка записує у файл 50 double чисел у бінарному форматі і потім вдало зчитує файл і такі значення чудово переводить у double.
#include #include #define FILENAME "b.txt" int main(void) < register int i; FILE * fp; double balance[101]; /* відкриття запис */ if ((fp = fopen(FILENAME, "wb")) == NULL) < printf("Cannot open file."); return 1; >for (i = 0; i < 101; i++) balance[i] = -25 + 0.5 * i; /* збереження за раз всього масиву balance */ fwrite(balance, sizeof balance, 1, fp); fclose(fp); /* обнулення масиву */ for (i = 0; i/* читання за раз всього масиву balance */ fread(balance, sizeof balance, 1, fp); /* виведення вмісту масиву */ for (i = 0; i
double f; *((unsigned long long*)&f) = strtoull(s.c_str(),0,16);
@Harry Цей код, на жаль, працює не коректно. Є припущення помилка через порядок слідування байтів (big-endian/little-endian).
@Vladimir Якщо запустити приклад, ви побачите, як записуються числа double у файл. І як вони коректно зчитуються. Ось що буде записано у файл:
0000 0000 0000 39c0 0000 0000 0080 38c0 0000 0000 0000 38c0 0000 0000 0080 37c0 0000 0000 0000 000 36c0 0000 0000 0000 36c0 0000 0000 0080 35c0 0000 0000 0000 35c0 0000 0000 0080 34c0 0000 0000 000 0080 33c0 0000 0000 0000 33c0 0000 0000 0080 32c0 0000 0000 0000 32c0 0000 0000 0080 31c0 00000 0 0000 0080 30c0 0000 0000 0000 30c0 0000 0000 0000 2fc0 0000 0000 0000 2ec0 0000 0000 0000 2dc0 000 0000 0000 2bc0 0000 0000 0000 2ac0 0000 0000 0000 29c0 0000 0000 0000 28c0 0000 0000 0000 27c0 000 0000 0000 0000 25c0 0000 0000 0000 24c0 0000 0000 0000 23c0 0000 0000 0000 22c0 0000 0000 0000 0 20c0 0000 0000 0000 1ec0 0000 0000 0000 1cc0 0000 0000 0000 1ac0 0000 0000 0000 18c0 0000 0000 000 14c0 0000 0000 0000 12c0 0000 0000 0000 10c0 0000 0000 0000 0cc0 0000 0000 0000 08c0 0000 0000 00 0000 00c0 0000 0000 0000 f8bf 0000 0000 0000 f0bf 0000 0000 0000 e0bf 0000 0000 0000 0000 0000 000 0000 f03f 0000 0000 0000 f83f 0000 0000 0000 0040 0000 0000 0000 0440 0000 0000 0000 0840 0000 000 0000 1040 0000 0000 0000 1240 0000 0000 0000 1440 0000 0000 0000 1640 0000 0000 0000 1840 0000 000 0000 0000 1c40 0000 0000 0000 1e40 0000 0000 0000 2040 0000 0000 0000 2140 0000 0000 0000 2240 000 0000 0000 0000 2440 0000 0000 0000 2540 0000 0000 0000 2640 0000 0000 0000 2740 0000 0000 0000 0 2940 0000 0000 0000 2a40 0000 0000 0000 2b40 0000 0000 0000 2c40 0000 0000 0000 2d40 0000 0000 0 0000 2f40 0000 0000 0000 3040 0000 0000 0080 3040 0000 0000 0000 3140 0000 0000 0080 3140 0000 000 0000 0080 3240 0000 0000 0000 3340 0000 0000 0080 3340 0000 0000 0000 3440 0000 0000 0080 3440 000 0000 0000 0080 3540 0000 0000 0000 3640 0000 0000 0080 3640 0000 0000 0000 3740 0000 0000 0080 0 3840 0000 00000080 3840 0000 0000 0000 3940
Як перетворити число в рядок і навпаки C++
Починаючи зі стандарту C++11 перетворення рядка в число і навпаки вбудовані в стандартну бібліотеку. Усі наступні функції є (як зазначено в пункті 21.5).
рядок у числове
float stof(const string&str, size_t *idx = 0); double stod(const string&str, size_t *idx = 0); long double stold(const string& str, size_t *idx = 0); int stoi (const string & str, size_t * idx = 0, int base = 10); long stol (const string str, size_t * idx = 0, int base = 10); unsigned long stoul(const string& str, size_t *idx = 0, int base = 10); long long stoll (const string & str, size_t * idx = 0, int base = 10); unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);
Кожен з них приймає рядок як вхідний знак і намагатиметься перетворити його на число. Якщо не вдається створити допустиме число, наприклад, тому що числові дані відсутні або число знаходиться поза межами типу, викидається виняток ( std::invalid_argument або std::out_of_range ).
Якщо перетворення успішно і idx не дорівнює 0, idx міститиме індекс першого символу, який не був використаний для декодування. Це може бути індекс за останнім символом.
Нарешті, інтегральні типи дозволяють вказати базу, цифр більше 9 передбачається алфавіт ( a=10 до z=35 ). Ви можете знайти більше інформації про точне форматування, яке можна розібрати для чисел з плаваючою точкою, підписаних цілих чисел і непідписаних цілих чисел.
Нарешті, для кожної функції також є навантаження, яке приймає std::wstring як перший параметр.
числова до рядкової
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);
Це простіше, ви передаєте відповідний числовий тип і отримуєте рядок назад. Для варіантів форматування ви повинні повернутися до опції рядкових потоків C++03 та використовувати маніпулятори потоків, як пояснюється в іншій відповіді тут.
Як зазначено у коментарях, ці функції повертаються до стандартної точності мантиси, яка, ймовірно, не є максимальною. Якщо вам потрібно більше точності, краще також повернутися до інших процедур форматування рядків.
Також існують схожі функції, які називаються to_wstring, вони повертають std::wstring.
Як перетворити число в рядок C++03
- Не використовуйте функції itoa або itof тому, що вони нестандартні і тому не переносяться.
- Використовуйте рядкові потоки
#include //include this to use string streams #include int main() < int number = 1234; std::ostringstream ostr; //output string stream ostr
Зверніть увагу, що ви також можете використовувати рядкові потоки для перетворення чисел з плаваючою комою на рядок, а також для форматування рядка на свій розсуд, як і за допомогою cout
std::ostringstream ostr; float f = 1.2; int i = 3; ostr
#include #include int main() < float f = 1.2; int i = 42; std::string sf = boost::lexical_cast(f); //sf is "1.2" std::string si = boost::lexical_cast(i); //sf is "42" >
Як перетворити рядок на число C++03
- Найлегший варіант, успадкований від C, - це функції atoi (для цілих чисел (від алфавіту до цілого числа)) та atof (для значень з плаваючою точкою (від алфавіту до числа з плаваючою точкою)). Ці функції приймають рядок у стилі C як аргумент ( const char * ), і тому їх використання може вважатися не дуже гарною практикою на C++. У cplusplusplus.com є легко зрозуміла документація по atoi та atof, включаючи те, як вони поводяться у разі неправильного введення.Однак, посилання містить помилку в тому, що відповідно до стандарту, якщо вхідне число занадто велике, щоб поміститися в цільовий тип, поведінка не визначена.
#include //the standard C library header #include int main() < std::string si = "12"; std::string sf = "1.2"; int i = atoi(si.c_str()); //the c_str() function "converts" double f = atof(sf.c_str()); //std::string to const char* >
#include #include int main() < std::string inputString = "1234 12.3 44"; std::istringstream istr(inputString); int i1, i2; float f; istr >> i1 >> f >> i2; //i1 is 1234, f is 12.3, i2 is 44 >
#include #include int main() < std::string sf = "42.2"; std::string si = "42"; float f = boost::lexical_cast(sf); //f is 42.2 int i = boost::lexical_cast(si); //i is 42 >
У C++17 нові функції std::to_chars і std::from_chars вводяться в заголовку charconv.
std::to_chars є локально-незалежним, що не виділяє і не висуває.
Лише невеликий набір політик форматування, які використовуються іншими бібліотеками (наприклад, std::sprintf), надається.
Гарантія, що std::from_chars може відновити кожне значення з плаваючою точкою, форматоване to_chars, надається тільки в тому випадку, якщо обидві функції з однієї і тієї ж реалізації
// See en.cppreference.com for more information, including format control. #include #include #include #include #include using Type = /* Any fundamental type */ ; std::size_t buffer_size = /* . */; [[noreturn]] void report_and_exit(int ret, const char *output) noexcept < std::printf("%s\n", output); std::exit(ret); >void check(const std::errc &ec) noexcept < if (ec == std::errc::value_too_large) report_and_exit(1, "Failed"); >int main()
Хоча це не повністю реалізовано компіляторами, це безперечно буде реалізовано.
Я вкрав цей зручний клас звідкись тут на StackOverflow, щоб перетворити щось, що можна зробити потоковим, у рядок:
// make_string class make_string < public: template make_string& operator <<( T const & val ) < buffer_ << val; return *this; >operator std::string() const < return buffer_.str(); >private: std::ostringstream buffer_; >;
А потім ви використовуєте його як;
string str = make_string()
Також я використовую цю функцію для перетворення рядків на щось, що можна зробити потоковим, оскільки вона не дуже безпечна, якщо ви намагаєтеся розібрати рядок, що не містить числа; (і вона не така розумна, як остання)
// parse_string template RETURN_TYPE parse_string(const STRING_TYPE& str) < std::stringstream buf; buf > val; return val; >
int x = parse_string("78");
Ви також можете захотіти версії для рядків.
Якщо ви все ще проектуєте його як окрему функцію, простіше написати наївний і універсальний код.
string IntToStr(int n) <string res; bool s=n
#include #include using namespace std; int main()