c++ std::stoi是如何实现的?

dzjeubhm  于 2022-12-15  发布在  其他
关注(0)|答案(4)|浏览(533)

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

i86rm4rw

i86rm4rw1#

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

cgyqldqp

cgyqldqp2#

我很想知道它们中的一些在幕后是如何工作的。比如std::stoi背后的实际代码是什么?
我认为您可以通过类似于以下内容的搜索找到“实际”代码:

  • 在Ubuntu上,我的makefile创建了一个.depends文件:

g++-5 -m64 -O3 -ggdb -std=c++14 -墙-额外-阴影-非虚拟数据或学究式-转换对齐-转换质量-转换指针-算术-未使用-超载虚拟-O 0-M *.cc〉.依赖
(我尽量使此命令的编译器选项与正常编译相匹配。)

  • 在浏览器中,我查看

http://en.cppreference.com/w/cpp/string/basic_string/stol
来确认
std::stoi包含在std::basic_string中(页面顶部)

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

grep --颜色-nH -e“基本字符串”.依赖项
grep在我当前的depends文件中报告了214次字符串,当我更改代码时,该文件的大小也随之改变。
报告示例:
取决于:14105:/usr/包含/c++/5位/基本字符串. h\

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

“/usr/包含/c++/5/位/基本字符串. h”,
然后搜索似乎只存在两次的“stoi”。
这表示编译器的版本5。
我想你应该可以在你的系统上做类似的搜索。
祝你好运。

lnxxn5zx

lnxxn5zx3#

这是对strtoi的一个引用,但我假设你想要一个关于它如何工作的实际解释。它实际上非常简单。步骤:
1.查找最大乘数(exp(base,strlen(number)-1)
1.对字符串运行for循环,并将其乘以乘数
1.每次迭代时将乘数除以基数
strtoi在C中的实现:

#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;
};
bqf10yzr

bqf10yzr4#

要转换字符串(假设其所有字符都是0到9之间的整数):
1.必须获取字符串的长度。
1.迭代字符串(选择向前或向后),并将每个幂添加到结果变量。
我将从一个乘数变量和一个结果变量开始:int multiplier = 1, result = 0,然后使用std::string::length函数得到字符串长度。向后循环字符串,将每个元素乘以乘数,并将其加到结果中。请确保在访问char时,应减去char 0的ASCII值。这可以通过减去48来完成,或者如果你不想查找ASCII值,你可以用一个方括号把0括起来。例如,如果你不执行从char到int的转换,那么访问字符'1'将导致程序读取49,这是不好的。至于乘数,在循环的每次迭代结束时将其乘以10。
我从后面迭代的原因是为了避免使用使用pow()函数,它使用了double/float。我发现它更简单,但这是你的选择。当然,你也可以通过手动循环乘以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”已经被转换成整数。
当然,这只是我自己的实现;如果你想要官方版本,那么this article包含了一些相关的信息。

相关问题