字符串转数字 std::strtol & std::strtoll & std::strtoul & std::strtoull 函数原型 #include <cstdlib> long strtol ( const char *str, char **str_end, int base ) ;long long strtoll ( const char *str, char **str_end, int base ) ;unsigned long strtoul ( const char *str, char **str_end, int base ) ;unsigned long long strtoull ( const char *str, char **str_end, int base ) ;
#include <cwchar> long wcstol ( const wchar_t * str, wchar_t ** str_end, int base ) ;long long wcstoll ( const wchar_t * str, wchar_t ** str_end, int base ) ;unsigned long wcstoul ( const wchar_t * str, wchar_t ** str_end, int base ) ;unsigned long long wcstoull ( const wchar_t * str, wchar_t ** str_end, int base ) ;
说明 将 str 指向的字符串转换为整数
跳过任何空白字符,直到找到第一个非空白字符,然后获取尽可能多的有效的整数字符(基数为 base)。有效整数字符定义如下:
加号(+)或减号(-)
前置 0 表示 base 为 8(八进制)
前置 0x 或 0X,表示 base 为 16(十六进制)
一系列的“数字”(对于 base 大于 10 的还包括字母)
base 的有效值为 {0,2,3,…,36}。二进制的有效数字为 {0, 1},三进制的有效数字为 {0, 1, 2},以此类推。对于 base 大于 10 的情况,有效“数字”包括字母,11 进制包括 A(a),12 进制包括 B(b),…,36 进制包括 Z(z)。
如果 base 为 0,将自动检查进制。如果前缀是 0,则为 8 进制,如果前缀为 0x 或 0X,则为 16 进制,其他情况为 10 进制。
str_end 指向需要处理的字符的结尾的下一个字符,如果为空,则忽略。
如果 str 为空或者不满足转换要求,该函数将不会进行转换。
返回值
代码例子 #include <cerrno> #include <cstdlib> #include <iomanip> #include <iostream> #include <string> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::strtol(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [" << value << "]" ; } void test (const std::string &str) { errno = 0 ; char *p_end{nullptr }; print (str, std::strtol (str.c_str (), &p_end, 10 )); std::cout << ", p_end point to: [" << std::string (p_end) << "]" ; if (errno == ERANGE) { std::cout << ", [out of range]" ; } std::cout << '\n' ; } int main () { test (" 12345" ); test ("12345 " ); test (" 12345 " ); test ("12345.abc" ); test ("abc 12345" ); test ("12345123451" ); test ("-12345123451" ); }
代码输出结果
std::strtol(" 12345") = [12345], p_end point to: [] std::strtol("12345 ") = [12345], p_end point to: [ ] std::strtol(" 12345 ") = [12345], p_end point to: [ ] std::strtol("12345.abc") = [12345], p_end point to: [.abc] std::strtol("abc 12345") = [0], p_end point to: [abc 12345] std::strtol("12345123451") = [2147483647], p_end point to: [], [out of range] std::strtol("-12345123451") = [-2147483648], p_end point to: [], [out of range]
std::strtof & std::strtod & std::strtold 函数原型 #include <cstdlib> float strtof ( const char * str, char ** str_end ) ;double strtod ( const char * str, char ** str_end ) ;long double strtold ( const char * str, char ** str_end ) ;
#include <cwchar> float wcstof ( const wchar_t * str, wchar_t ** str_end ) ;double wcstod ( const wchar_t * str, wchar_t ** str_end ) ;long double wcstold ( const wchar_t * str, wchar_t ** str_end ) ;
说明 将 str 指向的字符串转换为浮点数
跳过任何空白字符,直到找到第一个非空白字符,然后获取尽可能多的有效的浮点数字符。浮点数字符定义如下:
十进制浮点表达式
加号(+)或减号(-)
可选包含小数点字符的十进制数字的非空序列
e 或 E 后跟可选的减号(-)或加号(+)以及非空的十进制数字序列
十六进制浮点表达式
加号(+)或减号(-)
0x 或 0X
可选包含小数点字符的十六进制数字的非空序列
p 或 P 后跟可选的减号(-)或加号(+)以及非空的十进制数字序列
无穷大表达式
加号(+)或减号(-)
INF 或 INFINITY(忽略大小写)
非数字表达式
加号(+)或减号(-)
NAN 或 NAN(char_sequence) (NAN 忽略大小写),char_sequence 只能包含数字、拉丁字母和下划线
str_end 指向需要处理的字符的结尾的下一个字符,如果为空,则忽略
16 进制浮点数也有指数表达方式。其指数表达形式和 10 进制的指数表达形式相似,只是将 e 换为了 p。但是意思略有不同。
对于 16 进制浮点数指数,xPn 表示 x 的 16 进制数乘以 $2^n$
返回值
代码例子 #include <cstdlib> #include <iomanip> #include <iostream> #include <string> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::strtof(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [" << value << "]" ; } void test (const std::string &str) { errno = 0 ; char *p_end{nullptr }; print (str, std::strtof (str.c_str (), &p_end)); std::cout << ", p_end point to: [" << std::string (p_end) << "]" ; if (errno == ERANGE) { std::cout << ", [out of range]" ; } std::cout << '\n' ; } int main () { test ("123.456789123" ); test ("-123.456789123" ); test ("1.2345e3" ); test ("1.2345e-3" ); test ("-1.2345e-3" ); test ("0x12.6" ); test ("0x12.6p3" ); test ("nan" ); test ("inf" ); }
代码输出结果
std::strtof("123.456789123") = [123.457], p_end point to: [] std::strtof("-123.456789123") = [-123.457], p_end point to: [] std::strtof("1.2345e3") = [1234.5], p_end point to: [] std::strtof("1.2345e-3") = [0.0012345], p_end point to: [] std::strtof("-1.2345e-3") = [-0.0012345], p_end point to: [] std::strtof("0x12.6") = [18.375], p_end point to: [] std::strtof("0x12.6p3") = [147], p_end point to: [] std::strtof("nan") = [nan], p_end point to: [] std::strtof("inf") = [inf], p_end point to: []
std::atoi & std::atol & std::atoll 函数原型 #include <cstdlib> int atoi ( const char *str) ;long atol ( const char *str) ;long long atoll ( const char *str) ;
说明 将 str 指向的字符串转换为整数
跳过任何空白字符,直到找到第一个非空白字符,然后获取尽可能多的有效的整数字符(基数为 base)。有效整数字符定义如下:
atoi 系列的函数的缺点:
当转换出现错误时,函数不会抛异常也不会报错
对于不执行转换时会返回零,对于原来字符串就是 0 是不好进行判断
返回值
如果成功,则直接返回转换后的数字类型数值
如果返回值超出类型的范围(out of range),返回值为未定义
如果不能执行转换,则返回 0
代码例子 #include <cstdlib> #include <iostream> #include <string> #include <iomanip> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::atoi(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [" << value << "]\n" ; } void test (const std::string& str) { print (str, std::atoi (str.c_str ())); } int main () { test ("12345" ); test ("123.45" ); test ("12345 with word" ); test ("words 12345" ); test (" 12345" ); test ("12345 " ); test (" 12345 " ); test ("12345123451" ); test ("-12345" ); }
代码输出结果
std::atoi("12345") = [12345] std::atoi("123.45") = [123] std::atoi("12345 with word") = [12345] std::atoi("words 12345") = [0] std::atoi(" 12345") = [12345] std::atoi("12345 ") = [12345] std::atoi(" 12345 ") = [12345] std::atoi("12345123451") = [2147483647] std::atoi("-12345") = [-12345]
std::atof 函数原型 #include <cstdlib> double atof (const char *str) ;
说明 这里 str 的定义同 std::strtof & std::strtod & std::strtold 中的定义,具体内容见上方:arrow_up:
返回值
如果成功,则直接返回转换后的数字类型数值
如果返回值超出类型的范围(out of range),返回值为未定义
如果不能执行转换,则返回 0.0
代码例子 #include <cstdlib> #include <iostream> #include <string> #include <iomanip> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::atof(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [" << value << "]\n" ; } void test (const std::string str) { print (str, std::atof (str.c_str ())); } int main () { test ("0.000000012345" ); test ("123.45" ); test ("1.2345 with word" ); test ("words 1.2345" ); test (" 12.345" ); test ("12.345 " ); test (" 12.345 " ); test ("-12.345" ); test ("12345123451" ); test ("15e16" ); test ("0x12.6p3" ); test ("INF" ); test ("NAN" ); }
代码输出结果
std::atof("0.000000012345") = [1.2345e-08] std::atof("123.45") = [123.45] std::atof("1.2345 with word") = [1.2345] std::atof("words 1.2345") = [0] std::atof(" 12.345") = [12.345] std::atof("12.345 ") = [12.345] std::atof(" 12.345 ") = [12.345] std::atof("-12.345") = [-12.345] std::atof("12345123451") = [1.23451e+10] std::atof("15e16") = [1.5e+17] std::atof("0x12.6p3") = [147] std::atof("INF") = [inf] std::atof("NAN") = [nan]
std::stoi & std::stol & std::stoll & std::stoul & std::stoull 函数原型 #include <string> int stoi ( const std::string& str, std::size_t * pos = nullptr , int base = 10 ) ;int stoi ( const std::wstring& str, std::size_t * pos = nullptr , int base = 10 ) ;long stol ( const std::string& str, std::size_t * pos = nullptr , int base = 10 ) ;long stol ( const std::wstring& str, std::size_t * pos = nullptr , int base = 10 ) ;long long stoll ( const std::string& str, std::size_t * pos = nullptr , int base = 10 ) ;long long stoll ( const std::wstring& str, std::size_t * pos = nullptr , int base = 10 ) ;unsigned long stoul ( const std::string& str, std::size_t * pos = nullptr , int base = 10 ) ;unsigned long stoul ( const std::wstring& str, std::size_t * pos = nullptr , int base = 10 ) ;unsigned long long stoull ( const std::string& str, std::size_t * pos = nullptr , int base = 10 ) ;unsigned long long stoull ( const std::wstring& str, std::size_t * pos = nullptr , int base = 10 ) ;
说明 stoi 系列的函数可以支持窄字符和宽字符字符串,其内部实现是调用的 strtol 系列的函数
stoi 调用 std::strtol(str.c_str(), &ptr, base) 和 std::wcstol(str.c_str(), &ptr, base)
stol 调用 std::strtol(str.c_str(), &ptr, base) 和 std::wcstol(str.c_str(), &ptr, base)
stoll 调用 std::strtoll(str.c_str(), &ptr, base) 和 std::wcstoll(str.c_str(), &ptr, base)
stoul 调用 std::strtoul(str.c_str(), &ptr, base) 和 std::wcstoul(str.c_str(), &ptr, base)
stoull 调用 std::strtoull(str.c_str(), &ptr, base) 和 std::wcstoull(str.c_str(), &ptr, base)
其中 str 字符串的定义和 std::strtol 系列函数中定义相同
如果 pos 不为空,字符串中第一个未处理的字符的索引将存储在 *pos 中,即 strtol 系列函数中 str_end 指向字符的索引
因为 stoi 系列的函数会抛出异常,所以在使用该系列函数式一定要注意加上 try .. catch .. 块
返回值
如果成功,则直接返回转换后的数字类型数值
如果失败,则会抛出异常
std::invalid_argument: 参数无效,不执行转换时抛出该异常
std::out_of_range: 转换后超出了指定类型的范围时抛出该异常
代码例子 #include <string> #include <iostream> #include <iomanip> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::stoi(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [" << value << "]" ; } void printException (const std::string &str, const std::exception& e) { std::string tmp = "std::stoi(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [exception: " << e.what () << "]\n" ; } void test (const std::string& str) { try { std::size_t pos{0 }; print (str, std::stoi (str, &pos, 10 )); std::cout << ", pos: " << pos << '\n' ; } catch (const std::exception& e) { printException (str, e); } } int main () { test ("45" ); test ("3.14159" ); test ("12345 with word" ); test ("word 12345" ); test ("12345123451" ); }
代码输出结果
std::stoi("45") = [45], pos: 2 std::stoi("3.14159") = [3], pos: 1 std::stoi("12345 with word") = [12345], pos: 5 std::stoi("word 12345") = [exception: invalid stoi argument] std::stoi("12345123451") = [exception: stoi argument out of range]
std::stof & std::stod & std::stold 函数原型 #include <string> float stof ( const std::string& str, std::size_t * pos = nullptr ) ;float stof ( const std::wstring& str, std::size_t * pos = nullptr ) ;double stod ( const std::string& str, std::size_t * pos = nullptr ) ;double stod ( const std::wstring& str, std::size_t * pos = nullptr ) ;long double stold ( const std::string& str, std::size_t * pos = nullptr ) ;long double stold ( const std::wstring& str, std::size_t * pos = nullptr ) ;
说明 stof 系列的函数可以支持窄字符和宽字符字符串,其内部实现是调用的 strtof 系列的函数
stof 调用 std::strtof(str.c_str(), &ptr) 和 std::wcstof(str.c_str(), &ptr)
stod 调用 std::strtod(str.c_str(), &ptr) 和 std::wcstod(str.c_str(), &ptr)
stold 调用 std::strtold(str.c_str(), &ptr) 和 std::wcstold(str.c_str(), &ptr)
其中 str 字符串的定义和 std::strtof 系列函数中定义相同
如果 pos 不为空,字符串中第一个未处理的字符的索引将存储在 *pos 中,即 strtof 系列函数中 str_end 指向字符的索引
因为 stof 系列的函数会抛出异常,所以在使用该系列函数式一定要注意加上 try .. catch .. 块
返回值
如果成功,则直接返回转换后的数字类型数值
如果失败,则会抛出异常
std::invalid_argument: 参数无效,不执行转换时抛出该异常
std::out_of_range: 转换后超出了指定类型的范围时抛出该异常
代码例子 #include <string> #include <iostream> #include <iomanip> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::stof(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [" << value << "]" ; } void printException (const std::string &str, const std::exception& e) { std::string tmp = "std::stof(\"" + str + "\") " ; std::cout << std::setw (30 ) << std::left << tmp << "= [exception: " << e.what () << "]\n" ; } void test (const std::string& str) { try { std::size_t pos{0 }; print (str, std::stof (str, &pos)); std::cout << ", pos: " << pos << '\n' ; } catch (const std::exception& e) { printException (str, e); } } int main () { test ("123.456789123" ); test ("-123.456789123" ); test ("1.2345e3" ); test ("1.2345e-3" ); test ("-1.2345e-3" ); test ("0x12.6" ); test ("0x12.6p3" ); }
代码输出结果
std::stof("123.456789123") = [123.457], pos: 13 std::stof("-123.456789123") = [-123.457], pos: 14 std::stof("1.2345e3") = [1234.5], pos: 8 std::stof("1.2345e-3") = [0.0012345], pos: 9 std::stof("-1.2345e-3") = [-0.0012345], pos: 10 std::stof("0x12.6") = [18.375], pos: 6 std::stof("0x12.6p3") = [147], pos: 8
使用 std::stringstream #include <iostream> #include <sstream> #include <iomanip> template <typename T>void string_to_number (const std::string& str, T& number) { std::stringstream ss; ss << str; ss >> number; std::cout << "stringstream " << std::setw (7 ) << std::left << typeid (number).name () << " (" << std::quoted (str) << ") = [" << number << "]\n" ; } template <typename T>void test (const std::string& str) { T number; string_to_number (str, number); } int main () { test <int >("12345" ); test <int >("-12345" ); test <int >("12345abc" ); test <int >(" 12345 abc" ); test <float >("123.456789123" ); test <float >("-123.456789123" ); test <float >("1.2345e3" ); test <float >("1.2345e-3" ); test <float >("0x12.6" ); test <float >("0x12.6p3" ); }
代码输出结果
stringstream int ("12345") = [12345] stringstream int ("-12345") = [-12345] stringstream int ("12345abc") = [12345] stringstream int (" 12345 abc") = [12345] stringstream float ("123.456789123") = [123.457] stringstream float ("-123.456789123") = [-123.457] stringstream float ("1.2345e3") = [1234.5] stringstream float ("1.2345e-3") = [0.0012345] stringstream float ("0x12.6") = [0] stringstream float ("0x12.6p3") = [0]
std::from_chars (c++ 17) 函数原型 #include <charconv> struct from_chars_result { const char * ptr; std::errc ec; }; enum class chars_format { scientific = , fixed = , hex = , general = fixed | scientific }; std::from_chars_result from_chars (const char * first, const char * last, & value, int base = 10 ) ;std::from_chars_result from_chars (const char * first, const char * last, float & value, std::chars_format fmt = std::chars_format::general) ;std::from_chars_result from_chars (const char * first, const char * last, double & value, std::chars_format fmt = std::chars_format::general) ;std::from_chars_result from_chars (const char * first, const char * last, long double & value, std::chars_format fmt = std::chars_format::general) ;
说明 解析满足指定模式的字符序列 [first, last)。如果没有字符与模式匹配,或者通过解析匹配字符获得的值在值的类型中无法表示,value 不会被修改,否则,匹配模式的字符将被转换为对应的类型的值,保存在 value 中。
具体的模式如下:
该系列的函数不会抛出异常(non-throwing),与语言环境无关(locale-independent),不会分配内存(non-allocating)
需要注意的点:
不支持前置空格
不支持加号(+)开始
对于 16 进制的浮点数,不支持前置的 0x 和 0X
对于浮点数,如果设置 fmt 为 std::chars_format::scientific,则字符串中必须表示为科学计数表达式(包含 e 和 E 部分)
返回值
转换成功,std::from_chars_result 中 ptr 指向与模式不匹配的第一个字符或者 last,value 为转换后的值
如果一个也不匹配(不能转换),std::from_chars_result 中 ptr 指向 first,ec 为 std::errc::incalid_argument,value 值保持不变
如果转换后数值超出了返回值类型的范围,则 std::from_chars_result 中 ptr 指向 first,ec 为 std::errc::result_out_of_range,value 保持不变
性能
On GCC it’s around 4.5x faster than stoi, 2.2x faster than atoi and almost 50x faster than istringstream.
On Clang it’s around 3.5x faster than stoi, 2.7x faster than atoi and 60x faster than istringstream!
MSVC performs around 3x faster than stoi, ~2x faster than atoi and almost 50x faster than istringstream
代码例子 #include <charconv> #include <iostream> #include <string> #include <string_view> #include <iomanip> template <typename T>void print (const std::string &str, const T &value) { std::string tmp = "std::from_chars(\"" + str + "\") " ; std::cout << std::setw (35 ) << std::left << tmp << "= [" << value << "]" ; } template <typename T>void test_integer (const std::string &str, int base = 10 ) { T result; auto [p, ec] = std::from_chars (str.data (), str.data () + str.size (), result, base); if (ec == std::errc ()) { print (str, result); std::cout << ", p point to [" << p << "]" ; } else if (ec == std::errc::invalid_argument) { print (str, "invalid argument" ); std::cout << ", p point to [" << p << "]" ; } else if (ec == std::errc::result_out_of_range) { print (str, "result out of range" ); std::cout << ", p point to [" << p << "]" ; } std::cout << '\n' ; } template <typename T>void test_float (const std::string &str, std::chars_format fmt = std::chars_format::general) { T result; auto [p, ec] = std::from_chars (str.data (), str.data () + str.size (), result, fmt); if (ec == std::errc ()) { print (str, result); std::cout << ", p point to [" << p << "]" ; } else if (ec == std::errc::invalid_argument) { print (str, "invalid argument" ); std::cout << ", p point to [" << p << "]" ; } else if (ec == std::errc::result_out_of_range) { print (str, "result out of range" ); std::cout << ", p point to [" << p << "]" ; } std::cout << '\n' ; } int main () { test_integer <int >("12345" ); test_integer <int >(" 12345" ); test_integer <int >("12345 " ); test_integer <int >(" 12345 " ); test_integer <int >("12345 with word" ); test_integer <int >("word 12345" ); test_integer <int >("+12345" ); test_integer <int >("-12345" ); test_integer <int >("12" , 16 ); test_integer <int >("0x12" , 16 ); test_float <float >("123.456789123" ); test_float <float >("-123.456789123" ); test_float <float >("1.2345e3" ); test_float <float >("1.2345e-3" ); test_float <float >("1.2345e+3" ); test_float <float >("12.6" , std::chars_format::hex); test_float <float >("12.6p3" , std::chars_format::hex); }
代码输出结果
std::from_chars("12345") = [12345], p point to [] std::from_chars(" 12345") = [invalid argument], p point to [ 12345] std::from_chars("12345 ") = [12345], p point to [ ] std::from_chars(" 12345 ") = [invalid argument], p point to [ 12345 ] std::from_chars("12345 with word") = [12345], p point to [ with word] std::from_chars("word 12345") = [invalid argument], p point to [word 12345] std::from_chars("+12345") = [invalid argument], p point to [+12345] std::from_chars("-12345") = [-12345], p point to [] std::from_chars("12") = [18], p point to [] std::from_chars("0x12") = [0], p point to [x12] std::from_chars("123.456789123") = [123.457], p point to [] std::from_chars("-123.456789123") = [-123.457], p point to [] std::from_chars("1.2345e3") = [1234.5], p point to [] std::from_chars("1.2345e-3") = [0.0012345], p point to [] std::from_chars("1.2345e+3") = [1234.5], p point to [] std::from_chars("12.6") = [18.375], p point to [] std::from_chars("12.6p3") = [147], p point to []
数字转字符串 std::to_string & std::to_wstring 函数原型 std::string to_string ( int value ) ;std::string to_string ( long value ) ;std::string to_string ( long long value ) ;std::string to_string ( unsigned value ) ;std::string to_string ( unsigned long value ) ;std::string to_string ( unsigned long long value ) ;std::string to_string ( float value ) ;std::string to_string ( double value ) ;std::string to_string ( long double value ) ;
说明
对于浮点类型 std::to_string 可能会产生意外的结果,因为返回的字符串中的有效位数可能为零
std::to_string 依赖当前语言环境进行格式化,因此从多个线程并发调用 std::to_string 可能导致部分序列化
代码例子 #include <iostream> #include <string> #include <iomanip> template <typename T>void test (T value) { std::string str = std::to_string (value); std::cout << "std::to_string(\"" << value << "\") = [" << str << "]\n" ; std::wstring wstr = std::to_wstring (value); std::wcout << L"std::to_wstring(\"" << value << L"\") = [" << wstr << L"]\n" ; } int main () { test (12345 ); test (-12345 ); test (123.45 ); test (1.23e3 ); test (1e-20 ); test (1e30 ); }
代码输出结果
std::to_string("12345") = [12345] std::to_wstring("12345") = [12345] std::to_string("-12345") = [-12345] std::to_wstring("-12345") = [-12345] std::to_string("123.45") = [123.450000] std::to_wstring("123.45") = [123.450000] std::to_string("1230") = [1230.000000] std::to_wstring("1230") = [1230.000000] std::to_string("1e-20") = [0.000000] std::to_wstring("1e-20") = [0.000000] std::to_string("1e+30") = [1000000000000000019884624838656.000000] std::to_wstring("1e+30") = [1000000000000000019884624838656.000000]
sprintf & snprintf & sprintf_s & snprintf_s 函数原型 #include <cstdio> int sprintf ( char *restrict buffer, const char *restrict format, ... ) ;int snprintf ( char *restrict buffer, size_t bufsz, const char *restrict format, ... ) ;int sprintf_s (char *restrict buffer, rsize_t bufsz, const char *restrict format, ...) ;int snprintf_s (char *restrict buffer, rsize_t bufsz, const char *restrict format, ...) ;
说明 格式字符串由普通的多字节字符组成(% 除外),并按指定的格式进行转换:
转换字符
描述
%
格式转换标志,如果想要转换为 %,需要使用 %%
c
单个字符
s
字符串
d & i
十进制带符号数
o
八进制无符号数
x & X
十六进制无符号数
u
十进制无符号数
f & F
十进制浮点数
e & E
十进制指数浮点数
a & A
十六进制浮点数
g & G
十进制浮点数或十进制指数浮点数
浮点转换函数将无穷大转换为 inf 或 infinity。使用哪一个是实现定义的
非数字转换为 nan 或 nan(char_sequence)
返回 sprintf: 写入缓冲区的字符数(不包括终止空字符),如果发生编码错误(对于字符串和字符转换说明符),则为负值snprintf: 如果忽略 bufsz,返回为将写入缓冲区的字符数(不包括终止空字符),或者如果发生编码错误(对于字符串和字符转换说明符)则为负值sprintf_s: 写入缓冲区的字符数,不包括空字符(只要缓冲区不是空指针并且 bufsz 不为零且不大于 RSIZE_MAX),或运行时约束违规为零,编码错误为负值snprintf_s: 不包括终止空字符的字符数(只要缓冲区不是空指针并且 bufsz 不为零且不大于 RSIZE_MAX,则始终写入),如果 bufsz 被忽略,它将被写入缓冲区,如果运行时约束违反或编码错误发生,则为负值
代码例子 #include <cstdio> #include <iostream> #include <iomanip> int main () { std::cout << std::setw (8 ) << std::left << "format" << std::setw (2 ) << "n" << " " << " string" << '\n' ; std::cout << std::setw (20 ) << std::setfill ('-' ) << '-' << std::setfill (' ' )<< std::endl; char buf[30 ] = {"" }; int n = sprintf (buf, "%d" , 12345 ); std::cout << std::setw (8 ) << std::left << "%d:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%d" , -12345 ); std::cout << std::setw (8 ) << std::left << "%d:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%x" , 256 ); std::cout << std::setw (8 ) << std::left << "%x:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%o" , 256 ); std::cout << std::setw (8 ) << std::left << "%o:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%f" , 12.345 ); std::cout << std::setw (8 ) << std::left << "%f:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%.4f" , 12.345 ); std::cout << std::setw (8 ) << std::left << "%.4f:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%.4f" , 12.345 ); std::cout << std::setw (8 ) << std::left << "%.4f:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%e" , 1234.5 ); std::cout << std::setw (8 ) << std::left << "%e:" << std::setw (2 ) << n << " " << buf << '\n' ; n = sprintf (buf, "%.4a" , 147.0 ); std::cout << std::setw (8 ) << std::left << "%.4a:" << std::setw (2 ) << n << " " << buf << '\n' ; }
代码输出结果
format n string -------------------- %d: 5 12345 %d: 6 -12345 %x: 3 100 %o: 3 400 %f: 9 12.345000 %.4f: 7 12.3450 %.4f: 7 12.3450 %e: 12 1.234500e+03 %.4a: 11 0x1.2600p+7
to_chars 函数原型 #include <charconv> struct to_chars_result { char * ptr; std::errc ec; }; enum class chars_format { scientific = , fixed = , hex = , general = fixed | scientific }; std::to_chars_result to_chars (char * first, char * last, value, int base = 10 ) ;std::to_chars_result to_chars (char *, char *, bool , int = 10 ) = delete ;std::to_chars_result to_chars (char * first, char * last, float value) ;std::to_chars_result to_chars (char * first, char * last, double value) ;std::to_chars_result to_chars (char * first, char * last, long double value) ;std::to_chars_result to_chars (char * first, char * last, float value, std::chars_format fmt) ;std::to_chars_result to_chars (char * first, char * last, double value, std::chars_format fmt) ;std::to_chars_result to_chars (char * first, char * last, long double value, std::chars_format fmt) ;std::to_chars_result to_chars (char * first, char * last, float value, std::chars_format fmt, int precision) ;std::to_chars_result to_chars (char * first, char * last, double value, std::chars_format fmt, int precision) ;std::to_chars_result to_chars (char * first, char * last, long double value, std::chars_format fmt, int precision) ;
说明 将 value 值填充范围到[first, last) 指向的字符串,其中 [first, last) 必须是有效范围
返回
成功时,返回 to_chars_result 类型的值,其中 ec 等于值初始化的 std::errc,ptr 是写入字符结尾的后一个指针。请注意,该字符串不是以 NUL 结尾的
出错时,返回 to_chars_result 类型的值,其中 ec 等于 std::errc::value_too_large
代码例子 #include <iostream> #include <charconv> #include <string_view> #include <iomanip> #include <string> template <typename T>void print (T value, std::string_view str) { std::cout << "std::to_chars(" << std::setw (15 ) << std::right << std::setprecision (12 ) << value << ") = [" << str << "]\n" ; } template <typename T>void test_integer (std::string& str, T value, int base = 10 ) { auto [p, ec] = std::to_chars (str.data (), str.data () + str.size (), value, base); if (ec == std::errc ()) { print (value, std::string_view (str.data (), p - str.data ())); } else if (ec == std::errc::value_too_large) { print (value, str); } } template <typename T>void test_float (std::string& str, T value, std::chars_format fmt = std::chars_format::general) { auto [p, ec] = std::to_chars (str.data (), str.data () + str.size (), value, fmt); if (ec == std::errc ()) { print (value, std::string_view (str.data (), p - str.data ())); } else if (ec == std::errc::value_too_large) { print (value, str); } } template <typename T>void test_float_precision (std::string& str, T value, std::chars_format fmt = std::chars_format::general, int precision = 6 ) { auto [p, ec] = std::to_chars (str.data (), str.data () + str.size (), value, fmt, precision); if (ec == std::errc ()) { print (value, std::string_view (str.data (), p - str.data ())); } else if (ec == std::errc::value_too_large) { print (value, str); } } int main () { std::string str; str.resize (20 ); test_integer (str, 12345 ); test_integer (str, -12345 ); test_integer (str, 100 , 8 ); test_float (str, 123.456789123 ); test_float_precision (str, 123.456789123 , std::chars_format::general, 6 ); test_float (str, -123.456789123 ); test_float (str, 1234.5 ); test_float (str, 18.375 , std::chars_format::hex); test_float (str, 147.0 , std::chars_format::hex); }
代码输出结果
format n string -------------------- %d: 5 12345 %d: 6 -12345 %x: 3 100 %o: 3 400 %f: 9 12.345000 %.4f: 7 12.3450 %.4f: 7 12.3450 %e: 12 1.234500e+03 %.4a: 11 0x1.2600p+7