首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于int128_t类型的atoi()

用于int128_t类型的atoi()
EN

Stack Overflow用户
提问于 2017-08-10 16:33:00
回答 2查看 3.5K关注 0票数 16

如何在int128_t支持下使用argv值?我知道atoi()<cstdlib>公开的一系列函数,但不知何故我找不到一个用于int128_t固定宽度整数的函数。这可能是因为这个type不受c或c++标准的支持,但是有没有办法让我的代码工作呢?

代码语言:javascript
复制
#include <iostream>

int main(int argc, char **argv) {
    __int128_t value = atoint128_t(argv[1]);
}

几乎所有张贴的答案对我来说都足够好,但我选择的是针对我当前代码的逐个解决方案,所以也要看看其他的。

EN

回答 2

Stack Overflow用户

发布于 2017-08-11 01:20:56

下面是一种简单的实现方法:

代码语言:javascript
复制
__int128_t atoint128_t(const char *s)
{
    const char *p = s;
    __int128_t val = 0;

    if (*p == '-' || *p == '+') {
        p++;
    }
    while (*p >= '0' && *p <= '9') {
        val = (10 * val) + (*p - '0');
        p++;
    }
    if (*s == '-') val = val * -1;
    return val;
}

该代码检查每个字符是否为数字(带有可选的前导+或-),如果是,则将当前结果乘以10,并将与该数字相关联的值相加。然后,如果需要,它会反转符号。

请注意,此实现不会检查溢出,这与atoi的行为一致。

编辑:

通过根据符号添加或减去每个数字的值并跳过前导空格,修改了覆盖int128_MIN情况的实现。

代码语言:javascript
复制
int myatoi(const char *s)
{
    const char *p = s;
    int neg = 0, val = 0;

    while ((*p == '\n') || (*p == '\t') || (*p == ' ') ||
           (*p == '\f') || (*p == '\r') || (*p == '\v')) {
        p++;
    }
    if ((*p == '-') || (*p == '+')) {
        if (*p == '-') {
            neg = 1;
        }
        p++;
    }
    while (*p >= '0' && *p <= '9') {
        if (neg) {
            val = (10 * val) - (*p - '0');
        } else {
            val = (10 * val) + (*p - '0');
        }
        p++;
    }
    return val;
}
票数 3
EN

Stack Overflow用户

发布于 2017-08-11 22:15:21

C标准不强制支持128位整数。

然而,现代编译器通常都支持它们:gccclang都支持__int128_t__uint128_t类型,但令人惊讶的是,它们仍然将intmax_tuintmax_t限制为64位。

除了基本的算术运算符之外,没有太多对这些大整数的支持,特别是在C库中:没有scanf()printf()转换说明符等。

下面是一个strtoi128()strtou128()atoi128()的实现,它与C标准的atoi()strtol()strtoul()规范一致。

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

/* Change these typedefs for your local flavor of 128-bit integer types */
typedef __int128_t i128;
typedef __uint128_t u128;

static int strdigit__(char c) {
    /* This is ASCII / UTF-8 specific, would not work for EBCDIC */
    return (c >= '0' && c <= '9') ? c - '0'
        :  (c >= 'a' && c <= 'z') ? c - 'a' + 10
        :  (c >= 'A' && c <= 'Z') ? c - 'A' + 10
        :  255;
}

static u128 strtou128__(const char *p, char **endp, int base) {
    u128 v = 0;
    int digit;

    if (base == 0) {    /* handle octal and hexadecimal syntax */
        base = 10;
        if (*p == '0') {
            base = 8;
            if ((p[1] == 'x' || p[1] == 'X') && strdigit__(p[2]) < 16) {
                p += 2;
                base = 16;
            }
        }
    }
    if (base < 2 || base > 36) {
        errno = EINVAL;
    } else
    if ((digit = strdigit__(*p)) < base) {
        v = digit;
        /* convert to unsigned 128 bit with overflow control */
        while ((digit = strdigit__(*++p)) < base) {
            u128 v0 = v;
            v = v * base + digit;
            if (v < v0) {
                v = ~(u128)0;
                errno = ERANGE;
            }
        }
        if (endp) {
            *endp = (char *)p;
        }
    }
    return v;
}

u128 strtou128(const char *p, char **endp, int base) {
    if (endp) {
        *endp = (char *)p;
    }
    while (isspace((unsigned char)*p)) {
        p++;
    }
    if (*p == '-') {
        p++;
        return -strtou128__(p, endp, base);
    } else {
        if (*p == '+')
            p++;
        return strtou128__(p, endp, base);
    }
}

i128 strtoi128(const char *p, char **endp, int base) {
    u128 v;

    if (endp) {
        *endp = (char *)p;
    }
    while (isspace((unsigned char)*p)) {
        p++;
    }
    if (*p == '-') {
        p++;
        v = strtou128__(p, endp, base);
        if (v >= (u128)1 << 127) {
            if (v > (u128)1 << 127)
                errno = ERANGE;
            return -(i128)(((u128)1 << 127) - 1) - 1;
        }
        return -(i128)v;
    } else {
        if (*p == '+')
            p++;
        v = strtou128__(p, endp, base);
        if (v >= (u128)1 << 127) {
            errno = ERANGE;
            return (i128)(((u128)1 << 127) - 1);
        }
        return (i128)v;
    }
}

i128 atoi128(const char *p) {
    return strtoi128(p, (char**)NULL, 10);
}

char *utoa128(char *dest, u128 v, int base) {
    char buf[129];
    char *p = buf + 128;
    const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    *p = '\0';
    if (base >= 2 && base <= 36) {
        while (v > (unsigned)base - 1) {
            *--p = digits[v % base];
            v /= base;
        }
        *--p = digits[v];
    }
    return strcpy(dest, p);
}

char *itoa128(char *buf, i128 v, int base) {
    char *p = buf;
    u128 uv = (u128)v;
    if (v < 0) {
        *p++ = '-';
        uv = -uv;
    }
    if (base == 10)
        utoa128(p, uv, 10);
    else
    if (base == 16)
        utoa128(p, uv, 16);
    else
        utoa128(p, uv, base);
    return buf;
}

static char *perrno(char *buf, int err) {
    switch (err) {
    case EINVAL:
        return strcpy(buf, "EINVAL");
    case ERANGE:
        return strcpy(buf, "ERANGE");
    default:
        sprintf(buf, "%d", err);
        return buf;
    }
}

int main(int argc, char *argv[]) {
    char buf[130];
    char xbuf[130];
    char ebuf[20];
    char *p1, *p2;
    i128 v, v1;
    u128 v2;
    int i;

    for (i = 1; i < argc; i++) {
        printf("%s:\n", argv[i]);
        errno = 0;
        v = atoi128(argv[i]);
        perrno(ebuf, errno);
        printf("  atoi128():   %s  0x%s  errno=%s\n",
               itoa128(buf, v, 10), utoa128(xbuf, v, 16), ebuf);
        errno = 0;
        v1 = strtoi128(argv[i], &p1, 0);
        perrno(ebuf, errno);
        printf("  strtoi128(): %s  0x%s  endptr:\"%s\"  errno=%s\n",
               itoa128(buf, v1, 10), utoa128(xbuf, v1, 16), p1, ebuf);
        errno = 0;
        v2 = strtou128(argv[i], &p2, 0);
        perrno(ebuf, errno);
        printf("  strtou128(): %s  0x%s  endptr:\"%s\"  errno=%s\n",
               utoa128(buf, v2, 10), utoa128(xbuf, v2, 16), p2, ebuf);
    }
    return 0;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45608424

复制
相关文章

相似问题

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