字符串转数字 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