-3

我正在寻找一种将人类可读的字节大小(例如:100、1k、2M、4G)解析为字节值的快速方法。输入是 a char *,输出必须是 a size_t(例如,无符号,可能是 64 位或 32 位整数,具体取决于架构)。代码应该检测到无效输入并返回一个值,表明它是无效输入。

例子:

Input  => size_t result
-----------------------
"100"  => 100
"10k"  => 10240
"2M"   => 2097152
"4G"   => 4294967296 on 64-bit machine, error (overflow) on 32-bit machine
"ten"  => error

这是一个示例代码片段,可以扩展以处理单元前缀:

int parse_human_readable_byte_size(char *input, size_t *result) {
    /* TODO: needs to support k, M, G, etc... */
    return sscanf("%zu", result) == 1;
}

以下是一些额外的要求:

  • 必须在 C 中完成(非 C++)
  • 仅使用标准库(或至少常用的)库(例如sscanf, atoi

该代码预计每次程序执行仅运行几次,因此更小的可读代码优于更长的高性能代码。

4

3 回答 3

4

这是一个潜在的实现。包括检测所有错误的代码;goto如果您愿意,请填写您自己的处理来代替s。

char *endp = s;
int sh;
errno = 0;
uintmax_t x = strtoumax(s, &endp, 10);
if (errno || endp == s) goto error;
switch(*endp) {
case 'k': sh=10; break;
case 'M': sh=20; break;
case 'G': sh=30; break;
case 0: sh=0; break;
default: goto error;
}
if (x > SIZE_MAX>>sh) goto error;
x <<= sh;
于 2013-04-19T15:22:19.590 回答
0

我将尝试使用一个按字符分析输入字符的子函数。

进一步进行明显的错误检查,我将使其转换数字常量中的符号,乘以对应于常量的基数。

于 2013-04-19T15:21:58.133 回答
0

根据接受的答案,我更新了截图。它支持浮点输入(如1.5k),支持十六进制输入(如0x55k),删除gotos并使用字符串作为单元列表以避免切换并使更新变得容易。

static char *human_readable_suffix = "kMGT";

size_t *parse_human_readable(char *input, size_t *target) {
    char *endp = input;
    char *match = NULL;
    size_t shift = 0;
    errno = 0;

    long double value = strtold(input, &endp);
    if(errno || endp == input || value < 0)
        return NULL;

    if(!(match = strchr(human_readable_suffix, *endp)))
        return NULL;

    if(*match)
        shift = (match - human_readable_suffix + 1) * 10;

    *target = value * (1LU << shift);

    return target;
}

以下是测试结果:

1337   =>           1337 [ok, expected: 1337]
857.54 =>            857 [ok, expected: 857]
128k   =>         131072 [ok, expected: 131072]
1.5k   =>           1536 [ok, expected: 1536]
8M     =>        8388608 [ok, expected: 8388608]
0x55   =>             85 [ok, expected: 85]
0x55k  =>          87040 [ok, expected: 87040]
1T     =>  1099511627776 [ok, expected: 1099511627776]
32.    =>             32 [ok, expected: 32]
-87    => error (expected)
abcd   => error (expected)
32x    => error (expected)

完整代码见:https ://gist.github.com/maxux/786a9b8bf55fb0696f7e31b8fa3f6b9d

于 2021-12-07T14:34:35.090 回答