嘿大家,只是一个快速的事情,我有十六进制到整数工作,但我需要将数字小写。这就是我所拥有的,任何想法让A至F F不敏感吗?

int htoi(char f[]) {
    int  z, n;
    n = 0;

    for (z = 0; f[z] >= '0' && f[z] <= 'F'; ++z) 
        if (f[z] >= 'A' && f[z] <= 'F')
            n = 10 + 16 * n + (f[z] - 'A');
        else
            n = 16 * n + (f[z] - '0');
}

可能只是一件小事,但我想加入a-f和A-F。谢谢你的帮助!

有帮助吗?

解决方案

如果你这样做是为了学习如何做,请忽略这篇文章。如果您正在使用此函数,因为您需要将十六进制数字的字符串转换为 int ,那么您应该在标准库中进行操作。标准函数 strtol() 转换字符串到 long ,可以转换为 int (或者 unsigned int )。第三个参数是转换为的基数 - 在这种情况下,您希望16进制十六进制。此外,如果给定基数为0,如果字符串以 0x 开头,则为半角形,如果以 0 开头,则为octal,否则为十进制。这是一个非常有用的功能。


编辑:注意到这一点,但是当我们在这里时,值得一提的是你通常不应该使用 int 来索引数组。 C标准定义了一种名为 size_t 的类型,用于存储数组索引。它通常是 unsigned int unsigned long 或其他东西,但保证足够大以存储您可以使用的任何数组或指针偏移量。

使用 int 的问题在于,理论上,有一天,某人可能会传递一个比 INT_MAX 更长的字符串,然后你的 int 将溢出,可能会回绕,并开始读取内存,它可能不应该因为它使用负索引。这是非常不可能的,特别是对于这样的函数,因为返回的 int 值会在 int 计数器溢出之前很久就会溢出,但它要记住一件重要的事情。

为了在技术上正确,你应该只使用 size_t 类型变量来索引数组,或者至少只使用 unsigned 类型,除非你真的想尝试访问否定元素(除非你知道你在做什么,这通常是一个坏主意)。但是,这不是一个大问题。

其他提示

创建另一个函数,将十六进制数字转换为整数:

int hex_digit_to_integer(char digit) {
    if (digit >= 'A' && digit <= 'F') {
        return digit - 'A' + 10;
    } else if (digit >= 'a' && digit <= 'f') {
        return digit - 'a' + 10;
    } else if (digit >= '0' && digit <= '9') {
        return digit - '0';
    }

    return -1; // Bad input.
}

注意它如何处理四种情况:  * digit 是一个大写字母 A..F ,  * digit 是一个小写字母 a..f ,  * digit 是十进制数字 0..9 ,和  * digit 不是上述内容。

现在在原始函数中使用新函数:

int htoi(char f[]) {
    int z, n;
    n = 0;

    /* Loop until we get something which isn't a digit (hex_digit_to_integer returns something < 0). */
    for (z=0; hex_digit_to_integer(f[z]) >= 0; ++z) {
        n = 16 * n + hex_digit_to_integer(f[z]);
    }
}

请注意新功能的清晰度是多少?

如果你喜欢冒险,你可以使用这个神奇的功能(它不能处理错误的输入,所以你需要事先检查一下):

int hex_digit_to_integer(char digit) {
    return digit - (digit & 64 ? 55 : 48) & 15;
}

用专用变量替换所有f [z]。使用toupper(f [z])

分配该变量

以下是NPS NSRL Bloom包中的一些代码:

static int *hexcharvals = 0;

/** Initialization function is used solely for hex output
 */
static void nsrl_bloom_init()
{
    if(hexcharvals==0){
        /* Need to initialize this */
        int i;
        hexcharvals = calloc(sizeof(int),256);
        for(i=0;i<10;i++){
            hexcharvals['0'+i] = i;
        }
        for(i=10;i<16;i++){
            hexcharvals['A'+i-10] = i;
            hexcharvals['a'+i-10] = i;
        }
    }
}

/**
 * Convert a hex representation to binary, and return
 * the number of bits converted.
 * @param binbuf output buffer
 * @param binbuf_size size of output buffer in bytes.
 * @param hex    input buffer (in hex)
 */
int nsrl_hex2bin(unsigned char *binbuf,size_t binbuf_size,const char *hex)
{
    int bits = 0;
    if(hexcharvals==0) nsrl_bloom_init();
    while(hex[0] && hex[1] && binbuf_size>0){
        *binbuf++ = ((hexcharvals[(unsigned char)hex[0]]<<4) |
                     hexcharvals[(unsigned char)hex[1]]);
        hex  += 2;
        bits += 8;
        binbuf_size -= 1;
    }
    return bits;
}

此代码设计为超快,处理大写和小写十六进制,并处理任意长度的十六进制字符串。函数nsrl_hex2bin()接受二进制缓冲区,该缓冲区的大小以及要转换的十六进制字符串。它返回实际转换的位数。

哦,如果你只想要一个整数,那么你可以乘以字节(对于与字节无关的代码),或者只是进行强制转换(对于依赖于字节的代码)。

您可以尝试 sscanf

#include <stdio.h>

...

//NOTE: buffer overflow if f is not terminated with \0 !!
int htoi(char f[]){
  int intval = -1;
  if (EOF == sscanf(f, "%x", &intval))
    return -1; //error
  return intval;
}

两个选项:

在进行扫描之前转换为大写。

在处理小写的四个循环中添加第二个if。

请改为尝试:

int htoi (char f[]) {
    int  z, n;
    n = 0;
    for (z = 0; f[z] != '\0'; ++z) { 
        if (f[z] >= '0' && f[z] <= '9') {
            n = n * 16 + f[z] - '0';
        } else {
            if (f[z] >= 'A' && f[z] <= 'F') {
                n = n * 16 + f[z] - 'A' + 10;
            } else {
                if (f[z] >= 'a' && f[z] <= 'f') {
                    n = n * 16 + f[z] - 'a' + 10;
                } else {
                    break;
                }
            }
        }
    }
    return n;
}

它仍然以与你相同的方式处理输入(我倾向于使用指针,但它们有时很难被初学者理解)但引入了三个独立的情况,0-9,AF和af,适当地处理每个。

您的原始代码实际上会允许错误的字符('9'和'A'之间的六个字符)并根据它们产生不正确的结果。

请注意,此新代码通常仅在字符串结尾处终止循环。找到无效的十六进制字符将突破循环,在功能上与终止条件相同。

请使用strtol()。这是标准的C90功能,比大多数天真的实现功能强大得多。它还支持从dec(无前缀),十六进制(0x)和oct(从0开始)的无缝转换。

使用shift旋转而不是乘法实现。

int HexToDec(char *Number)
{

    unsigned int val = 0;

    int i , nibble;
    for(i = strlen( Number ) - 1; i >= 0; --i, nibble += 4)
    {
        const char hex = Number[i];
        if (hex >= '0' && hex <= '9')
            val += (hex - '0')<<nibble;
        else if (hex >= 'A' && hex <= 'F')
            val += (hex - 'A' + 10)<<nibble;
        else if (hex >= 'a' && hex <= 'f')
            val += (hex - 'a' + 10)<<nibble;
        else
            return -1;
    }
    return val;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top