c - 您将如何在 Daily WTF 中实现被 mock 的功能?

标签 c coding-style

The Daily WTF对于 2008-11-28 手铐,以下代码:

static char *nice_num(long n)
{
    int neg = 0, d = 3;
    char *buffer = prtbuf;
    int bufsize = 20;

    if (n < 0)
    {
        neg = 1;
        n = -n;
    }
    buffer += bufsize;
    *--buffer = '\0';

    do
    {
        *--buffer = '0' + (n % 10);
        n /= 10;
        if (--d == 0)
        {
            d = 3;
            *--buffer = ',';
        }
    }
    while (n);

    if (*buffer == ',') ++buffer;
    if (neg) *--buffer = '-';
    return buffer;
}

你会怎么写?

最佳答案

如果您是一位经验丰富的 C 程序员,您会发现这段代码实际上并没有那么糟糕。它相对简单(对于 C),而且速度非常快。它存在三个问题:

  1. 它在 LONG_MIN (-2,147,483,648) 的边缘情况下失败,因为取反这个数字会在二进制补码中产生自身
    • 它假定 32 位整数 - 对于 64 位长整数,20 字节的缓冲区不够大
    • 它不是线程安全的 - 它使用全局静态缓冲区,因此多个线程同时调用它会导致竞争条件

问题 #1 很容易通过特殊情况解决。为了解决 #2,我将代码分成两个函数,一个用于 32 位整数,一个用于 64 位整数。 #3 有点难 - 我们必须更改接口(interface)以使其完全线程安全。

这是我的解决方案,基于此代码但经过修改以解决这些问题:

static int nice_num(char *buffer, size_t len, int32_t n)
{
  int neg = 0, d = 3;
  char buf[16];
  size_t bufsize = sizeof(buf);
  char *pbuf = buf + bufsize;

  if(n < 0)
  {
    if(n == INT32_MIN)
    {
      strncpy(buffer, "-2,147,483,648", len);
      return len <= 14;
    }

    neg = 1;
    n = -n;
  }

  *--pbuf = '\0';

  do
  {
    *--pbuf = '0' + (n % 10);
    n /= 10;
    if(--d == 0)
    {
      d = 3;
      *--pbuf = ',';
    }
  }
  while(n > 0);

  if(*pbuf == ',') ++pbuf;
  if(neg) *--pbuf = '-';

  strncpy(buffer, pbuf, len);
  return len <= strlen(pbuf);
}

说明:它在堆栈上创建一个本地缓冲区,然后用与初始代码相同的方法填充它。然后,它将它复制到传递给函数的参数中,确保不会溢出缓冲区。它还有一个 INT32_MIN 的特例。如果原始缓冲区足够大,则返回值为 0;如果缓冲区太小,结果字符串被截断,则返回值为 1。

关于c - 您将如何在 Daily WTF 中实现被 mock 的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/327216/

相关文章:

c# - Win32 资源编辑器库?

c - 由于某种原因,我的其他进程没有从我的第一个进程(C 中的 MPI)接收数据

c - Eclipse 转到标签在 C 中不起作用

JavaScript 样式 : which of these things should I pass as arguments to my namespace function?

python - 使就地操作返回对象是一个坏主意吗?

c++ - 尽可能多地维护 "const-ness"是个好主意吗?

c - 需要在函数前加上 (void)

c - 如何识别traceroute包?

使用 dup2 创建管道

javascript - 在 html 标签中使用组成的属性是否有任何可能的负面影响