【问题标题】:Why does n need to be positive为什么 n 必须是正数
【发布时间】:2021-06-13 19:21:22
【问题描述】:

在 k&r c,第 2 版,第 59 页:

/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
    int i, sign;
    if ((sign = n) < 0) /* record sign */
        n = -n;         /* make n positive --- why need this? */ 
    i = 0;
    do
    {                          /* generate digits in reverse order */
        s[i++] = n % 10 + '0'; /* get next digit */
    } while ((n /= 10) > 0);   /* delete it */
    if (sign < 0)
        s[i++] = '-';
    s[i] = '\0';
    reverse(s);
}

为什么n需要是正数,c++中需要这个吗?

【问题讨论】:

  • n 不会被翻转为正数时,while 条件(n /= 10) &gt; 0 将立即为false

标签: c kernighan-and-ritchie


【解决方案1】:

书上的这个功能很糟糕。

如果n 等于 INT_MIN,n = -n 将调用未定义行为 (UB)。

为什么n需要是正数,c++中需要这个吗?

在 C++ 中这样做会产生错误的 INT_MIN 结果。

最好将指针返回到转换后的字符串。它允许您在表达式中使用此函数的结果或作为其他函数的参数。

n % 10 + '0' 不是很便携。最好使用带数字的表格。它适用于任何字符编码。

另一个问题:不要使用标准库函数的名称。

K&R IMO 有点过时了,现在很多编程技术都被认为很糟糕。

char *reverse(char *s)
{
    char *wrk = s, *end = s;
    if(s && *s)
    {
        while(*(end + 1)) end++;
        while(end > wrk)
        {
            char tmp = *wrk;
            *wrk++ = *end;
            *end-- = tmp;
        } 
    }
    return s;
}

char *myitoa(int n, char s[])
{
    static const char digits[]="0123456789";
    int sign = n < 0;
    char *wrk = s;
    do
    {
        *wrk++ = digits[abs(n % 10)];
        n /= 10;
    }while(n);
    if(sign) *wrk++ = '-';
    *wrk = 0;
    reverse(s);
    return s;
}

int main(void)
{
    char buff[64];
    printf("%s\n", myitoa(INT_MIN, buff));
    printf("%s\n", myitoa(INT_MAX, buff));
    printf("%s\n", myitoa(0, buff));
}

https://godbolt.org/z/5so8chvcn

【讨论】:

  • 没有人关心其他编码,甚至 EBCDIC 也有相邻的数字(尽管不是字母)。
  • @o11c 有些人会这样做。
  • n* % 10 + '0' 不是很便携。 Wrong. 这保证在任何编码中产生n 的最低位。
  • @AndrewHenle 它只说字符集必须有从09 的数字,但没有说明顺序或代码。
  • @0___________ "在源基本字符集和执行基本字符集中,上述十进制数字列表中 0 之后的每个字符的值都应比前一个字符的值大一。"
【解决方案2】:

该函数旨在将整数转换为字符数组。将123-123 转换为字符有什么区别?好吧,除了负号之外,什么都没有。因此,itoa() 的这种实现基本上存储了符号,然后对数字本身进行操作,因为这些是主要的信息来源。最后,如果符号为负,则函数将- 字符附加到数组中,然后最后将其反转。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 2018-03-31
    • 2014-05-27
    • 2019-08-13
    • 2019-11-05
    • 2016-09-30
    相关资源
    最近更新 更多