C++字符串和数字相互转换的多种方法(附带实例)
数值类型和字符串类型之间的转换是一种普遍存在的操作。在 C++11 之前,几乎不支持数值类型和字符串的转换,所以开发人员不得不主要依靠类型不安全的函数,他们通常编写自己的实用函数,以避免一遍又一遍地编写相同的代码。
在 C++11 中,标准库提供了用于数字和字符串之间转换的实用函数。在本节中,你将学习如何使用现代 C++ 标准库函数在数字和字符串之间进行转换。
当需要在数字和字符串之间进行转换时,请使用以下标准转换函数:
1) 要将整数或浮点类型转换为字符串类型,请使用 std::to_string() 或者 std::to_wstring(),如以下代码片段所示:
2) 要将字符串类型转换为整数类型,请使用 std::stoi()、std::stol()、std::stoll()、std::stoul() 或 std::stoull(),如以下代码片段所示:
3) 要将字符串类型转换为浮点类型,请使用 std::stof()、std::stod() 或 std::stold(),如以下代码片段所示:
将整数类型或浮点类型转换为字符串类型,可以使用 std::to_string() 函数(它将转换为 std::string)或者 std::to_wstring() 函数(它将转换为 std::wstring)。下面的代码片段列出了这两个函数的所有重载:
当涉及相反的转换时,有一组名称格式为 ston(代表 string to number)的函数,其中 n 代表(代表 integer)、l(代表 long)、ll(代表 long long)、ul(代表 unsigned long)或 ull(代表 unsigned long long),以此类推。
下面列出了这些函数,每个函数都有两个重载版本:其中一个将 std::string 作为第一个参数,另一个将 std::wstring 作为第一个参数。
在以下所有示例中,结果都是整数 42(最后一个示例除外,它的结果是 -42):
仅当指定的基数为 8 或 0 时,才应用可选前缀 0(用于八进制);类似地,仅当指定的基数为 16 或 0 时,才应用可选前缀 0x 或 0X(用于十六进制)。
将字符串转换为整数的函数有三个参数:
输入字符串中的有效数字取决于进制。对于二进制,唯一有效的数字是 0 和 1;对于 5 进制,它们是 0~4;对于 11 进制,有效数字是 0~9 以及字符 A 和 a;这可以一直持续到 36 进制,其中包含有效字符 0~9、A~Z 和 a~z。
下面是将不同进制的数字字符串转换为十进制整数的其他示例。同样,最终计算结果都是 42 或 -42:
1) std::invalid_argument:不能进行转换时抛出。
2) std::out_of_range:转换后的值超出结果类型所能表示的范围(或者底层函数将 errno 设置为 ERANGE)时抛出。
另一组将字符串转换为浮点类型的函数也类似,只是它们没有表示进制的参数。一个有效的浮点数值可以在输入字符串中有不同表示形式:
以下是将字符串转换为双精度浮点数的各种示例:
转换为十进制的值通过有效值(由整数和小数部分组成)与基数的指数幂相乘确定。
对于上述给定的二进制浮点数字面量的十六进制表示,有效值为 15.4312499…(请注意第七位数字后的数字没有显示),基数是 2,指数是 3。因此,结果是 15.4312499…*8,即 123.44999980926514。
在 C++11 中,标准库提供了用于数字和字符串之间转换的实用函数。在本节中,你将学习如何使用现代 C++ 标准库函数在数字和字符串之间进行转换。
本节中提到的所有实用函数都可以在头文件<string>中找到。
当需要在数字和字符串之间进行转换时,请使用以下标准转换函数:
1) 要将整数或浮点类型转换为字符串类型,请使用 std::to_string() 或者 std::to_wstring(),如以下代码片段所示:
auto si = std::to_string(42); // si="42" auto sl = std::to_string(42L); // sl="42" auto su = std::to_string(42u); // su="42" auto sd = std::to_wstring(42.0); // sd="42.000000" auto sld = std::to_wstring(42.0L); // sld="42.000000"
2) 要将字符串类型转换为整数类型,请使用 std::stoi()、std::stol()、std::stoll()、std::stoul() 或 std::stoull(),如以下代码片段所示:
auto i1 = std::stoi("42"); auto i2 = std::stoi("101010", nullptr, 2); // i2 = 42 auto i3 = std::stoi("052", nullptr, 8); // i3 = 42 auto i4 = std::stoi("0x2A", nullptr, 16); // i4 = 42
3) 要将字符串类型转换为浮点类型,请使用 std::stof()、std::stod() 或 std::stold(),如以下代码片段所示:
// d1 = 123.4500000000000 auto d1 = std::stof("123.45"); // d2 = 123.4500000000000 auto d2 = std::stod("1.2345e+2"); // d3 = 123.44999880926514 auto d3 = std::stod("0xF.6E6666p3");
将整数类型或浮点类型转换为字符串类型,可以使用 std::to_string() 函数(它将转换为 std::string)或者 std::to_wstring() 函数(它将转换为 std::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::wstring to_wstring(int value); std::wstring to_wstring(long value); std::wstring to_wstring(long long value); std::wstring to_wstring(unsigned value); std::wstring to_wstring(unsigned long value); std::wstring to_wstring(unsigned long long value); std::wstring to_wstring(float value); std::wstring to_wstring(double value); std::wstring to_wstring(long double value);这些函数在头文件
<string>
中,并且具有用于有符号和无符号整数以及实数类型的重载。因为每种类型使用适当的格式说明符调用时,它们会产生与 std::sprintf() 或者 std::swprintf() 函数相同的效果。当涉及相反的转换时,有一组名称格式为 ston(代表 string to number)的函数,其中 n 代表(代表 integer)、l(代表 long)、ll(代表 long long)、ul(代表 unsigned long)或 ull(代表 unsigned long long),以此类推。
下面列出了这些函数,每个函数都有两个重载版本:其中一个将 std::string 作为第一个参数,另一个将 std::wstring 作为第一个参数。
int stoi(const std::string& str, std::size_t* pos = 0, int base = 10); int stoi(const std::wstring& str, std::size_t* pos = 0, int base = 10); long stol(const std::string& str, std::size_t* pos = 0, int base = 10); long stol(const std::wstring& str, std::size_t* pos = 0, int base = 10); long long stoll(const std::string& str, std::size_t* pos = 0, int base = 10); long long stoll(const std::wstring& str, std::size_t* pos = 0, int base = 10); unsigned long stoul(const std::string& str, std::size_t* pos = 0, int base = 10); unsigned long stoul(const std::wstring& str, std::size_t* pos = 0, int base = 10); unsigned long long stoull(const std::string& str, std::size_t* pos = 0, int base = 10); unsigned long long stoull(const std::wstring& str, std::size_t* pos = 0, int base = 10); float stof(const std::string& str, std::size_t* pos = 0); float stof(const std::wstring& str, std::size_t* pos = 0); double stod(const std::string& str, std::size_t* pos = 0); double stod(const std::wstring& str, std::size_t* pos = 0); long double stold(const std::string& str, std::size_t* pos = 0); long double stold(const std::wstring& str, std::size_t* pos = 0);将字符串转换为整数类型的函数是丢弃非空格字符前的所有空格字符,然后尽可能多地提取字符以形成有符号或无符号数字(取决于具体情况),然后将其转换为请求的整数类型(stoi() 将返回一个整数,stoul() 将返回一个无符号长整型类型,以此类推)。
在以下所有示例中,结果都是整数 42(最后一个示例除外,它的结果是 -42):
auto i1 = std::stoi("42"); // i1 = 42 auto i2 = std::stoi(" 42"); // i2 = 42 auto i3 = std::stoi(" 42fortytwo"); // i3 = 42 auto i4 = std::stoi("+42"); // i4 = 42 auto i5 = std::stoi("-42"); // i5 = -42有效整数由以下部分组成:
- 符号,+ 或 -(可选);
- 前缀 0 表示八进制(可选);
- 前缀 0x 或 0X 表示十六进制(可选);
- 数字序列。
仅当指定的基数为 8 或 0 时,才应用可选前缀 0(用于八进制);类似地,仅当指定的基数为 16 或 0 时,才应用可选前缀 0x 或 0X(用于十六进制)。
将字符串转换为整数的函数有三个参数:
- 输入字符串;
- 指针,当它不为空时,将接收已处理的字符数,这可能包括任何被丢弃的前导空格、符号位和进制前缀,因此它不应与整数值的位数混淆;
- 表示进制的数字,默认情况下是 10。
输入字符串中的有效数字取决于进制。对于二进制,唯一有效的数字是 0 和 1;对于 5 进制,它们是 0~4;对于 11 进制,有效数字是 0~9 以及字符 A 和 a;这可以一直持续到 36 进制,其中包含有效字符 0~9、A~Z 和 a~z。
下面是将不同进制的数字字符串转换为十进制整数的其他示例。同样,最终计算结果都是 42 或 -42:
auto i6 = std::stoi("052", nullptr, 8); auto i7 = std::stoi("052", nullptr, 0); auto i8 = std::stoi("0x2A", nullptr, 16); auto i9 = std::stoi("0x2A", nullptr, 0); auto i10 = std::stoi("101010", nullptr, 2); auto i11 = std::stoi("22", nullptr, 20); auto i12 = std::stoi("-22", nullptr, 20); auto pos = size_t{ 0 }; auto i13 = std::stoi("42", &pos); // pos = 2 auto i14 = std::stoi("-42", &pos); // pos = 3 auto i15 = std::stoi(" +42dec", &pos);// pos = 5需要重点注意的是,如果转换失败,这些转换函数会抛出异常。它们可以抛出以下两种异常:
1) std::invalid_argument:不能进行转换时抛出。
try { auto i16 = std::stoi(""); } catch (std::exception const & e) { // prints "invalid stoi argument" std::cout << e.what() << '\n'; }
2) std::out_of_range:转换后的值超出结果类型所能表示的范围(或者底层函数将 errno 设置为 ERANGE)时抛出。
try { // OK auto i17 = std::stoi("12345678901234"); // throws std::out_of_range auto i18 = std::stoi("12345678901234"); } catch (std::exception const & e) { // prints "stoi argument out of range" std::cout << e.what() << '\n'; }
另一组将字符串转换为浮点类型的函数也类似,只是它们没有表示进制的参数。一个有效的浮点数值可以在输入字符串中有不同表示形式:
- 十进制浮点表达式(包含可选符号、带可选点的十进制数字序列、可选 e 或 E,后跟带有可选符号的指数)。
- 二进制浮点表达式(包含可选符号、0x 或 0X 前缀、带可选点的十六进制数字序列、可选 p 或 P,后跟带可选符号的指数)。
- 无限表达式(包含可选符号,后跟不区分大小写的 INF 或 INFINITY)。
- 非数字表达式(包含可选符号,后跟不区分大小写的 NAN 和可能的其他字母数字字符)。
以下是将字符串转换为双精度浮点数的各种示例:
auto d1 = std::stod("123.45"); // d1 = 123.450000000000 auto d2 = std::stod("+123.45"); // d2 = 123.450000000000 auto d3 = std::stod("-123.45"); // d3 = -123.450000000000 auto d4 = std::stod(" 123.45"); // d4 = 123.450000000000 auto d5 = std::stod(" -123.45abc"); // d5 = -123.450000000000 auto d6 = std::stod("1.2345e+2"); // d6 = 123.450000000000 auto d7 = std::stod("0xF.6E6666p3"); // d7 = 123.44999880926514 auto d8 = std::stod("INF"); // d8 = inf auto d9 = std::stod("-infinity"); // d9 = -inf auto d10 = std::stod("NAN"); // d10 = nan auto d11 = std::stod("-nanac"); // d11 = -nan二进制科学计数法中的浮点常数由以下几个部分组成:
- 16 进制前缀 0x;
- 整数部分,在本例中为 F,即十进制的 15;
- 小数部分,在本例中是6E6666或二进制的 011011100110011001100110,为了将其转换为小数,我们需要将 2 的幂的倒数相加,即 1/4+1/8+1/32+1/64+1/128+…;
- 后缀,代表 2 的幂,在本例中,p3 表示 2 的 3 次方。
转换为十进制的值通过有效值(由整数和小数部分组成)与基数的指数幂相乘确定。
对于上述给定的二进制浮点数字面量的十六进制表示,有效值为 15.4312499…(请注意第七位数字后的数字没有显示),基数是 2,指数是 3。因此,结果是 15.4312499…*8,即 123.44999980926514。