【问题标题】:Converting a multidigital integer from a char array into an integer将多位整数从 char 数组转换为整数
【发布时间】:2023-03-28 21:25:01
【问题描述】:

我已经构建了一个小程序,它将给定的 char 数组转换为整数:

#include <stdio.h>

int char_to_int(char* value);

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("Illegal argument count!");
        return 1;
    }

    printf("As char array: %s\n", argv[1]);
    printf("As integer: %i", char_to_int(argv[1]));

    return 0;
}

int char_to_int(char* value)
{
    return *value - '0';
}

问题是当我输入一个多位数字时,整数只包含一个数字,这是合乎逻辑的,但我不知道如何重写代码。而且我也不知道为什么只有第一个字符被转换。

我知道这是非常基本的东西,但我想知道如何正确实现它。

我还想避免在 STL 中使用 ato() 函数。

带有错误处理的返工代码:

#include <stdio.h>

int char_to_int(char* value);

int illegal_conversion = 0;

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        printf("Illegal argument count!");
        return 1;
    }

    int result = char_to_int(argv[1]);

    if (illegal_conversion)
    {
        printf("Illegal arguments");
        return 1;
    }

    printf("As char array: %s\n", argv[1]);
    printf("As integer: %i", result);

    return 0;
}

int char_to_int(char* value)
{
    int result = 0;
    int negative_integer = 0;

    while (*value)
    {
        if (*value == 43)
        {
            *value++;
            continue;
        }
        else if (*value == 45)
        {
            *value++;
            negative_integer = 1;
            continue;
        }
        else if (*value < 48 || *value > 57)
        {
            illegal_conversion = 1;
            return 1;
        }

        result *= 10;
        result += *value++ - '0';
    }

    if (negative_integer)
        result *= -1;

    return result;
}

【问题讨论】:

  • 要转换的atoi()函数怎么样?
  • 是的,这是我需要提及的另一件事。我想避免使用该功能,因为我想自己实现该转换。不过谢谢你的提及。
  • @J...S 也许他想学习 :)
  • @PeterJ 我很佩服这一点。顺便说一句,你的方法教会了我一些东西。我从来没有想过增加char 指针本身!
  • 查看 ASCII 表。您需要减去 48 才能得到正确的字符。

标签: c char int type-conversion


【解决方案1】:

因为你只返回第一个数字的数值。

这个函数转换但不做任何检查,它只适用于有效的非负十进制数,否则它是一个UB

int char_to_int(char* value)
{
    int result = 0;
    while(*value)
    {
        result *= 10;
        result += *value++ - '0';
    }
    return result;
}

或者更聪明一点的:

int char_to_int(char* value, int *res)
{
    int sign = 0;
    int status = 0;
    int result = 0;


    if (value != NULL && res != NULL)
    {
        while (*value)
        {
            switch (*value)
            {
                case '+':
                case '-':
                    if (sign) status = -1;
                    sign = *value == '-' ? -1 : 1;
                    break;
                default:
                    if (!isdigit(*value)) status = -1;
                    if(!sign) sign = 1;
                    *result *= 10;
                    *result += *value - '0';
                    break;
            }
            value++;
            if (status) break;
        }
        if(!status)*res = sign * result;
    }

    return status;
}

【讨论】:

  • 继续编程 :)
  • 现在自己试试: 1. 检查输入字符串是否有效。 2. 符号检测和空格去除。很好的练习
  • 别担心,它是完美的。作为字符数组:324 作为整数:324
  • 但是 "dfsff" 会给出结果并且它不是一个有效的数字。 -345 也会给出错误的结果。尝试自己解决。
  • 检查字符是否在ASCII数字范围内就足够了,不是吗?
【解决方案2】:

在可以避免的情况下,重做的代码会导致未定义的行为

带有(2 的补码)int 的示例

char buf[100];
sprintf(buf, "%d", INT_MIN);  // e.g. -2147483648
int y = char_to_int(buf);  

char_to_int() 中的 while 循环最终会执行

// before
// result: 214748364
// *value: '8'
result += *value++ - '0';
// after
// `int` overflow, this is undefined behavior

为了避免,而不是将答案累积为正值,然后在找到“-”时取反,而是将答案累积为负值,然后在未找到“-”时取反。这不太直观,但避免了 UB。

使用unsigned 作为扩展范围是另一种方法,但在INT_MAX == UINT_MAX 的稀有机器上会失败。我只遇到过一次这样的机器,而且是它最宽的整数。

cmets 中提到的其他改进。

#include <ctype.h>

int char_to_int(const char *value) {  // use const
  int sign = *value;
  if (sign == '-' || sign == '+') {
    value++;
  }

  bool digit_found = false;
  int result = 0;
  // while (isdigit(*value)) {    // avoid this as it is UB when *value < 0, not EOF
  while (isdigit((unsigned char) *value)) { // or (*value >= '0' && *value <= '9')
    result *= 10;
    result -= *value - '0';  // notice the `-=`
    value++;
    digit_found = true;
  }
  if (sign != '-') {
    result = -result;
  }

  // Error detection
  if (*value != '\0' || !digit_found) {
    ; //Handle_Invalid_String();
  }

  return result;
}

注意:不包括溢出检测。

【讨论】:

    猜你喜欢
    • 2016-04-30
    • 2011-08-28
    • 1970-01-01
    • 2020-03-31
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多