当前位置: 首页 > 知识库问答 >
问题:

重新编码itoa:最小int错误

苏君昊
2023-03-14

我试图重新编码itoa函数,给定一个int,它将返回一个表示其十进制值的字符串。到目前为止,这些功能运行良好:

char        *ft_itoa(int n)
{
    char    s[1024];
    int     i;
    int     neg;

    i = 0;
    neg = 0;
    if (n == 0)
        s[i++] = '0';
    if (n < 0)
    {
        n = n * (-1);
        neg = 1;
    }
    while (n != 0)
    {
        s[i++] = (n % 10) + 48;
        n /= 10;
    }
    if (neg)
        s[i++] = '-';
    s[i] = '\0';
    return (ft_strrev(s));
}

最小整数值 -2147483648 除外。在这种情况下,该函数返回:

"-./,),(-*,("

威奇……很奇怪。请注意,ft_strrev将反转结果并进行malloc。有线索吗?

编辑:

这里有非常有趣的答案。我对缓冲区的最小尺寸特别感兴趣。使用限制.h似乎可以解决问题,但我不允许包含除 stdlib.h 和字符串.h 之外的其他标头。我也被限制在三个功能,马洛克,自由和写作。但是,我确实从libc重新编码了strdup和许多函数。

有人能解释一下为什么这一行会声明我需要的确切内存量吗

char   buf[sizeof(int) * CHAR_BIT / 3 + 3];

使用无符号计算数字可以避免INT_MIN的问题。INT_MIN的错误修复。

为什么?

共有2个答案

顾光明
2023-03-14

避免int溢出(if(n

#include <limits.h>
char *ft_itoa(int n) {
  char s[50];
  // char s[1024];
  int i;
  int neg;

  i = 0;
  neg = 0;
  //if (n == 0)          // special case not need with do loop
  //    s[i++] = '0';

  if (n < 0) {           // Insure n is _not_ positive
    // n = n * (-1);
    neg = 1;
  } else {
    n = -n;              // no overflow possible here
  }
  // while (n != 0)
  do {
    // s[i++] = (n % 10) + 48;
    s[i++] = '0' - (n % 10);   // subtract
    n /= 10;
  } while (n);
  if (neg) s[i++] = '-';
  s[i] = '\0';
  return strdup(strrev(s));
}

对于清理后的版本

#include <limits.h>

// Compute max size need to represent an `int`
#define INT_DEC_SIZE (sizeof (int)*CHAR_BIT/3 + 3)

char *ft_itoa(int n) {
  char s[INT_DEC_SIZE];
  char *p = &s[sizeof s - 1];
  *p = '\0';
  int i = n;
  if (i > 0) {
    i = -i;
  }
  do {
    p--;
    *p = '0' - (i % 10);
    i /= 10;
  } while (i);
  if (n < 0) *(--p) = '-';
  return strdup(p);
}

INT_DEC_SIZE参考

卫胜
2023-03-14

您的代码有几个小问题:

>

  • 缓冲区太大了:包括符号和空终止符,24个字节就足够了。为了绝对的可移植性,sizeof(int)*CHAR_BIT/3的上限是正确的。不是错误,而是浪费。

    如果将数字从右到左存储到缓冲区中,则不需要最后的反向阶段,可以直接调用strdup()。更简单、更快。

    使用无符号计算数字将避免INT_MIN的问题。INT_MIN的错误修复。

    循环i

    您应该使用'0'而不是硬编码ASCII值48。更具可读性和可移植性。

    以下是修改后的版本:

    #include <limits.h>
    
    char *ft_itoa(int n) {
        char buf[sizeof(int)*CHAR_BIT/3 + 3];
        char *s;
        unsigned int v;
    
        v = n;
        if (n < 0) {
            v = -v;
        }
        s = buf + sizeof(buf);
        *--s = '\0';
        while (v >= 10) {
            *--s = '0' + v % 10;
            v /= 10;
        }
        *--s = '0' + v;
        if (n < 0)
            *--s = '-';
        return strdup(s);
    }
    

    如果strdup在您的系统上不可用,那么它很容易实现,如果您从堆中分配字符串,那么它非常有用。

  •  类似资料:
    • 问题内容: 我进行了全新的OSX 10.9.3全新安装并安装了pip,然后执行了 两次安装似乎都非常令人满意,并且运行没有任何错误(尽管有不计其数的警告)。当我尝试使用导入熊猫运行python脚本时,出现以下错误: 如何解决此错误并使熊猫正确加载? 问题答案: 您可以安装熊猫的早期版本。 在我的情况下,它解决了问题…

    • 问题内容: 导入熊猫时,会出现以下错误: 我正在运行Python 2.7.5,Pandas 0.14.1和Numpy 1.9.0。我尝试使用pip安装两种版本的旧版本,每次都会出现重大错误。我是Python的初学者,因此这里的任何帮助将不胜感激。:) 编辑:运行OS X 10.9.4 编辑2:这是我卸载并重新安装Numpy + Pandas,然后运行.py文件的视频的链接:https ://www

    • 给出了一个由N个整数组成的非空零索引数组。一对整数(P,Q),如0≤ P 包含以下示例片段: 切片(1,2),其平均值为(2 2)/2=2 目标是找到平均值最小的切片的起始位置。 写一个函数: 即,给定一个由N个整数组成的非空零索引数组A,返回具有最小平均值的切片的起始位置。如果有多个具有最小平均值的切片,您应该返回这样一个切片的最小起始位置。 例如,给定数组A,这样: 如上所述,函数应该返回1。

    • 要再次编码,解码数据将再次转换为,然后转换为编码的字符串。但是与不匹配。请帮助我创建一个完美无瑕的编码解码到重新编码流。 详细说明,如果这样执行,重新编码与初始编码完全匹配。 但是,我的是从数据库中提取的,如下所示,在这种情况下,重新编码不匹配。 这2看起来相似的方式,但我的程序似乎正在产生一个损坏的版本,实际的base64解码字符串应该是什么。

    • “你好,世界” 这是我在网站上的第一篇帖子,也是我在第五周学习java编程课程的第一篇文章。我应该提一下,我还是一个初学者。我本周的任务如下: “创建一个(双精度)数组来存储下面的分数。然后使用上述方法之一创建排序类。确保排序类处理双精度数组(双精度[] 数组名称;)。创建一个客户端类来调用排序类。将数组从最小到最大排序,然后打印出已排序的数组。 到目前为止,我所做的工作是创建第一个用于收集和打印

    • 我试图用TheNewBoston的教程制作一个蛇游戏,因为我是一名中学生,在Python方面没有太多经验。代码是: 但是,当我执行、播放、丢失并按C重试时,会出现此错误。当我想退出时,Q可以正常工作,但C只是退出,并打印此错误: C:\Python34\python。exe“C:/Users/Ded/PycharmProjects/PyGame/PyGame Tutorial.py”回溯(上次调用