【问题标题】: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 个答案:)

标签: c++ string function


【解决方案1】:

以递归方式执行它可能是最简单的。使用以下思路:

8302 = 830 * 10 + 2

即:

  1. 如果字符串中只有一个char - 返回它;否则继续
  2. 分隔字符串中的最后一个char
  3. 将字符串(没有最后一个字符)转换为整数 - 使用递归
  4. 乘以 10 并加上最后一个 char

这里有很多细节:

  • 如何将 1 char 转换为整数? - 从中减去'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 没有做你认为的事情。
    猜你喜欢
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    • 2017-10-16
    • 2015-08-10
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多