std::stoi 是如何实现的?
How is std::stoi implemented?
大多数日常用例已经转换为标准库中可用的函数。但是,我想知道其中一些人在幕后是如何工作的。比如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
的引用,但我假设你想要一个关于它如何工作的实际解释。这其实很简单。 步骤:
- 求最大乘数(exp(base, strlen(number)-1)
- 在字符串上运行 for 循环并将其乘以乘法器
- 每次迭代将乘数除以基 数
在 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 之间的整数):
- 您必须获取字符串的长度。
- 遍历字符串(您可以选择向前或向后),并将每个幂添加到结果变量中。
我将从一个乘数变量和一个结果变量开始: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"已转换为整数。
当然,这只是我自己的实现;如果你想要官方的,那么本文包含一些关于它的信息。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 使用GSoap实现ONVIF
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 用于AVX的ln(x)的实现,m256
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如何实现内部实现依赖于模板参数的类
- 我的 PRNG 实现与我尝试复制的实现有何不同?