你如何实现自己的字符串到整数的转换
Posted
技术标签:
【中文标题】你如何实现自己的字符串到整数的转换【英文标题】:How do you implement your own string to integer conversion 【发布时间】:2016-09-27 12:25:04 【问题描述】:所以我想通过创建自己的函数而不是使用 stoi/atoi 函数来获取一个字符串,例如 8302 并将其转换为整数。
到目前为止,我尝试过这样做:
int stringToInt(string input)
int i = 0;
while(input[i] >= '0' && input[i] <= '9')
input[i] = input[i] * 10 + ......
i++;
return i;
我知道每次找到一个整数时我都需要继续乘以 10,这样我就可以增加它,例如 123 = 1*10*10+2*10+3。但我不知道如何编码。任何人都可以提出一种方法吗?
【问题讨论】:
为什么要将字符串中的每个 ASCII 字符值乘以 10? 您不应该对字符串索引和累加器使用相同的变量。为累加器使用单独的变量。 您返回的是索引而不是转换后的数字。此外,您不会检查字符串的结尾。 @FirstStep 这是一个名为 awesomelipsis 的 c++17 功能。可变参数模板的扩展,它为您自动完成整个程序。只需粘贴到堆栈溢出中。 @FirstStep 看到了吗?已经有 6 个答案:) 【参考方案1】:以递归方式执行它可能是最简单的。使用以下思路:
8302 = 830 * 10 + 2
即:
-
如果字符串中只有一个
char
- 返回它;否则继续
分隔字符串中的最后一个char
将字符串(没有最后一个字符)转换为整数 - 使用递归
乘以 10 并加上最后一个 char
这里有很多细节:
如何将 1char
转换为整数? - 从中减去'0'
如何将char
与字符串的其余部分分开? - 使用substr
当您有一个有效的递归解决方案时,您可能希望将其转换为迭代解决方案 - 这会使其更快,但可能不太可读
如何处理 "aaa"
或 "123haha"
等无效字符串 - 我的算法无法处理此问题
【讨论】:
OP 应该考虑的其他点:处理负数。湾。如果第 4 步会溢出他的累加器该怎么办(关于如何在不触发溢出的情况下检测到这一点有一些有趣的问题)。 C。结合后两者:在不触发溢出的情况下处理最负数的条目。 我认为这些考虑主要是针对其他可能在未来阅读本文的人; OP提到了“stoi/atoi”,所以他似乎并不关心这些事情,就像atoi
doesn't care【参考方案2】:
在您可以定义 char2int 转换之前:
inline int ctoi(char c)
switch (c)
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
default:
throw std::runtime_error("Invalid char conversion");
并使用它:
int my_stoi_dec(const std::string& str)
int rtn = 0;
int exp = 1;
for (auto cp = str.crbegin(); cp != str.crend(); ++cp)
char c = *cp;
if (isdigit(c))
rtn += ctoi(c) * exp;
exp *= 10;
else if (c == '+')
return rtn;
else if (c == '-')
return rtn * -1;
else
throw std::runtime_error("Integer error conversion");
【讨论】:
你不应该使用幻数。这使得代码不可移植。 @NathanOliver 更好? 是的。这是迄今为止最完整的答案。它不处理下溢/溢出,但我不会对此投反对票。【参考方案3】:这个非常接近你的尝试:
int toInt(const std::string& input)
int i = 0;
for (const auto c : input)
if (c < '0' || c > '9')
break;
i = i*10 + c-'0';
return i;
唯一的假设是字符'0'
到'9'
在字符集中直接相邻。 if
语句确保我们在非数字字符处停止。使用c-'0'
将数字字符转换为其整数值。
请记住,这只解析字符串的前几位。不考虑以符号 +
或 -
开头的字符串。
【讨论】:
这是尽可能干净的。您应该在答案中添加解释,因为它似乎最适合按原样使用。【参考方案4】:一个好方法是找到你的第一个数字,然后从那里开始创建一个多人游戏变量,然后将每个数字乘以十。对于您添加的每个字符,您必须从中减去“0”,因为“0”不等于 int 0。
示例:
string s = "12346";
int multiplayer = 1;
int i = 0;
int result = 0;
while (s[i] >= '0' && s[i] <= '9')
++i;
--i;
for(i ; i >= 0 ; --i)
result += (s[i] - '0') * multiplayer;
multiplayer *= 10;
【讨论】:
【参考方案5】:最好从右到左开始转换。
因此,您将从字符串的末尾开始迭代字符串,并在其开头结束。在每次迭代中,我们将获取字符,将其转换为 int 并乘以它的 multiplier
(它在结果整数中的位置),然后将其添加到最终结果中。
这应该可行:
#include <iostream>
#include <string>
int stringToInt(std::string input)
int result = 0;
int multiplier = 1;
for (int i = input.length() - 1; i >= 0; i--) // start from right
if (input[i] - '0' < 0 || input[i] - '0' > 9) // if any character is not an integer, return maximum negative
result = INT16_MIN;
break;
result += (input[i] - '0') * multiplier; // convert to int, get its position and then add it to result.
multiplier *= 10; // get next position
return result;
int main()
std::string MyEx = "123456";
int MyInt = stringToInt(MyEx);
std::cout << MyInt;
return 0;
【讨论】:
从操作码和检查,不能保证所有字符串项都是数字 @HumamHelfawi OP 没有说明这一点。根据他的示例输入,不清楚其中一个字符可能不是整数。我还是添加了它,感谢您指出它。【参考方案6】:void enforce( bool b )
if ( !b )
throw std::range_error("Not a valid string to convert to integer");
int stringToInt(std::string)
for ( std::size_t i( 0 ); i != ( last - first ); ++i )
enforce( ( '0' <= first[ i ] ) && ( first[ i ] <= '9' ) );
result += pow(10,i) * ( first[ i ] - '0' );
Source
【讨论】:
10^i
没有做你认为的事情。以上是关于你如何实现自己的字符串到整数的转换的主要内容,如果未能解决你的问题,请参考以下文章
IEnumerable 类型如何转换成IQueryable类型