在C中将字节数转换为文件大小

发布于 2024-09-26 23:33:08 字数 1004 浏览 0 评论 0原文

我想将单个字节数转换为文件大小(具有 .KB、.MB 和 .GB)。

如果数字是 0,我不想有任何单位。 如果该数字可以被 1024 的倍数整除(不是浮点数),那么我将打印: x 。否则,我想以一度精度打印浮点数。

我写了一些代码,看起来效果很好,但是很麻烦。我正在研究如何使我的功能更清洁/更高效,老实说,它非常丑陋:

char *
calculateSize( off_t size )
{
  char *result = (char *) malloc(sizeof(char) * 20);
  static int GB = 1024 * 1024 * 1024;
  static int MB = 1024 * 1024;
  static int KB = 1024;
  if (size >= GB) {
    if (size % GB == 0)
      sprintf(result, "%d GB", size / GB);
    else
      sprintf(result, "%.1f GB", (float) size / GB);
  }
  else if (size >= MB) {
    if (size % MB == 0)
      sprintf(result, "%d MB", size / MB);
    else
      sprintf(result, "%.1f MB", (float) size / MB);
  }
  else {
    if (size == 0) {
      result[0] = '0';
      result[1] = '\0';
    }
    else {
      if (size % KB == 0)
        sprintf(result, "%d KB", size / KB);
      else
        sprintf(result, "%.1f KB", (float) size / KB);
    }
  }
  return result;
}

如果有人有更好的方法来实现相同的结果,我将非常感激。

I want to convert a single number of bytes, into a file size (that has .KB, .MB and .GB).

If the number is 0, I don't want to have any unit.
If the number is exactly divisible by a multiple of 1024 (not a floating point), then I will print: x . Otherwise, I want to print a floating point with one degree precision.

I made some code that seems to work well, but it's very cumbersome. I'm looking into ways I could make my function cleaner/more efficient please, it's honestly VERY ugly:

char *
calculateSize( off_t size )
{
  char *result = (char *) malloc(sizeof(char) * 20);
  static int GB = 1024 * 1024 * 1024;
  static int MB = 1024 * 1024;
  static int KB = 1024;
  if (size >= GB) {
    if (size % GB == 0)
      sprintf(result, "%d GB", size / GB);
    else
      sprintf(result, "%.1f GB", (float) size / GB);
  }
  else if (size >= MB) {
    if (size % MB == 0)
      sprintf(result, "%d MB", size / MB);
    else
      sprintf(result, "%.1f MB", (float) size / MB);
  }
  else {
    if (size == 0) {
      result[0] = '0';
      result[1] = '\0';
    }
    else {
      if (size % KB == 0)
        sprintf(result, "%d KB", size / KB);
      else
        sprintf(result, "%.1f KB", (float) size / KB);
    }
  }
  return result;
}

I would really appreciate if someone has a better way to achieve the same result please.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

禾厶谷欠 2024-10-03 23:33:08

使用扩展到 EiB 的表驱动表示。

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DIM(x) (sizeof(x)/sizeof(*(x)))

static const char     *sizes[]   = { "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" };
static const uint64_t  exbibytes = 1024ULL * 1024ULL * 1024ULL *
                                   1024ULL * 1024ULL * 1024ULL;

char *
calculateSize(uint64_t size)
{   
    char     *result = (char *) malloc(sizeof(char) * 20);
    uint64_t  multiplier = exbibytes;
    int i;

    for (i = 0; i < DIM(sizes); i++, multiplier /= 1024)
    {   
        if (size < multiplier)
            continue;
        if (size % multiplier == 0)
            sprintf(result, "%" PRIu64 " %s", size / multiplier, sizes[i]);
        else
            sprintf(result, "%.1f %s", (float) size / multiplier, sizes[i]);
        return result;
    }
    strcpy(result, "0");
    return result;
}

测试代码

int main(void)
{   
    uint64_t list[] =
    {   
        0, 1, 2, 34, 900, 1023, 1024, 1025, 2048, 1024 * 1024, 
        1024 * 1024 * 1024 + 1024 * 1024 * 400
    };
    int i; 
    for (i = 0; i < DIM(list); i++)
    {   
        char *str = calculateSize(list[i]);
        printf("%18" PRIu64 " = %s\n", list[i], str);
        free(str);
    }
    return 0;
}

测试输出

                 0 = 0
                 1 = 1 B
                 2 = 2 B
                34 = 34 B
               900 = 900 B
              1023 = 1023 B
              1024 = 1 KiB
              1025 = 1.0 KiB
              2048 = 2 KiB
           1048576 = 1 MiB
        1493172224 = 1.4 GiB

Using a table-driven representation extended up to EiB.

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DIM(x) (sizeof(x)/sizeof(*(x)))

static const char     *sizes[]   = { "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" };
static const uint64_t  exbibytes = 1024ULL * 1024ULL * 1024ULL *
                                   1024ULL * 1024ULL * 1024ULL;

char *
calculateSize(uint64_t size)
{   
    char     *result = (char *) malloc(sizeof(char) * 20);
    uint64_t  multiplier = exbibytes;
    int i;

    for (i = 0; i < DIM(sizes); i++, multiplier /= 1024)
    {   
        if (size < multiplier)
            continue;
        if (size % multiplier == 0)
            sprintf(result, "%" PRIu64 " %s", size / multiplier, sizes[i]);
        else
            sprintf(result, "%.1f %s", (float) size / multiplier, sizes[i]);
        return result;
    }
    strcpy(result, "0");
    return result;
}

Test code

int main(void)
{   
    uint64_t list[] =
    {   
        0, 1, 2, 34, 900, 1023, 1024, 1025, 2048, 1024 * 1024, 
        1024 * 1024 * 1024 + 1024 * 1024 * 400
    };
    int i; 
    for (i = 0; i < DIM(list); i++)
    {   
        char *str = calculateSize(list[i]);
        printf("%18" PRIu64 " = %s\n", list[i], str);
        free(str);
    }
    return 0;
}

Test output

                 0 = 0
                 1 = 1 B
                 2 = 2 B
                34 = 34 B
               900 = 900 B
              1023 = 1023 B
              1024 = 1 KiB
              1025 = 1.0 KiB
              2048 = 2 KiB
           1048576 = 1 MiB
        1493172224 = 1.4 GiB
|煩躁 2024-10-03 23:33:08

我会使用表格方法。大致如下:

void
printsize(size_t  size)
{                   
    static const char *SIZES[] = { "B", "kB", "MB", "GB" };
    size_t div = 0;
    size_t rem = 0;

    while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) {
        rem = (size % 1024);
        div++;   
        size /= 1024;
    }

    printf("%.1f %s\n", (float)size + (float)rem / 1024.0, SIZES[div]);
}

I'd use a table approach. Something along the lines of:

void
printsize(size_t  size)
{                   
    static const char *SIZES[] = { "B", "kB", "MB", "GB" };
    size_t div = 0;
    size_t rem = 0;

    while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) {
        rem = (size % 1024);
        div++;   
        size /= 1024;
    }

    printf("%.1f %s\n", (float)size + (float)rem / 1024.0, SIZES[div]);
}
不即不离 2024-10-03 23:33:08

更好的方法是:

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

char *humanMemorySize(uint64_t bytes) {
    char *result = (char *) malloc(sizeof(char) * 20);
    char *sizeNames[] = { "B", "KB", "MB", "GB" };

    uint64_t i = (uint64_t) floor(log(bytes) / log(1024));
    double humanSize = bytes / pow(1024, i);
    snprintf(result, sizeof(char) * 20, "%g %s", humanSize, sizeNames[i]);

    return result;
}

必须释放函数的结果。

A nicer way would be:

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

char *humanMemorySize(uint64_t bytes) {
    char *result = (char *) malloc(sizeof(char) * 20);
    char *sizeNames[] = { "B", "KB", "MB", "GB" };

    uint64_t i = (uint64_t) floor(log(bytes) / log(1024));
    double humanSize = bytes / pow(1024, i);
    snprintf(result, sizeof(char) * 20, "%g %s", humanSize, sizeNames[i]);

    return result;
}

The result of the function must be freed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文