首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >itoa函数的改进

itoa函数的改进
EN

Code Review用户
提问于 2021-03-20 04:50:49
回答 1查看 296关注 0票数 2

我写了一个伊藤忠雄昨天,它基于我现在正在改进的反馈。下面的情况如何?有什么办法可以改进吗?

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>
#include <limits.h>

char* itoa(int number, size_t sz, char buffer[sz])
{
    // do error handling and edge cases
    if (buffer == NULL || sz == 0)
        return NULL;
    else if (number == 0) 
        return strcpy(buffer, "0");

    char tmp[sz];
    int idx = 0;
    bool is_negative = (number < 0);
    if (!is_negative) number = -number; // so we can handle INT_MIN

    for (; number != 0; number/=10, idx++) {
        if (sz-- == 0) return NULL;
        tmp[idx] = '0' - (number % 10); // negative version of number + '0'
    }
    if (is_negative) {
        if (sz-- == 0) return NULL;
        tmp[idx++] = '-';
    }

    // reverse
    for (int i=0; i<idx; i++)
        buffer[idx-i-1] = tmp[i];
    buffer[idx] = '\0';
    return buffer;
}


int main(void)
{
    char buffer[100];
    int test[] = {123, 234, 0, 17, -4, -7, -17, -27, INT_MAX, INT_MIN};
    size_t len = sizeof(test) / sizeof(*test);
    
    // give it a small buffer and see how it works
    for (int i=0, num; i < len; i++) {
        num = test[i];
        char* str = itoa(num, 2, buffer); 
        printf("%-10d <%s>\n", num, str);
    }
    
    // now give it the correctly-sized buffer
    for (int i=0, num; i < len; i++) {
        num = test[i];
        char* str = itoa(num, sizeof buffer / sizeof *buffer, buffer);
        printf("%-10d <%s>\n", num, str);
    }
}

这里的工作代码:https://onlinegdb.com/H1xKCemNu。有关这方面的几个问题:

  • 对于用C编写的最琐碎的函数,似乎有那么多的边缘情况需要考虑。例如,上面的函数花了我大约两个小时(在@chux的一些非常有用的反馈之后)。这是编写C代码时常见的问题吗?或者说,这是一个更初学者的问题,将随着经验的消失?
  • 使用for循环时,我经常会发现自己被一个错误咬了,例如,没有实现idx在前一个循环之后增加,但在下一个循环被检查之前。有什么特别的方法来注意这个吗?
  • 这里还有什么地方需要改进吗?
EN

回答 1

Code Review用户

回答已采纳

发布于 2021-03-20 07:04:27

不正确的大小检查

itoa(num, 2, buffer);窗体"17",它需要3 char,尽管只提供了2。

也许OP意味着2是允许的字符串长度,而不是所需的字符串大小。在这种情况下,sizeof buffer / sizeof *buffer不是允许的长度。

缺失标头

添加#include <stdbool.h>

缺失大小检查

角情况:即使是strcpy(buffer, "0");,也会发生sz == 1

缓冲区溢出问题的一个简单替代方法是在本地缓冲区中形成初始字符,该缓冲区的大小适合最坏情况(INT_MIN),如char local_buf[12]。检查idxsz。然后倒转到真正的目的地。

代码语言:javascript
复制
// Re-write end-of-code.
// ....
// Prior code does not check `sz` nor change sz as characters are saved in ample sized local_buf

if (idx + 1 > sz) {
  if (sz > 0) buffer[0] = 0;  // Set buffer[] to "" if possible
  return NULL;
}

for (int i=0; i<idx; i++)
    buffer[idx-i-1] = local_buf[i];
buffer[idx] = '\0';
return buffer;

12使用代码来扩展到所需的大小,而不是硬代码。例如。

代码语言:javascript
复制
// Scale by log10(2)
#define INT_STR_SZ (sizeof(int)*CHAR_BIT*301030/1000000 + 3)
char local_buf[INT_STR_SZ];
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/257428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档