将char数组中的多数字整数转换为整数

时间:2017-08-05 13:04:40

标签: c char int type-conversion

我构建了一个小程序,它将给定的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;
}

2 个答案:

答案 0 :(得分:3)

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

此函数转换但没有任何检查,它仅适用于有效的非负十进制数,否则它是一个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 :(得分:0)

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

(2的补码)int

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

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

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

为了避免,而不是将答案累积为正值,然后如果找到“ - ”则否定否定,将答案累积为负值,然后如果未找到“ - ”则否定。这不太直观,但避免了UB。

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

评论中提到的其他改进。

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

注意:不包括溢出检测。