c17 新特性 字符串和数字转换 charconv

理论

传统字符串转换

下面列出几种常用的方法:

  1. std::stoi() 更加安全,因为它会抛出异常,但无法处理前导空白字符。
  2. std::stringstream 更加灵活,可以处理前导空白字符,但性能略差。
  3. std::atoi() 简单快速,但不会抛出异常,如果无法转换会返回 0。
  4. std::strtol() 可以处理更复杂的情况,如指定进制,并返回转换过程中遇到的第一个无法转换的字符
std::stoi() 函数可以将 std::string 类型转换为 int 类型。如果无法转换,将抛出 std::invalid_argument 异常。
示例:
std::string str = "42";
int num = std::stoi(str);

使用 std::stringstream 可以先将 std::string 类型的字符串转换为 std::stringstream 流,然后通过 >> 运算符将其提取到 int 类型的变量中。
示例:
std::string str = "42";
int num;
std::stringstream ss(str);
ss >> num;

std::atoi() 函数可以将 C 风格的字符串(即 const char*)转换为 int 类型。需要注意的是,它不会抛出任何异常,如果无法转换,将返回 0。
示例:
std::string str = "42";
char* endptr;
int num = static_cast<int>(std::strtol(str.c_str(), &endptr, 10));

std::strtol() 函数可以将 C 风格的字符串(即 const char*)转换为 long 类型。它还可以返回转换过程中遇到的第一个无法转换的字符。上述代码中的 endptr 指针指向了转换过程中遇到的第一个无法转换的字符。、
示例:
std::string str = "42";
char* endptr;
int num = static_cast<int>(std::strtol(str.c_str(), &endptr, 10));

所以根据上述,大家能够大致明白,传统模式下的字符串转换,接口多,功能参差不齐,要性能没安全,要安全没性能。所以本次讨论的charconv解决这类问题。

新字符串转换

std::to_charsstd::from_chars是C++17引入的两个非常有用的函数,它们可以帮助我们在C++中更高效地进行数字和字符串之间的转换

std::from_chars 它具有以下特点:

  1. 更快速高效std::from_chars 是直接使用底层 C 标准库的转换函数实现的,因此性能更优。
  2. 更好的异常处理: 与 std::stoi() 类似,std::from_chars 也会在转换失败时返回一个错误码,而不是抛出异常。
  3. 无需手动检查std::from_chars 会自动检查转换是否成功,开发者只需要检查返回值即可。
  4. 无需中间转换std::from_chars 可以直接从 std::string_view 或 C 风格字符串转换,不需要先转换为 std::string

std::to_chars  它可以将 intfloat 或 double 类型的值转换为字符串。它与前面提到的 std::from_chars 函数是相对应的。

下面让我们具体了解一下 std::to_chars 的用法和特点:

  1. 简单高效std::to_chars 是直接使用底层 C 标准库的转换函数实现的,因此性能较优。
  2. 无需中间转换std::to_chars 可以直接将值转换为 C 风格字符串,不需要先转换为 std::string
  3. 返回错误码: 与 std::from_chars 类似, std::to_chars 也会返回一个错误码,表示转换是否成功。
  4. 支持浮点数转换: 除了整数类型,std::to_chars 还支持 float 和 double 类型的转换。

实践 

使用to_chars数字转字符串,再使用from_chars转回字符串。

#include <charconv>  //新版本头文件
#include <iostream>
#include <string_view>

std::string_view int_toString(int value, char *buffer, size_t size) {
  // ptr 转换后返回的时缓冲区结束的位置
  auto [ptr, err] = std::to_chars(buffer, buffer + size, value);
  if (err != std::errc{})
    return {};
  return {buffer, static_cast<size_t>(ptr - buffer)};
}
int main() {
  char buff[20];
  int value = 2333;

  std::string_view result = int_toString(value, buff, sizeof(buff));
  if (result.empty()) {
    std::cerr << "转换失败\n";
    return 1;
  }
  std::cout << "int :" << value << "  string  " << result << "  buff  " << buff;

  int conv = 0;
  auto [_, err] =
      std::from_chars(result.data(), result.data() + result.size(), conv);
  if (err != std::errc{}) {
    std::cerr << "Error converting string to integer." << std::endl;
    return 1;
  }
  std::cout << "\nConverted integer value: " << conv << std::endl;

  return 0;
}

输出 


int :2333  string  2333  buff  2333
Converted integer value: 2333

总结

这两个函数的主要优点包括:

  1. 性能优化: 通过避免创建临时的std::string对象,可以大幅提高数字和字符串之间转换的效率。

  2. 出错处理: 这些函数返回一个由指针和错误代码组成的结构体,可以帮助开发者更好地处理转换过程中可能出现的错误。

  3. 灵活性: 这些函数可以与各种数值类型和字符串表示一起使用,提高了代码的通用性和可复用性。

总的来说,std::to_charsstd::from_chars是C++17中非常有价值的新特性,它们可以帮助开发者编写更高效、更安全的数字和字符串转换代码。对于需要频繁进行这种转换的应用程序来说,使用这些函数可以带来显著的性能优势。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值