C 将字符数组中的多数字整数转换为整数

C 将字符数组中的多数字整数转换为整数,c,char,int,type-conversion,C,Char,Int,Type Conversion,我构建了一个小程序,可以将给定的字符数组转换为整数: #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

我构建了一个小程序,可以将给定的字符数组转换为整数:

#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';
}
#包括
int char_至int(char*值);
int main(int argc,char*argv[])
{
如果(argc!=2)
{
printf(“非法参数计数!”);
返回1;
}
printf(“作为字符数组:%s\n”,argv[1]);
printf(“作为整数:%i”,字符到整数(argv[1]);
返回0;
}
整数字符到整数(字符*值)
{
返回*值-'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;
}
#包括
int char_至int(char*值);
int非法_转换=0;
int main(int argc,char*argv[])
{
如果(argc!=2)
{
printf(“非法参数计数!”);
返回1;
}
int result=char_to_int(argv[1]);
if(非法的_转换)
{
printf(“非法论点”);
返回1;
}
printf(“作为字符数组:%s\n”,argv[1]);
printf(“作为整数:%i”,结果);
返回0;
}
整数字符到整数(字符*值)
{
int结果=0;
int负整数=0;
while(*值)
{
如果(*值==43)
{
*值++;
继续;
}
否则,如果(*值==45)
{
*值++;
负整数=1;
继续;
}
如果(*值<48 | |*值>57)则为else
{
非法的_转换=1;
返回1;
}
结果*=10;
结果+=*值++-'0';
}
if(负整数)
结果*=-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;
}
在可以避免的情况下,返工代码会导致未定义的行为

带有(2的补码)
int

char buf[100];
sprintf(buf, "%d", INT_MIN);  // e.g. -2147483648
int y = char_to_int(buf);  
char\u to\u int()
中的
while
循环最终执行

// before
// result: 214748364
// *value: '8'
result += *value++ - '0';
// after
// `int` overflow, this is undefined behavior
为了避免,不要将答案累加为正值,然后在找到“-”时否定,而是将答案累加为负值,然后在未找到“-”时否定。这不太直观,但可以避免UB

使用
unsigned
作为扩展范围是另一种方法,但在
INT\u MAX==UINT\u 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;
}
#包括
int char_to int(const char*value){//使用const
整数符号=*值;
如果(符号=='-'| |符号=='+')){
值++;
}
bool digit_found=假;
int结果=0;
//while(isdigit(*value)){//避免此操作,因为当*value<0时它是UB,而不是EOF

while(isdigit((unsigned char)*value)){//or(*value>='0'&&&&*value)要转换的
atoi()
函数如何?是的,这是我需要提到的另一件事。我想避免使用该函数,因为我想自己实现该转换。但是感谢您的提及。@J…也许他想学习:)@PeterJ我很欣赏。顺便说一句,你的方法教会了我一些东西。我从来没有想过增加
char
指针本身!看看ASCII表。你需要减去48才能得到正确的char。继续编程:)现在自己试试:1.检查输入字符串是否有效。2.符号检测和空格删除。非常好练习不用担心它是完美的。作为字符数组:324作为整数:324,但“dfsff”将给出结果,并且它不是一个有效的数字。-345也将给出错误的结果。请自己尝试进行排序。检查字符是否在ASCII数的范围内就足够了,不是吗?