std::stoi 是如何实现的?

How is std::stoi implemented?

本文关键字:实现 何实现 stoi std      更新时间:2023-10-16

大多数日常用例已经转换为标准库中可用的函数。但是,我想知道其中一些人在幕后是如何工作的。比如std::stoi背后的实际代码是什么?

最直接的方法是调用适当的 C 函数,在本例中为strtol,检查发生了什么,如果失败,则抛出适当的异常,然后返回结果。

我想知道其中一些是如何在幕后工作的。喜欢什么 标准::stoi 背后的实际代码?

我认为您可以通过执行类似于以下内容的搜索来找到"实际"代码:

  • 在 Ubuntu 上,我的 makefile 创建一个 .depends 文件,其中包含:

    g++-5 -m64 -O3 -ggdb -std=c++14 -wall -wextra -wshadow -wnon- virtual-dtor -pedantic -wcast-align -wcast-qual -wconversion -Wpointer-arith -Wunused -Woverload-virtual -O0 -M *.cc> .depends

    (我尝试使此命令的编译器选项与我的正常编译相匹配。

  • 在浏览器中,我查看

    http://en.cppreference.com/w/cpp/string/basic_string/stol

    以识别

    std::stoi 包含在 std::basic_string 中(在页面顶部)

  • 在我的编辑器中,(或)使用 grep,我在 .depends 文件中搜索"basic_string">

    grep --color -nH -e "basic_string" .depends

    grep 在我的当前依赖文件中报告字符串 214 次,其中 更改代码时更改大小。

    一个报告的示例:

    .depends:14105:/usr/include/c++/5/bits/basic_string.h \

  • 在我的编辑器中,我打开指定的文件

    "/usr/include/c++/5/bits/basic_string.h",

    然后搜索"stoi",它似乎只存在两次。

    这表示编译器的 v5。

我认为您应该能够在您的系统上进行类似的搜索。

祝你好运。

这是对strtoi的引用,但我假设你想要一个关于它如何工作的实际解释。这其实很简单。 步骤:

  1. 求最大乘数(exp(base, strlen(number)-1)
  2. 在字符串上运行 for 循环并将其乘以乘法器
  3. 每次迭代将乘数除以基

在 C 语言中实现strtoi

#include <string.h>
int ipow(int base, int exp)
{
int result = 1;
for (;;)
{
if (exp & 1)
result *= base;
exp >>= 1;
if (!exp)
break;
base *= base;
}
return result;
}
int charToDigit(char ch) {
switch (ch) {
case '0':
return 0;
break;
case '1':
return 1;
break;
case '2':
return 2;
break;
case '3':
return 3;
break;
case '4':
return 4;
break;
case '5':
return 5;
break;
case '6':
return 6;
break;
case '7':
return 7;
break;
case '8':
return 8;
break;
case '9':
return 9;
break;
default:
throw "0-9";
break;
}
};
int stoi(const char* string) {
int basenum = 0;
int pos = ipow(10, strlen(string)-1);
const int len = strlen(string);
// first is biggest, pos
for (int i = 0; i<len; i++) {
basenum += charToDigit(string[i])*pos;
pos /= 10;
};
return basenum;
};

转换字符串(假设其所有字符都是 0 到 9 之间的整数):

  1. 您必须获取字符串的长度。
  2. 遍历字符串(您可以选择向前或向后),并将每个幂添加到结果变量中。

我将从一个乘数变量和一个结果变量开始:int multiplier = 1, result = 0,然后我将使用std::string::length函数获取字符串长度。向后循环字符串,我将每个元素乘以乘数并将其添加到结果中。确保在访问字符时应减去字符 0 的 ASCII 值。这可以通过减去 48 来完成,或者如果您不想查找 ASCII 值,您可以将 0 括在单括号中。 例如,如果您不执行从 char 到 int 的转换,那么访问字符"1"将导致程序读取 49,这是不好的。至于乘数,在循环的每次迭代结束时将其乘以 10。

我从后面迭代的原因是避免使用使用双精度/浮点的 pow() 函数。我觉得它更简单,但这是你的选择。当然,你也可以通过手动制作一个与字符串长度相同的次数乘以 10 的循环来避免 pow(),但这样效率会降低一些。

下面是一个可以使用的简单实现:

#include <string>
#include <iostream>
int stoi(std::string s) {
int multiplier = 1, result = 0;
for (int i = s.length() - 1; i >= 0; i--) {
result += multiplier * (s[i] - '0');
multiplier *= 10;
}
return result;
}
int main() {
std::cout << stoi("1235") + 1;
return 0;
}

如果运行此程序,它应输出 1236,因为字符串"1235"已转换为整数。

当然,这只是我自己的实现;如果你想要官方的,那么本文包含一些关于它的信息。