Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在实现我自己的Atoi()时有一些bug_C_C11_Atoi - Fatal编程技术网

C 在实现我自己的Atoi()时有一些bug

C 在实现我自己的Atoi()时有一些bug,c,c11,atoi,C,C11,Atoi,我不明白。当我的函数从主函数的char返回随机数时。原始atoi()返回-1。我目前使用的是C11版本。我从某人那里听说,这是因为int溢出,我需要从我的函数返回int,但我现在返回long。如果不是2147483647,如何检测到InOverflow #include <stdio.h> #include <stdlib.h> #include <stdbool.h> bool mx_isdigit(int c) { return c >=

我不明白。当我的函数从主函数的char返回随机数时。原始atoi()返回-1。我目前使用的是C11版本。我从某人那里听说,这是因为int溢出,我需要从我的函数返回int,但我现在返回long。如果不是2147483647,如何检测到InOverflow

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

bool mx_isdigit(int c) {
    return c >= 48 && c <= 57;
}


bool mx_isspace(char c) {
    return (c >= 9 && c <= 13) || c == 32;
}


int mx_atoi(const char *str) {
    long num = 0;
    int sign = 1;

    for (; mx_isspace(*str); str++);

    if (*str == '-' || *str == '+') {
        sign = *str == '-' ? -sign : sign;
        str++;
    }

    for (; *str; str++) {
        if (!mx_isdigit(*str)) {
            break;
        }
        num = (num * 10) + (*str - '0');
    }
    return sign == -1 ? -num : 0 + num;
}

int main(void) {

    char str[100] = "12327123061232712306";
    printf("R: %d\n", atoi(str));
    printf("M: %d", mx_atoi(str));
}
#包括
#包括
#包括
布尔mx_isdigit(内部c){

返回c>=48&&c=9&&c在函数
int mx_atoi(const char*str){…
中,您正在计算
long
类型的结果,但函数返回
int
;因此如果
num
中存储的
long
类型的结果不适合
int
类型,则会丢失某些内容(实际上,由于有符号整数值被转换,行为是“实现定义的”,即依赖于编译器)。结果可能被逐位截断,产生一个“看起来”与您输入的十进制数大不相同的数字。参见,例如,在线C11草稿。粗体段落适用于:

6.3.1.3有符号和无符号整数

1当整数类型的值转换为其他整数类型时 除了_Bool,如果值可以用新类型表示,则 没有变化

2否则,如果新类型是无符号的,则该值由 重复地加上或减去一个大于最大值 可以在新类型中表示,直到值在 新型号(60)

3否则,将对新类型进行签名,并且无法删除该值 在其中表示;结果要么是定义的实现,要么是 执行定义的信号被触发。

int-mx_-atoi(const-char*str)
转换为
long-mx_-atoi(const-char*str)
,使用
long
-变量存储结果,不要忘记在
printf
中使用格式说明符
%ld
而不是
%d

否则,如果您需要坚持使用
int
,并且希望安全地对溢出做出反应,您可以执行以下操作

if (num > INT_MAX) {
  return -1;
}

在循环内部。
INT\u MAX
在函数
INT mx\u atoi(const char*str)内部的
limits.h
中定义{…
,您正在计算
long
类型的结果,但函数返回一个
int
;因此,如果
num
中存储的
long
类型的结果不适合
int
类型,则会丢失一些内容(实际上,由于符号整数值被转换,行为是“实现定义的”),即编译器相关)。结果可以按位截断,生成的数字“看起来”与您输入的十进制数字大不相同。参见,例如,联机C11草稿。粗体段落适用于:

6.3.1.3有符号和无符号整数

1当整数类型的值转换为其他整数类型时 除了_Bool,如果值可以用新类型表示,则 没有变化

2否则,如果新类型是无符号的,则该值由 重复地加上或减去一个大于最大值 可以在新类型中表示,直到值在 新型号(60)

3否则,将对新类型进行签名,并且无法删除该值 在其中表示;结果要么是定义的实现,要么是 执行定义的信号被触发。

int-mx_-atoi(const-char*str)
转换为
long-mx_-atoi(const-char*str)
,使用
long
-变量存储结果,不要忘记在
printf
中使用格式说明符
%ld
而不是
%d

否则,如果您需要坚持使用
int
,并且希望安全地对溢出做出反应,您可以执行以下操作

if (num > INT_MAX) {
  return -1;
}
在循环内部。
INT\u MAX
limits.h中定义

c>=48&&c
c>=48&&c
int
溢出可能性

num=(num*10)+(*str-“0”);
遇到
int
溢出,这是未定义的行为(UB),当:

1) 输入字符串应表示
INT\u MIN
INT/long
具有相同的范围或
2) 输入字符串对
int
范围之外的值进行编码

避免这种情况的各种方法

未检测到无数字字符串

在这种情况下返回0是合理的,但代码可能需要设置一些错误条件

不抱怨尾随的非数字

简单地忽略尾随字符是合理的,但代码可能需要设置一些错误条件


避免
int
溢出的一种方法(不要依赖
long
int
宽)是在
(num*10)+(*str-'0')
之前进行测试,因为负
int
比正
多,所以在负的一侧进行累积

bool digit_found = false;
int val = 0;
for (; mx_isdigit(*str); str++) {
    digit_found = true;
    int digit = *str - '\0';
    if (val <= INT_MIN/10 && (val < INT_MIN/10 || digit > -(INT_MIN%10))) { // C99
      return sign == 1 ? INT_MAX : INT_MIN;
    }
    val = val * 10 - digit;  // note subtraction here
}

if (!digit_found) {
    return 0; // Or handle in some other fashion
}

if (sign == 1) {
  // If val is too negative to negate ...
  if (val < -INT_MAX) {
    return INT_MAX;  // overflow
  }
  return -val;
}
return val;
bool digit\u found=false;
int-val=0;
对于(;mx_isdigit(*str);str++){
找到的数字=真;
整数位数=*str-'\0';
如果(val-(INT_MIN%10)){//C99
返回符号==1?整数最大值:整数最小值;
}
val=val*10位;//注意这里的减法
}
如果(!找到数字){
返回0;//或以其他方式返回句柄
}
如果(符号==1){
//如果val太负而不能否定。。。
如果(val<-INT_MAX){
返回INT_MAX;//溢出
}
返回值-val;
}
返回val;

int
溢出可能性

num=(num*10)+(*str-“0”);
遇到
int
溢出,这是未定义的行为(UB),当:

1) 输入字符串应表示
INT\u MIN
INT/long
具有相同的范围或
2) 输入字符串对
int
范围之外的值进行编码

多种方式
int mx_atoi(const char *str) {    
    for (; mx_isspace(*str); str++);

    bool negative = false;
    if (*str == '-' || *str == '+') {
        negative = *str == '-';
        str++;
    }

    int num = 0;
    for (; mx_isdigit(*str); str++) {
        if (INT_MAX / 10 < num) {
            goto ERR_OVERFLOW;
        }
        num *= 10;
        const unsigned char c = *str - '0';
        if (INT_MAX - c < num) {
            goto ERR_OVERFLOW;
        }
        num += c;

    }
    return negative ? -num : num;
    ERR_OVERFLOW:
    return negative ? INT_MIN : INT_MAX;
}
bool digit_found = false;
int val = 0;
for (; mx_isdigit(*str); str++) {
    digit_found = true;
    int digit = *str - '\0';
    if (val <= INT_MIN/10 && (val < INT_MIN/10 || digit > -(INT_MIN%10))) { // C99
      return sign == 1 ? INT_MAX : INT_MIN;
    }
    val = val * 10 - digit;  // note subtraction here
}

if (!digit_found) {
    return 0; // Or handle in some other fashion
}

if (sign == 1) {
  // If val is too negative to negate ...
  if (val < -INT_MAX) {
    return INT_MAX;  // overflow
  }
  return -val;
}
return val;
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

bool mx_isdigit(int c);
bool mx_isspace(char c);

int mx_atoi(const char* str) {
    long long num = 0;
    int sign = 1;

    for (; mx_isspace(*str); str++);

    if (*str == '-' || *str == '+') {
        sign = *str == '-' ? -sign : sign;
        str++;
    }

    for (; *str; str++) {
        if (!mx_isdigit(*str)) {
            break;
        }
      if ((num * 10) + (*str - '0') < num) {
          return sign == -1 ? 0 : -1;
      }
        num = (num * 10) + (*str - '0');
    }

    return sign == -1 ? -num : num;
}

int main(void) {

    char str[100] = "-9223372036854775809";
    printf("R: %d\n", atoi(str));
    printf("M: %d\n", mx_atoi(str));
}